diff --git a/.claude/skills/testing/SKILL.md b/.claude/skills/testing/SKILL.md index 37c8081c..5b4070a1 100644 --- a/.claude/skills/testing/SKILL.md +++ b/.claude/skills/testing/SKILL.md @@ -37,10 +37,12 @@ test/ ### Organization Rules - Tests for `RuleEngine` go in `test/RuleEngine/` +- Tests for each ERC-2771 contract go in its own directory: `test/RuleEngine2771/`, `test/RuleEngineOwnable2771/`, `test/RuleEngineOwnable2Step2771/` - Tests for `RuleEngineOwnable` go in `test/RuleEngineOwnable/` +- Tests for `RuleEngineOwnable2Step` go in `test/RuleEngineOwnable2Step/` - Shared test logic uses `*Base.sol` abstract contracts with virtual hooks - Test files use `.t.sol` suffix; base/helper files use `.sol` -- **Both variants must be tested.** When adding a feature to `RuleEngineBase`, add tests in both `test/RuleEngine/` and `test/RuleEngineOwnable/`. +- **Every variant must be tested.** When adding a feature to `RuleEngineBase`, add tests for all six deployables, preferably through a shared `test/utils/*TestBase.sol` with one short file per variant directory. ## Helper Contracts @@ -176,8 +178,7 @@ contract MyFeatureTest is Test, HelperContract { ruleWhitelist = new RuleWhitelist(DEFAULT_ADMIN_ADDRESS, ZERO_ADDRESS); ruleEngineMock = new RuleEngine( DEFAULT_ADMIN_ADDRESS, - ZERO_ADDRESS, // forwarder - ZERO_ADDRESS // token (bound later) + ZERO_ADDRESS // token (bound later); use RuleEngine2771 to test a forwarder ); } diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 56c12414..641fab80 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -25,7 +25,11 @@ jobs: - name: Run Forge tests run: forge test -vvv - + + # test/ERC3643Real/ is skipped by the default profile: it deploys the vendored T-REX token (solc 0.8.30) + - name: Run Forge tests against the real ERC-3643 token + run: FOUNDRY_PROFILE=erc3643 forge test -vvv + - name: Setup NodeJS 20.5.0 uses: actions/setup-node@49933ea5288caeca8642d1e84afbd3f7d6820020 #v4.4.0 with: diff --git a/.gitignore b/.gitignore index f8d680ea..6cfce4aa 100644 --- a/.gitignore +++ b/.gitignore @@ -19,8 +19,7 @@ cache_hardhat/ *.dtmp #claude history -INSTRUCTION.md -PLAN.md -SUMMARY.md -FEEDBACK.md +draft .codex +out-erc3643/ + diff --git a/.gitmodules b/.gitmodules index 3d4fedd5..abbc8972 100644 --- a/.gitmodules +++ b/.gitmodules @@ -16,3 +16,6 @@ [submodule "ERC-3643"] path = lib/ERC-3643 url = https://github.com/ERC-3643/ERC-3643 +[submodule "lib/Rules"] + path = lib/Rules + url = https://github.com/CMTA/Rules diff --git a/AGENTS.md b/AGENTS.md index f64b8dc3..9a100082 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -8,9 +8,9 @@ AGENTS.md and CLAUDE.md files must always be identical — always update both to **RuleEngine** is a Solidity smart contract system that enforces transfer restrictions for [CMTAT](https://github.com/CMTA/CMTAT) and [ERC-3643](https://eips.ethereum.org/EIPS/eip-3643) tokens. It acts as an external controller that calls pluggable rule contracts on each token transfer, mint, or burn. -- **Version:** 3.0.0 (defined in `src/modules/VersionModule.sol`) -- **Solidity:** ^0.8.20 (compiled with 0.8.36) -- **EVM target:** Prague +- **Version:** 3.0.0-rc7 (defined in `src/modules/VersionModule.sol`; the string carries the release-candidate suffix and must be bumped with each tag — update the `version()` assertions in `test/RuleEngine/RuleEngineDeployment.t.sol`, `test/utils/ERC2771VariantTestBase.sol`, `test/RuleEngineOwnable/RuleEngineOwnableDeployment.t.sol`, `test/RuleEngineOwnable2Step/RuleEngineOwnable2Step.t.sol` and `test/hardhat/RuleEngine.smoke.js` with it) +- **Solidity:** ^0.8.27 (compiled with 0.8.37). `src/` and `script/` declare `^0.8.27`: it is the first version that supports `require(cond, CustomError())` on the legacy pipeline, so do not lower it +- **EVM target:** Osaka (Fusaka upgrade) - **License:** MPL-2.0 ## Build & Test Commands @@ -23,10 +23,18 @@ forge test --match-contract --match-test # Run specific test forge coverage # Code coverage forge coverage --no-match-coverage "(mocks|test)" --report lcov # Production coverage (src/ + script/) forge fmt # Format code +FOUNDRY_PROFILE=erc3643 forge test # Real ERC-3643 token suite (test/ERC3643Real/, solc 0.8.30) +FOUNDRY_INVARIANT_RUNS=256 FOUNDRY_INVARIANT_DEPTH=500 forge test --match-contract InvariantTest # deeper invariant run (foundry.toml caps it at 64 x 50) ``` -Dependencies are git submodules. Initialize with `forge install`, update with `forge update`. -CMTAT submodule also needs `cd lib/CMTAT && npm install` for its OpenZeppelin deps. +`test/ERC3643Real/` deploys the vendored T-REX 4.2.0-beta1 `Token`, which pins `pragma solidity 0.8.30`. It is +skipped by the default profile and built by `[profile.erc3643]` (solc 0.8.30, `out-erc3643/`, context-scoped +`@onchain-id` remapping to the stubs in `test/utils/onchainid/`). Files there must pin `pragma solidity 0.8.30`. +Never move the context-scoped remapping into `remappings.txt`: `hardhat-foundry` rejects it. + +Dependencies are git submodules. Initialize with `git submodule update --init` (non-recursive is enough), update with `forge update`. +`remappings.txt` resolves `@openzeppelin/...` to this repo's own submodules for every file, including the CMTAT sources, +so `cd lib/CMTAT && npm install` and `--recursive` are only needed to run CMTAT's own Hardhat suite. ## Agent Workflow @@ -54,21 +62,24 @@ Use `@openzeppelin/contracts/` for OpenZeppelin imports and `CMTAT/` for CMTAT i ## Architecture -### Three Deployable Contracts +### Six Deployable Contracts ``` -RuleEngine — RBAC via AccessControl (multi-operator) -RuleEngineOwnable — ERC-173 Ownable (single-owner) -RuleEngineOwnable2Step — ERC-173 Ownable2Step (single-owner, two-step handover) +RuleEngine — RBAC via AccessControl (multi-operator), no ERC-2771 +RuleEngine2771 — RBAC via AccessControl + ERC-2771 (immutable trusted forwarder) +RuleEngineOwnable — ERC-173 Ownable (single-owner), no ERC-2771 +RuleEngineOwnable2771 — ERC-173 Ownable + ERC-2771 +RuleEngineOwnable2Step — ERC-173 Ownable2Step (single-owner, two-step handover), no ERC-2771 +RuleEngineOwnable2Step2771 — ERC-173 Ownable2Step + ERC-2771 ``` -All three share their core logic through `RuleEngineBase` directly or via `RuleEngineOwnableShared`. +All six share their core logic through `RuleEngineBase`: `RuleEngine` extends it directly with RBAC, and the four ownable variants go through `RuleEngineOwnableShared`. Each access-control model has a version without ERC-2771 (constructor `(admin|owner_, tokenContract)`) and a `*2771` version with an immutable trusted forwarder (constructor `(admin|owner_, forwarderIrrevocable, tokenContract)`). Every `X2771` extends its counterpart `X` (`RuleEngine2771 is ERC2771ModuleStandalone, RuleEngine`, and likewise for the ownable pair) and adds only `ERC2771ModuleStandalone` plus the three `Context` overrides. The deployables live in `src/deployment/accessControl/` (RBAC) and `src/deployment/ownable/` (ERC-173). ### Inheritance Hierarchy ``` RuleEngineBase (abstract) -├── VersionModule → version() returns "3.0.0" +├── VersionModule → version() returns "3.0.0-rc7" ├── RulesManagementModule → add/remove/set/clear rules, maxRules cap │ ├── AccessControl (OZ) │ └── RulesManagementModuleInvariantStorage → errors, events, roles @@ -83,21 +94,32 @@ RuleEngineBase (abstract) ├── RuleEngineInvariantStorage → errors └── IRuleEngineERC1404 → CMTAT interface -RuleEngine +RuleEngine → no gasless support +├── RuleEngineBase +├── AccessControlEnumerable (OZ) +└── ERC3643ComplianceRolesStorage, RulesManagementModuleRolesStorage → roles + +RuleEngine2771 ├── ERC2771ModuleStandalone → gasless support -└── RuleEngineBase +└── RuleEngine RuleEngineOwnable -├── ERC2771ModuleStandalone → gasless support -├── RuleEngineOwnableShared +├── RuleEngineOwnableShared → no gasless support │ └── RuleEngineBase └── Ownable (OZ) → ERC-173 -RuleEngineOwnable2Step +RuleEngineOwnable2771 ├── ERC2771ModuleStandalone → gasless support -├── RuleEngineOwnableShared +└── RuleEngineOwnable + +RuleEngineOwnable2Step +├── RuleEngineOwnableShared → no gasless support │ └── RuleEngineBase └── Ownable2Step (OZ) → ERC-173 + +RuleEngineOwnable2Step2771 +├── ERC2771ModuleStandalone → gasless support +└── RuleEngineOwnable2Step ``` ### Access Control Pattern @@ -114,7 +136,7 @@ function _onlyTokenBindingManager() internal virtual; // wired by ERC3643ComplianceModule to its own abstract hook: function _onlyComplianceManager() internal virtual; -// RuleEngine overrides with RBAC: +// RuleEngine (and RuleEngine2771, which extends it) overrides with RBAC: function _onlyRulesManager() internal virtual override onlyRole(RULES_MANAGEMENT_ROLE) {} function _onlyRulesLimitManager() internal virtual override onlyRole(DEFAULT_ADMIN_ROLE) {} function _onlyComplianceManager() internal virtual override onlyRole(COMPLIANCE_MANAGER_ROLE) {} @@ -131,21 +153,29 @@ function _onlyComplianceManager() internal virtual override onlyOwner {} Rule validation uses a two-layer override: -1. **`RulesManagementModule._checkRule()`** — checks zero address + duplicates +1. **`RulesManagementModule._checkRule()`** — checks the zero address (duplicates are rejected by `_addRule` through the return value of `_rules.add`) 2. **`RuleEngineBase._checkRule()`** — calls `RulesManagementModule._checkRule()` then validates ERC-165 interface ```solidity // RulesManagementModule (generic checks): function _checkRule(address rule_) internal view virtual { - if (rule_ == address(0x0)) revert ...ZeroNotAllowed(); - if (_rules.contains(rule_)) revert ...AlreadyExists(); + require(rule_ != address(0), RuleEngine_RulesManagementModule_RuleAddressZeroNotAllowed()); } +// RulesManagementModule._addRule (duplicate check): +require(_rules.add(address(rule_)), RuleEngine_RulesManagementModule_RuleAlreadyExists()); + // RuleEngineBase (adds ERC-165 check): function _checkRule(address rule_) internal view virtual override { RulesManagementModule._checkRule(rule_); - if (!ERC165Checker.supportsInterface(rule_, RuleInterfaceId.IRULE_INTERFACE_ID)) - revert RuleEngine_RuleInvalidInterface(); + require(_supportsRuleInterface(rule_), RuleEngine_RuleInvalidInterface()); +} + +// ERC-165 support checked once, then the current IRule ID, then the legacy (pre-rc7) one: +function _supportsRuleInterface(address rule_) internal view virtual returns (bool) { + if (!ERC165Checker.supportsERC165(rule_)) return false; + return ERC165Checker.supportsERC165InterfaceUnchecked(rule_, RuleInterfaceId.IRULE_INTERFACE_ID) + || ERC165Checker.supportsERC165InterfaceUnchecked(rule_, RuleInterfaceId.IRULE_LEGACY_INTERFACE_ID); } ``` @@ -214,7 +244,7 @@ This gives O(1) add/remove/contains and iterable storage. | Interface | Purpose | Where Defined | |-----------|---------|---------------| -| `IRule` | What every rule must implement (extends `IRuleEngineERC1404`) | `src/interfaces/IRule.sol` | +| `IRule` | What every rule must implement: the six functions the engine calls + ERC-165 (extends `IERC1404Extend`, `IERC3643IComplianceContract`, `IERC165`; no `canTransfer*`) | `src/interfaces/IRule.sol` | | `IRulesManagementModule` | Rule CRUD operations | `src/interfaces/IRulesManagementModule.sol` | | `ITokenBinding` | Token binding registry, standard-agnostic | `src/interfaces/ITokenBinding.sol` | | `ITokenBindingExtended` | Batch binding, token self-binding, `getTokenBounds` | `src/interfaces/ITokenBindingExtended.sol` | @@ -222,7 +252,7 @@ This gives O(1) add/remove/contains and iterable storage. | `IRuleEngine` | Full CMTAT integration interface | `lib/CMTAT/contracts/interfaces/engine/IRuleEngine.sol` | **ERC-165 interface IDs:** -- `IRule`: `0x2497d6cb` (`src/modules/library/RuleInterfaceId.sol`) +- `IRule`: `0xb1a69752` (`src/modules/library/RuleInterfaceId.sol`). Narrowed in rc7 (was `0x2497d6cb`, which also covers `canTransfer` / `canTransferFrom`); the engine accepts both, the legacy one as `IRULE_LEGACY_INTERFACE_ID` (`RuleEngineBase._supportsRuleInterface`) - `IERC3643Compliance`: `0x3144991c`, extended: `0x646ba2be`, `IERC7551Compliance`: `0x7157797f` (`ComplianceInterfaceId.sol`) - `IERC1404`: `0xab84a5c8` (`ERC1404InterfaceId.sol`) - `IRuleEngine`: from `CMTAT/library/RuleEngineInterfaceId.sol` @@ -253,9 +283,14 @@ Errors, events, and role constants are centralized in "invariant storage" abstra ``` src/ ├── deployment/ -│ ├── RuleEngine.sol # RBAC variant (deploy this) -│ ├── RuleEngineOwnable.sol # Ownable variant (deploy this) -│ └── RuleEngineOwnable2Step.sol # Ownable2Step variant (deploy this) +│ ├── accessControl/ +│ │ ├── RuleEngine.sol # RBAC variant, no ERC-2771 (deploy this) +│ │ └── RuleEngine2771.sol # RBAC variant with ERC-2771 (deploy this) +│ └── ownable/ +│ ├── RuleEngineOwnable.sol # Ownable variant, no ERC-2771 (deploy this) +│ ├── RuleEngineOwnable2771.sol # Ownable variant with ERC-2771 (deploy this) +│ ├── RuleEngineOwnable2Step.sol # Ownable2Step variant, no ERC-2771 (deploy this) +│ └── RuleEngineOwnable2Step2771.sol # Ownable2Step variant with ERC-2771 (deploy this) ├── RuleEngineBase.sol # Abstract core logic (do not deploy) ├── RuleEngineOwnableShared.sol # Shared logic for ownable variants ├── interfaces/ # IRule, IRulesManagementModule, ITokenBinding(Extended), IERC3643Compliance(Extended) @@ -270,8 +305,13 @@ test/ ├── HelperContractOwnable2Step.sol # Base helper for RuleEngineOwnable2Step tests ├── utils/ # CMTAT deployment helpers ├── RuleEngine/ # Tests for RuleEngine (RBAC) +├── RuleEngine2771/ # Tests for RuleEngine2771 (RBAC + ERC-2771) ├── RuleEngineOwnable/ # Tests for RuleEngineOwnable ├── RuleEngineOwnable2Step/ # Tests for RuleEngineOwnable2Step +├── RuleEngineOwnable2771/ # Tests for RuleEngineOwnable2771 +├── RuleEngineOwnable2Step2771/ # Tests for RuleEngineOwnable2Step2771 +├── ERC3643Real/ # Real T-REX token tests (FOUNDRY_PROFILE=erc3643 only) +├── RuleStandalone/ # A rule set directly as a CMTAT token's rule engine (no RuleEngine) └── RuleWhitelist/ # Tests for the whitelist mock rule script/ # Foundry example/deployment scripts @@ -284,12 +324,15 @@ For detailed test conventions, templates, helper contracts, test addresses, nami Key points: - Tests for `RuleEngine` go in `test/RuleEngine/`, tests for `RuleEngineOwnable` go in `test/RuleEngineOwnable/` - Tests for `RuleEngineOwnable2Step` go in `test/RuleEngineOwnable2Step/` +- Tests for each `*2771` contract go in its own `test//` directory (`RuleEngine2771`, `RuleEngineOwnable2771`, `RuleEngineOwnable2Step2771`) - Use `HelperContract` for RBAC tests, `HelperContractOwnable` for Ownable tests - Use `HelperContractOwnable2Step` for `RuleEngineOwnable2Step` tests - Always use specific error selectors in `vm.expectRevert()` - When adding a feature to `RuleEngineBase`, add tests for **all deployable variants** +- Behaviour shared by the variants is tested once in an abstract base under `test/utils/` (`ERC2771TokenGateTestBase`, `ERC2771VariantTestBase`, `NoForwarderTestBase`, `RuleAggregationTestBase`, `RuleEngineInvariantTestBase`), with a short per-variant file in each `test/RuleEngine*/` directory that only deploys the variant +- Before trusting a new test, check it can fail: break the line it guards and run the suite (the rc7 code-quality review mutation-tests the suite this way) -## RBAC Roles (RuleEngine only) +## RBAC Roles (RuleEngine and RuleEngine2771) | Role | Identifier | Purpose | |------|-----------|---------| @@ -300,12 +343,14 @@ Key points: ## Key Invariants 1. **Only bound tokens** can call `transferred()`, `created()`, `destroyed()` -2. **Rules are validated via ERC-165** before being added — they must support `IRULE_INTERFACE_ID` +2. **Rules are validated via ERC-165** before being added — they must support `IRULE_INTERFACE_ID` or the legacy `IRULE_LEGACY_INTERFACE_ID` 3. **No duplicate rules** — `EnumerableSet` prevents this 4. **No zero-address rules** — checked in `_checkRule` -5. **Admin has all roles** in `RuleEngine` (the `hasRole` override) -6. **Forwarder is immutable** — set at construction, cannot be changed -7. **Rule contracts in `src/mocks/` are reference implementations** — they are useful for testing and examples, not as production rule contracts. Production rules live in a [separate repository](https://github.com/CMTA/Rules). +5. **Admin has all roles** in `RuleEngine` and `RuleEngine2771` (the `hasRole` override in `RuleEngine`, inherited by `RuleEngine2771`) +6. **Forwarder is immutable** — set at construction, cannot be changed (the three `*2771` contracts; the others have none) +7. **Token identity uses `msg.sender`, never `_msgSender()`** — `_checkBoundToken` (`onlyBoundToken`) and the token self-binding check in `_authorizeTokenBindingChange` compare the raw caller so the ERC-2771 forwarder cannot pass as a token; administrative checks keep `_msgSender()` (gasless admin). Pinned by `test/utils/ERC2771TokenGateTestBase.sol` +8. **Rules and bound tokens are disjoint** — `RuleEngineBase._checkBindingTarget` rejects binding a current rule and `_checkRule` rejects adding a bound token as a rule, both with `RuleEngine_RulesManagementModule_RuleAccountCannotReceivePrivileges`. Pinned by `invariant_RulesAndBoundTokensAreDisjoint` +9. **Rule contracts in `src/mocks/` are reference implementations** — they are useful for testing and examples, not as production rule contracts. Production rules live in a [separate repository](https://github.com/CMTA/Rules). ## Solidity Style @@ -314,7 +359,7 @@ Key points: - Function ordering: constructor, receive, fallback, external, public, internal, private (view/pure last within each group) - Function declaration order: visibility, mutability, virtual, override, custom modifiers - All `internal` functions must be marked `virtual`, so inheriting contracts can override them. -- Use `require(condition, CustomError(...))` for custom errors; avoid direct `revert CustomError(...)`. +- Use `require(condition, CustomError(...))` for custom errors; avoid direct `revert CustomError(...)`. `src/` has no conditional `revert` left (the only two are the unconditional ones of `RuleOperationRevertMock`). Note that `require` evaluates the error's arguments even when the check passes: an argument read from storage costs an extra read, so cache it in a local first (see `RulesManagementModule.addRule`). - In `src/`, avoid `super` calls and prefer explicit parent-contract calls (e.g., `AccessControl.grantRole(...)`) for readability and deterministic inheritance behavior. - Section headers: `/* ============ SECTION ============ */` - **No emoji in code comments or NatSpec.** Use a plain word marker instead: `WARNING:`, `NOTE:`, `IMPORTANT:`. Emoji render inconsistently across editors, terminals, `forge doc` output and diffs; they are not searchable (`grep WARNING` finds the marker, `grep ⚠️` depends on the shell); and they encode as multi-byte sequences that can be silently mangled by tooling. This applies to `src/`, `test/` and `script/`. Markdown documentation may use emoji freely — the restriction is Solidity comments only. @@ -327,16 +372,17 @@ Key points: 2. Create an invariant storage contract in `src/modules/library/` for errors/events 3. Add a virtual access control hook (e.g., `_onlyNewManager()`) 4. Have `RuleEngineBase` inherit the module -5. Override the hook in both `RuleEngine` and `RuleEngineOwnable` -6. Add tests in `test/RuleEngine/`, `test/RuleEngineOwnable/`, and `test/RuleEngineOwnable2Step/` +5. Override the hook in `RuleEngine`, `RuleEngineOwnable` and `RuleEngineOwnable2Step` +6. Add tests for all six deployables (one directory each under `test/`), preferably through a shared `test/utils/*TestBase.sol` ### Adding a new rule (mock) 1. Create the rule in `src/mocks/rules/` -2. Implement `IRule` (which extends `IRuleEngineERC1404`) +2. Implement `IRule`; to also support the standalone role (set directly as a CMTAT token's rule engine), implement CMTAT's `IRuleEngineERC1404` too and advertise `RULE_ENGINE_INTERFACE_ID`. The 4-argument `transferred` then needs `override(IRule, IRuleEngine)` 3. Implement ERC-165 with `IRULE_INTERFACE_ID` -4. Add tests using the existing `HelperContract` base +4. `transferred*` hooks may update the rule's own storage but must not make a state-changing external call; external reads must be `view` (`STATICCALL`). Six CMTAT variants have no reentrancy guard around `transferred` (see `doc/technical/RuleEngine-with-CMTAT.md` §4.6). A rule can also be set directly as a CMTAT token's rule engine (§4.8): keep `canTransfer*` consistent with `detectTransferRestriction*`, and a production stateful rule must restrict who calls `transferred` +5. Add tests using the existing `HelperContract` base ### Modifying access control 1. Update the virtual hook in the relevant module -2. Update overrides in **both** `RuleEngine.sol` and `RuleEngineOwnable.sol` +2. Update overrides in `RuleEngine.sol`, `RuleEngineOwnable.sol` and `RuleEngineOwnable2Step.sol` 3. Update tests in all affected test directories diff --git a/CHANGELOG.md b/CHANGELOG.md index e07c0a62..21bcec27 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -25,7 +25,12 @@ See [https://semver.org](https://semver.org) Reference: [keepachangelog.com/en/1.1.0/](https://keepachangelog.com/en/1.1.0/) -Custom changelog tag: `Dependencies`, `Documentation`, `Testing` +Custom changelog tag + +- `breaking change`: breaking change regarding storage [ERC-7201](https://eips.ethereum.org/EIPS/eip-7201) namespace , as well as external engine +- `Dependencies` (npm package, openzeppelin,...) +- `Documentation` +- `Testing` ## Checklist @@ -43,12 +48,163 @@ forge lint - Perform a code coverage and update the files in the corresponding directory [./doc/coverage](./doc/coverage) - Perform an audit with several audit tools (Aderyn and Slither), update the report in the corresponding directory [./doc/security/audits/tools](./doc/security/audits/tools) - Update surya doc by running the 3 scripts in [./doc/script](./doc/script) + - Check that the compilation artifacts of the release are in [./doc/compilation](./doc/compilation), in a `vX.Y.Z` directory (`foundry/` from `forge build`, `hardhat/` from `npx hardhat compile --force`, one entry per deployable contract). Artifacts of a previous version may stay alongside, but the latest one must be present. - Update changelog +## v3.0.0 - Unreleased (pending audit) + +Commit: to be added once the audit is done and the release is tagged. + +> **Note:** this section summarises the main changes between **v2.1.0** and **v3.0.0**. It will be finalised, with the audit report and its findings, once the audit is done. Per-item details, tests and documentation are in the release-candidate entries below (`v3.0.0-rc0` to `v3.0.0-rc7`). + +### Summary + +v3.0.0 turns the RuleEngine into a generic compliance controller for both CMTAT and ERC-3643 tokens. There is a single rule type, and the rules themselves move to a dedicated repository. There are six deployable variants (RBAC, `Ownable` and `Ownable2Step`, each with or without ERC-2771), and tokens must be explicitly bound to the engine. On-chain safeguards bound the rule set and separate rule accounts from privileged ones. + +### Breaking change + +- **Rules are no longer part of this repository.** Production rules are developed and audited separately in [CMTA/Rules](https://github.com/CMTA/Rules); `src/mocks/rules/` only holds reference mocks (suffixed `Mock` since rc5). (rc0) +- **Single rule type.** The separate validation (read-only) and operation (read-write) rule lists are merged into one rule set, managed by `RulesManagementModule` (`addRule`, `removeRule`, `setRules`, `clearRules`, `rules`, `rule`, `rulesCount`, `containsRule`). `RuleEngineOperation` is renamed `RulesManagementModule` and `MetaTxModuleStandalone` `ERC2771ModuleStandalone`. (rc0) +- **Rules must implement `IRule` and advertise it through ERC-165** (`0xb1a69752` since rc7; the rc1-rc6 ID `0x2497d6cb`, which also covers `canTransfer` / `canTransferFrom`, is still accepted); `addRule` / `setRules` reject any other contract. A v2.x rule cannot be added as is. (rc1, rc7) +- **Only bound tokens may call the engine.** `transferred`, `created` and `destroyed` revert with `TokenBinding_UnauthorizedCaller` unless the caller was bound, with `bindToken` or the constructor's `tokenContract` argument. A token's own `bindToken(this)` / `unbindToken(this)` (ERC-3643 `setCompliance`) requires a prior `setTokenSelfBindingApproval`. (rc0, rc3) +- **Rule-set cap.** `addRule` / `setRules` revert with `RuleEngine_RulesManagementModule_MaxRulesExceeded` above `maxRules` (default 10, changed with `setMaxRules`). (rc3) +- **Rule accounts cannot hold privileges.** `RuleEngine.grantRole` and the ownable variants' `transferOwnership` revert for an address in the rule set. (rc3) +- **Interfaces split.** The base ERC-3643 surface is in `IERC3643Compliance`, and the helpers (batch binding, self-binding approval, `getTokenBounds`) are in `IERC3643ComplianceExtended`. Binding moved to the standard-agnostic `ITokenBinding` / `ITokenBindingExtended`. Selectors and ERC-165 IDs of the existing functions are unchanged. (rc3, rc6) +- **Errors renamed.** `RuleEngine_ERC3643Compliance_*` became `TokenBinding_*`, which changes their selectors. (rc6) +- **RBAC base.** `RuleEngine` uses `AccessControlEnumerable` (still with "default admin has all roles"). The deployable contracts moved to `src/deployment/`. (rc2) +- **CMTAT v3.3.0 routing.** With CMTAT ≥ v3.3.0, mint, burn and the minter `batchTransfer` reach the engine on the 4-argument `transferred(spender, from, to, value)` with the operator as `spender`. Rules that check the spender must handle `from == address(0)` / `to == address(0)`. On CMTAT v3.0.0 – v3.2.0 those operations still use the 3-argument overload. (rc4, CMTAT side) +- **Compiler floor.** The CMTAT engine interfaces require `pragma ^0.8.24`, so the engine compiles with Solidity ≥ 0.8.24 despite its own `^0.8.20` pragma. +- **`version()`** returns the release string with its suffix while in release candidate (`"3.0.0-rc7"`). (rc7) +- **No storage change to migrate.** The RuleEngine is not upgradeable: moving from v2.x means deploying a new engine, re-adding the rules and re-pointing each token (`setRuleEngine` / `setCompliance`). + +### Added + +- **ERC-3643 compliance.** The engine implements `IERC3643Compliance` (`canTransfer`, `transferred`, `created`, `destroyed`, `bindToken`, `unbindToken`, `isTokenBound`, `getTokenBound`), so it can be set as the compliance contract of an ERC-3643 (T-REX) token. (rc0) +- **Two ownable variants:** `RuleEngineOwnable` (ERC-173 `Ownable`) and `RuleEngineOwnable2Step` (`Ownable2Step`), next to the RBAC `RuleEngine`. (rc1, rc2) +- **Each access-control model with or without ERC-2771:** `RuleEngine`, `RuleEngineOwnable` and `RuleEngineOwnable2Step` no longer have a trusted forwarder, and their constructors are `(admin|owner_, tokenContract)`; the new `RuleEngine2771`, `RuleEngineOwnable2771` and `RuleEngineOwnable2Step2771` carry an immutable forwarder, `(admin|owner_, forwarderIrrevocable, tokenContract)`, as the three contracts did up to rc6. (rc7) +- **Token binding registry**, reusable outside this project: `TokenBindingModule` / `TokenBindingExtendedModule`, with batch binding, `getTokenBounds()` and gated token self-binding (`setTokenSelfBindingApproval`, `setTokenSelfBindingApprovalBatch`, `isTokenSelfBindingApproved`). (rc3, rc6) +- **Rule-set cap:** `maxRules()`, `setMaxRules(uint256)` and the `SetMaxRules` event, emitted at deployment too. (rc3, rc5) +- **ERC-165 advertisement** of `IRuleEngine`, `IERC1404`, `IERC1404Extend`, `IERC3643Compliance` and its extension, `IERC7551Compliance` (subset), plus ERC-173 / `Ownable2Step` or `IAccessControl(Enumerable)` per variant. The IDs are computed from the interfaces and pinned by tests. (rc1–rc6) +- **Spender-aware path** (`transferred(spender, …)`, `canTransferFrom`, `detectTransferRestrictionFrom`), first added in v2.1.0 (partial support), and forwarded to every rule as part of CMTAT's `IRuleEngine`. + +### Security + +- Fixes and mitigations for the Nethermind AuditAgent scan findings 1–7: multi-tenant binding warning, `IAccessControl` no longer advertised by `RuleEngineOwnable`, missing interface IDs, the rule-count cap, rule accounts excluded from privileges, the restriction-code uniqueness convention, and the empty `setRules` documented. (rc2, rc3) +- Token self-binding requires explicit per-token approval, so an arbitrary contract cannot bind itself. (rc3) +- The trusted ERC-2771 forwarder can no longer act as a token: the bound-token gate and the token self-binding check compare `msg.sender`, while administration stays gasless. (rc7) +- Documented trust model: rules and every contract they call are trusted, and `transferred*` hooks must not make state-changing external calls. (rc7) + +### Dependencies + +- CMTAT: supports **≥ v3.0.0**, target **v3.3.0-rc4** (tested also against v3.0.0 via `lib/CMTATv3.0.0`). v2.1.0 targeted CMTAT v3.0.0-rc5. +- OpenZeppelin Contracts / Contracts Upgradeable **v5.7.0**. +- Solidity **0.8.37**, EVM **Osaka** (Fusaka upgrade). +- ERC-3643 reference implementation (tests only): T-REX **4.2.0-beta1**. + +### Testing + +- Test suites for all six deployable variants, CMTAT integration (current and v3.0.0), an ERC-3643 mock-token integration, and a real T-REX 4.2.0-beta1 suite in the `erc3643` Foundry profile. Also a Hardhat smoke test and tests pinning the deployment scripts and every ERC-165 interface ID. + +### Documentation + +- Full reference in `doc/README.md`, and integration guides `doc/technical/RuleEngine-with-CMTAT.md`, `RuleEngine-with-ERC3643.md` and `TokenBinding-module.md`. +- Static-analysis (Slither, Aderyn) and automated-review reports per release candidate, indexed in `doc/security/audits/AUDIT_OVERVIEW.md`. +- PlantUML flow and access-control diagrams, sol2uml and Surya diagrams. + +### v3.0.0-rc7 - 2026-10-14 + +Commit: + +### Summary + +Security hardening of the ERC-2771 token-identity checks, and ERC-2771 becomes opt-in: each access-control model is split into a contract without ERC-2771 (`RuleEngine`, `RuleEngineOwnable`, `RuleEngineOwnable2Step`) and a `*2771` contract with the trusted forwarder (`RuleEngine2771`, `RuleEngineOwnable2771`, `RuleEngineOwnable2Step2771`). The trusted forwarder can no longer pass as a token: the bound-token gate and the token self-binding check now compare `msg.sender`. The CMTAT submodule moves to v3.3.0-rc4 and the ERC-3643 submodule to T-REX 4.2.0-beta1, which is now tested end-to-end in a dedicated Foundry profile. The CMTAT / Rules documentation is corrected and completed. `version()` now carries the release-candidate suffix. The code-quality review fixes add a narrower `IRule` interface (the previous one is still accepted), one error fewer, the deployables grouped in `src/deployment/accessControl/` and `src/deployment/ownable/`, and invariant tests. + +rc7 is **not** a drop-in update from rc6: it changes three constructors, who may call the token callbacks, the `version()` string, the source paths of the deployables, the error set, the `IRule` ERC-165 ID that new rules advertise, what a manager's unbind does to a token's self-binding approval, and whether an address may be both a rule and a bound token. Each is listed below with what to do. + +### Breaking change + +- **ERC-2771 is now opt-in: `RuleEngine`, `RuleEngineOwnable` and `RuleEngineOwnable2Step` no longer support it, and their constructors drop the forwarder.** They are now `constructor(address admin, address tokenContract)` and `constructor(address owner_, address tokenContract)`, have no `isTrustedForwarder` / `trustedForwarder`, and treat every caller as the raw `msg.sender`. The versions with a trusted forwarder are the new **`RuleEngine2771`**, **`RuleEngineOwnable2771`** and **`RuleEngineOwnable2Step2771`**, whose constructors `(admin|owner_, forwarderIrrevocable, tokenContract)` and behaviour are those of the rc6 contracts without the suffix. Migration: a deployment that passed `address(0)` as forwarder drops the middle argument; one that passed a forwarder deploys the `*2771` contract. Deployment scripts in other repositories (for example CMTA/Rules) that call the 3-argument constructors must be updated. +- **Token callbacks and token self-binding are no longer relayable through the ERC-2771 forwarder.** `transferred`, `created` and `destroyed` (`onlyBoundToken`), and a token's own `bindToken` / `unbindToken(this)`, now identify the token by `msg.sender` instead of `_msgSender()`. A call that the trusted forwarder relays with a token address appended is rejected (`TokenBinding_UnauthorizedCaller`, or the binding-manager check for the self-binding path). Real tokens are unaffected, because they always call the engine directly. Only a setup that relayed token callbacks through the forwarder breaks, and no legitimate setup does. Administrative functions are unchanged and remain relayable. +- **`version()` return value format.** It now returns `"3.0.0-rc7"` instead of `"3.0.0"`. An integration that compares the string literally (deployment checks, indexers, upgrade scripts) must be updated, and must expect the suffix to change at each release candidate. +- **A manager unbind revokes self-binding approval.** An ERC-3643 token unbound by the binding manager must be approved again (`setTokenSelfBindingApproval`) before it can bind itself through `setCompliance`. Tokens that unbind themselves are unaffected. See Security. +- **An address can no longer be both a rule and a bound token.** `bindToken` / `bindTokens` reject a current rule and `addRule` / `setRules` reject a bound token (`RuleEngine_RulesManagementModule_RuleAccountCannotReceivePrivileges`). A deployment that bound a rule address, or used a bound token as a rule, must choose one role. See Security. +- **Deployable source paths.** The six deployables moved from `src/deployment/` to `src/deployment/accessControl/` (`RuleEngine`, `RuleEngine2771`) and `src/deployment/ownable/` (the four ownable contracts). A project that imports them, or a script that names the file (`forge create src/deployment/RuleEngine.sol:RuleEngine`), must update the path. Contract names, constructors and ABIs are unchanged. +- **Error removed: `RuleEngine_RulesManagementModule_OperationNotSuccessful`.** It could not be triggered (the checks before it always reverted first), so no transaction emitted it, but it disappears from the ABI. Off-chain decoders that list the engine's errors (indexers, monitoring, block explorers, scripts that map a selector to a revert reason) should drop it. Duplicate and absent rules still revert with `RuleEngine_RulesManagementModule_RuleAlreadyExists` and `RuleEngine_RulesManagementModule_RuleDoNotMatch`. +- **`IRule` ERC-165 ID: `0xb1a69752` for new rules, `0x2497d6cb` still accepted.** `IRule` no longer requires `canTransfer` / `canTransferFrom`, so `RuleInterfaceId.IRULE_INTERFACE_ID` changes from `0x2497d6cb` to `0xb1a69752`. Existing rules need no change: the rc7 engine accepts both IDs. The reverse is not true: a rule compiled against rc7 that advertises only `RuleInterfaceId.IRULE_INTERFACE_ID` is rejected by an rc6 or older engine (`RuleEngine_RuleInvalidInterface`). A rule meant to work with both generations advertises both IDs (`RuleInterfaceId.IRULE_LEGACY_INTERFACE_ID` is provided for that). +- **What does not change.** Storage: the RuleEngine is not upgradeable and uses no ERC-7201 namespace. The functions, their selectors, the events and the ERC-165 IDs the engine advertises are the same as rc6 for `RuleEngine`, `RuleEngineOwnable` and `RuleEngineOwnable2Step`, apart from the constructors and ERC-2771 views listed above; the `*2771` contracts expose the rc6 surface of those three (ERC-2771 has no ERC-165 ID). The CMTAT v3.3.0-rc4 update changes only NatSpec in `IRuleEngine`; its engine-facing breaking changes (mint, burn and the minter `batchTransfer` routed to the 4-argument `transferred`, the reentrancy guard around `transferred`, the `^0.8.24` pragma of the engine interfaces) were already present in the v3.3.0-rc1 / rc3 targets of rc4–rc6. + +### Security + +- **The trusted ERC-2771 forwarder can no longer act as a token.** `TokenBindingModule._checkBoundToken` (the `onlyBoundToken` gate) and the token self-binding check in `TokenBindingExtendedModule._authorizeTokenBindingChange` compared `_msgSender()`, so a trusted forwarder could append a token's address and pass as that token. It could (a) call `transferred` / `created` / `destroyed` with no token movement, driving stateful rules, for example consuming a per-minter mint quota or a one-time transfer approval; and (b) call `unbindToken(token)` for a token approved for self-binding, after which every operation of that token reverted until it was re-bound. Both checks now compare the raw `msg.sender`; a token never calls through a forwarder. A signature-verifying forwarder could not produce these calls, because a token cannot sign, so the exposure was limited to a buggy, malicious or permissive forwarder. This aligns with CMTAT's `onlyTokenBridge` and with CMTAT's RuleEngine integration guide. The administrative checks keep `_msgSender()`, so gasless administration is unchanged. +- **`RuleEngineOwnable2Step` re-checks the rule-account guard in `acceptOwnership`.** The check that keeps rule contracts away from ownership ran only at nomination (`transferOwnership`), so an address nominated while it was not a rule, then added as a rule, could still accept and own the engine. `acceptOwnership` now reverts with `RuleEngine_RulesManagementModule_RuleAccountCannotReceivePrivileges` in that case; the transfer completes once the address is removed from the rule set. Applies to `RuleEngineOwnable2Step2771` too. Required two actions by the trusted owner. rc7 security review `F-1` ([CLAUDE_AUDIT.md](./doc/security/audits/tools/v3.0.0-rc7/CLAUDE_AUDIT.md)). +- **An administrative unbind revokes the token's self-binding approval.** `unbindToken` and `unbindTokens` called by the binding manager now also clear the token's self-binding approval (`TokenBindingExtendedModule._unbindToken`, emitting `TokenSelfBindingApprovalSet(token, false)`). Before, an approved token could bind itself again right after the manager unbound it, undoing the manager's decision. A token unbinding itself keeps its approval, so ERC-3643 `setCompliance` migrations are unchanged. The approval setter now goes through `_setTokenSelfBindingApproval`, the single write path of the per-token event. rc7 security review `F-2` ([CLAUDE_AUDIT.md](./doc/security/audits/tools/v3.0.0-rc7/CLAUDE_AUDIT.md)). +- **Rules and bound tokens are kept disjoint.** Binding a current rule (`bindToken`, `bindTokens`, or a rule binding itself with a self-binding approval) now reverts with `RuleEngine_RulesManagementModule_RuleAccountCannotReceivePrivileges`, and so does adding a bound token as a rule (`addRule`, `setRules`). Binding lets an address drive every rule, so a rule that was also a bound token could call the engine's callbacks from inside its own `transferred` hook. Implemented with a new empty hook in the reusable registry, `TokenBindingModule._checkBindingTarget`, overridden by `RuleEngineBase`, and a bound-token check in `RuleEngineBase._checkRule`. The NatSpec and `TokenBinding-module.md` now state that binding is a trust decision: an EOA or any other contract can still be bound. rc7 security review `F-3` ([CLAUDE_AUDIT.md](./doc/security/audits/tools/v3.0.0-rc7/CLAUDE_AUDIT.md)). + +### Changed + +- `pragma solidity` raised from `^0.8.20` to **`^0.8.27`** in every `src/` and `script/` file. The code uses `require(cond, CustomError())`, which the legacy pipeline supports from solc 0.8.27 only, so it never compiled below that version (checked: 0.8.20, 0.8.24 and 0.8.26 fail, 0.8.27 builds). The pragma now states the real floor, and an integrator on an older compiler gets a clear version error. Found by the rc7 code-quality review (`F-1`) and the Aderyn `L-2` triage. `README.md`, `CLAUDE.md` / `AGENTS.md` and `RuleEngine-with-ERC3643.md` updated. +- `RuleEngineBase`: the three view loops (`detectTransferRestriction`, `detectTransferRestrictionFrom`, `messageForTransferRestriction`) iterate `_rules` directly (`_rules.length()`, `_rules.pos(i)`) instead of the public `rulesCount()` / `rule(i)`, which re-checked the bound on every iteration. Same form as the enforcement loops; no behaviour change. Measured −682 gas per detect call with 3 rules (−227 per rule); T-REX tokens pay it on every transfer and mint through `canTransfer`. rc7 code-quality review `A-3`. +- `RuleEngineBase._messageForTransferRestriction`: the rule is read once per iteration and reused for `canReturnTransferRestrictionCode` and `messageForTransferRestriction`, instead of being read again from storage after the first external call. No behaviour change; measured −375 gas per call with 3 rules. rc7 code-quality review `B-1`. +- `RulesManagementModule`: `addRule` / `setRules` and `removeRule` rely on the return value of the `EnumerableSet` mutation instead of a preceding `contains()` lookup, as the token binding already did. `_checkRule` now checks only the zero address; a duplicate still reverts with `RuleEngine_RulesManagementModule_RuleAlreadyExists` (after the ERC-165 check instead of before), and removing an absent rule still reverts with `RuleEngine_RulesManagementModule_RuleDoNotMatch`. The unreachable `RuleEngine_RulesManagementModule_OperationNotSuccessful` error is removed. Measured −271 gas on `addRule` and −268 on `removeRule`; branch coverage of `src/` reaches 100% (40/40). The redundant checks added no security (assessed in the review). rc7 code-quality review `B-2`. +- `RuleEngine` now holds the RBAC logic directly and `RuleEngine2771` extends it, the same pattern as the ownable `*2771` contracts; the intermediate abstract `RuleEngineAccessControlShared` (introduced earlier in rc7, never released) is removed. The deployables are grouped by access-control model in `src/deployment/accessControl/` and `src/deployment/ownable/`. No behaviour change: constructors, roles, ERC-165 answers and the 438 Foundry tests (and the 13 real ERC-3643 tests) are unchanged. `README.md`, `doc/README.md`, `CLAUDE.md` / `AGENTS.md`, `package.json`, `doc/TOOLCHAIN.md` and `doc/script/script_sol2uml.sh` updated. rc7 code-quality review `D-2`. +- CI (`.github/workflows/ci.yml`) also runs `FOUNDRY_PROFILE=erc3643 forge test`, so the 13 tests against the real T-REX 4.2.0-beta1 token are no longer skipped. rc7 code-quality review `K-4`. +- A rule used directly as a CMTAT token's rule engine (no RuleEngine) is now tested and documented: `test/RuleStandalone/RuleStandaloneCMTAT.t.sol` (9 tests, one or more per reference rule, on a real CMTAT token; 438 -> 447 tests) and `RuleEngine-with-CMTAT.md` §4.8, which states what a rule must do for that role (restrict who calls `transferred` when it keeps state, keep `canTransfer*` consistent with `detectTransferRestriction*`). The four reference rules import `RULE_ENGINE_INTERFACE_ID` and `ERC1404EXTEND_INTERFACE_ID` from CMTAT instead of hardcoding them. rc7 code-quality review `I-2`. +- Error style: the 8 remaining `if (...) { revert X(); }` sites in `src/` (and 4 in the mock rules) use `require(cond, X())`, as the project convention asks. Same errors, same conditions; gas unchanged on the token path (`transferred`), +13 on `addRule` (the cap is cached in a local because `require` evaluates the error argument eagerly) and +5 on `setRules`. rc7 code-quality review `E-2`. +- `IRule` declares the engine's needs only (`src/interfaces/IRule.sol`: `IERC1404Extend`, `IERC3643IComplianceContract`, `IERC165`, plus the 4-argument `transferred` and `canReturnTransferRestrictionCode`) and `RuleInterfaceId.IRULE_INTERFACE_ID` is recomputed (`0xb1a69752`). The four reference rules also implement `IRuleEngineERC1404` to keep the standalone role, with `override(IRule, IRuleEngine)` on the 4-argument `transferred`; the test probes `RuleCodeProbe` and `SupplyCapProbeRule` drop `canTransfer` / `canTransferFrom` and are accepted on all six deployables. `IRule` no longer inherits CMTAT's `IRuleEngineERC1404`, so a new rule needs neither `canTransfer` nor `canTransferFrom`. **Not breaking for existing rules:** `RuleEngineBase._supportsRuleInterface` accepts the new ID or the legacy one (`RuleInterfaceId.IRULE_LEGACY_INTERFACE_ID`, `0x2497d6cb`, a superset of the new interface), after checking ERC-165 support once; a contract advertising neither, or answering `true` to every ID, is rejected. `addRule` with a current-ID rule costs 64 gas less than before. New tests: the new ID equals the old one XOR the two selectors and the legacy constant is pinned; on all six deployables, an engine-only rule is accepted, a rule advertising only the legacy ID is accepted, and a contract advertising no rule ID, claiming every ID, or without ERC-165 (an EOA) is rejected; removing the ERC-165 pre-check or the legacy fallback each fails 6 tests (447 -> 481 tests). rc7 code-quality review `I-1`. +- `bindTokens` / `unbindTokens` stay atomic by decision: one token already bound (or not bound) reverts the whole call, unlike the skip-if-already-done batch convention of `RuleAddressList`, because a binding change is security-relevant. Stated in the `ITokenBindingExtended` NatSpec and `TokenBinding-module.md` §4; the batch tests now check the rollback of the tokens processed before the failure, and a new test pins empty batches as no-ops, in the three access-control families (460 -> 463 tests). rc7 code-quality review `C-3`. +- Self-binding approval events: kept as they are, documented. The `ITokenBindingExtended` NatSpec no longer says `TokenSelfBindingApprovalBatchSet` lists the tokens whose permission *changed* (it is the input array, with no-ops and duplicates), and states that the batch emits no per-token `TokenSelfBindingApprovalSet`, so indexers must handle both events or read `isTokenSelfBindingApproved`; same warning in `TokenBinding-module.md` §4. `TokenBound` / `TokenUnbound` NatSpec states they stay non-indexed as declared by ERC-3643. rc7 code-quality review `C-2`. +- NatSpec and comments: `RulesManagementModule` gets a real `@title`; the two `_transferred` describe enforcement (they apply every rule and revert on the first rejection) instead of detection; `RuleEngineBase` loses the placeholder `// Apply on RuleEngine` and its `detectTransferRestriction` doc is reworded; section headers read `PUBLIC/EXTERNAL FUNCTIONS` in the three binding modules; the empty `Events` header of `VersionModule` is removed; "restricion" typo fixed in `RuleEngineBase` and the mock rules. Comment-only. rc7 code-quality review `G-2`. +- `ERC3643TokenMock` header: describes the vendored T-REX 4.2.0-beta1 (not 4.1.3) and says the real token is tested in `test/ERC3643Real/` under the `erc3643` profile; the claims that it cannot be compiled, pins 0.8.17 and uses OpenZeppelin 4.8 are removed. rc7 code-quality review `G-3`. +- `version()` now returns `"3.0.0-rc7"` instead of `"3.0.0"`, so the on-chain string matches the release tag (`VersionModule.VERSION`). The `version()` assertions of the RBAC and Ownable suites and of the Hardhat smoke test are updated, and `RuleEngineOwnable2Step` gains its own `testHasRightVersion` (348 -> 349 tests). + +### Added + +- Add `test/utils/ERC2771TokenGateTestBase.sol` and `test/RuleEngine*/ERC2771TokenGate.t.sol`: 7 tests × 3 deployable variants (349 -> 370 tests). Each simulates a forwarder relay (`vm.prank(forwarder)` with the claimed sender appended to the calldata) and checks four things: the forwarder cannot pass as a bound token on any of the four callbacks; a forged mint callback does not consume a `RuleMintAllowanceMock` quota, while a real one does; the forwarder cannot unbind a token approved for self-binding; and the bound token, an approved self-binding token and a relayed binding manager still work. Against the rc6 code, the three impersonation tests fail. +- Add the deployables **`RuleEngine2771`**, **`RuleEngineOwnable2771`** and **`RuleEngineOwnable2Step2771`** (`src/deployment/accessControl/` and `src/deployment/ownable/`), each adding an immutable ERC-2771 trusted forwarder to its access-control model. Every `*2771` contract extends its counterpart without the suffix (`RuleEngine2771 is ERC2771ModuleStandalone, RuleEngine`, and likewise for the two ownable contracts) and adds only `ERC2771ModuleStandalone` and the three `Context` overrides; the RBAC logic (constructor checks, initial `SetMaxRules`, `grantRole` rule guard, admin-has-all-roles `hasRole`, ERC-165, access-control hooks) is held by `RuleEngine` itself. `RuleEngineOwnableShared` drops ERC-2771 (constructor `(tokenContract)`). The coverage mocks become `RuleEngine2771Exposed`, `RuleEngineOwnable2771Exposed` and `RuleEngineOwnable2Step2771Exposed`. Tests: two new shared bases, `ERC2771VariantTestBase` (forwarder trusted, version, zero admin/owner, same ERC-165 answers as the counterpart without forwarder, `_msgData` stripping on a relayed call; run for the three `*2771` contracts) and `NoForwarderTestBase` (no `isTrustedForwarder` / `trustedForwarder`, an appended sender is ignored; run for the three others); new directories `test/RuleEngine2771/`, `test/RuleEngineOwnable2771/`, `test/RuleEngineOwnable2Step2771/` with the ERC-2771 token-gate suites moved there and the rule-aggregation suite; initial `SetMaxRules` checked for all six. Every 3-argument constructor call with a zero forwarder in the tests and scripts drops that argument; the Hardhat smoke test deploys `RuleEngine` and `RuleEngine2771` (395 -> 438 Foundry tests). +- Add `test/utils/RuleAggregationTestBase.sol` (7 tests × 3 deployable variants, in `test/RuleEngine*/RuleAggregation.t.sol`) and the test-only rule `test/utils/RuleCodeProbe.sol`, whose restriction codes, claimed code and message are set per test. They pin how the engine aggregates several rules: the first non-zero code in rule order (two fuzz properties, for the 3- and 4-argument views, with `canTransfer` / `canTransferFrom` derived from it), boundary codes 1 and 255, the message taken from the rule that claims the code, every rule run by each callback, and the zero address on the correct side in `created` / `destroyed`. Also add `testSetTokenSelfBindingApprovalEmitsEvent` (3 variants; the event was never asserted) and `testCannotBindTokensBatchWithDuplicateToken`, and make the two bare `vm.expectRevert()` of `ERC3643TokenIntegration.t.sol` name their error. Found by mutation testing in the rc7 code-quality review: 4 of 32 mutants of `src/` survived the suite, and all 33 (one added) are now killed (370 -> 395 tests). +- Add `test/ERC3643Real/ERC3643RealTokenRuleEngine.t.sol` (13 tests) against the **real** vendored ERC-3643 token (T-REX 4.2.0-beta1): self-binding through `init` / `setCompliance`, mint through `created`, burn through `destroyed`, `transfer` / `transferFrom` on the 3-argument `transferred` with no spender forwarded, `forcedTransfer` notifying compliance, unbound callers rejected, and the post-update notification order (a CMTAT-style supply cap counts a mint twice). Run with `FOUNDRY_PROFILE=erc3643 forge test`: a new `[profile.erc3643]` builds at solc 0.8.30 (the token pins `pragma solidity 0.8.30`) into `out-erc3643/`, with a context-scoped `@onchain-id` remapping to the stubs in `test/utils/onchainid/`; the default profile skips the directory. Test helpers: `IdentityRegistryStub`, `SupplyCapProbeRule`. + +- Add `test/RuleEngine/RulesManagementModuleTest/CMTATOperationRoutingV3.t.sol` (10 tests) against a real **CMTAT v3.0.0** token, the last audited CMTAT release: for `transfer`, `transferFrom`, `mint` and `burn`, the exact `transferred` overload and arguments reaching the engine and the rule (`transfer`, `mint`, `burn` on the 3-argument overload, `transferFrom` on the 4-argument one with the spender), a rule rejecting that overload blocking each operation, and a rule enforced only on the 4-argument path letting mint and burn through. Shown to fail when the expected minter or spender is changed. 610 -> 620 tests. + +- Add handler-based invariant tests for all six deployables: `test/utils/RuleEngineInvariantTestBase.sol` (a `RuleEngineHandler` that drives random sequences of rule and binding administration and models their effect) and a `RuleEngineInvariant.t.sol` per `test/RuleEngine*/` directory. Four invariants: the rule set matches the model and is well formed (no duplicate, no `address(0)`, every member advertises a rule ID, `rules()` and `rule(i)` agree), `maxRules()` is the last value set and never 0, and the bound tokens match the model with no duplicate. Shown to fail on three mutants. `foundry.toml` caps them at 64 runs x 50 calls (about 3 s; the defaults took about 5 minutes). 481 -> 505 tests. rc7 code-quality review `K-5`. + +### Documentation + +- `doc/README.md` "Like CMTAT": corrected the overload routing. The section said the 3-argument `transferred` is never called in CMTAT v3.3.0 flows and listed `transfer` with a spender; a direct `transfer` is in fact the one operation that uses the 3-argument overload. The table now gives the overload per operation, including `batchMint`, `batchBurn`, `burnFrom`, self-burn, cross-chain mint/burn and the minter `batchTransfer`, as documented in the CMTAT v3.3.0-rc4 `IRuleEngine` NatSpec; `doc/technical/RuleEngine-with-CMTAT.md` gains the minter `batchTransfer` row. Compatibility tables and the tested toolchain (OpenZeppelin v5.7.0, CMTAT v3.3.0-rc4) updated. +- CMTAT / Rules related documentation: complete CMTAT entry-point table (`batchMint`, `batchBurn`, `burnFrom`, cross-chain, minter `batchTransfer` with `spender == from`, `forcedTransfer` bypass); CMTAT v3.0.0–v3.2.0 3-argument mint/burn note; ERC-2771 forwarder trust stated for the bound-token gate (`doc/README.md` §Gasless, `RuleEngine-with-CMTAT.md` §4.7, `RuleEngine-with-ERC3643.md` §4.5, `TokenBinding-module.md` §4); rule-side `transferred*` reentrancy obligation (`RuleEngine-with-CMTAT.md` §4.6, `CLAUDE.md`); token-level ERC-1404 mint/burn pre-flight caveat; ERC-3643 post-update notification order (`RuleEngine-with-ERC3643.md` §4.9); rule lists synced with the Rules repository (`RuleSanctionsList` spelling, seven missing rules, `RuleConditionalTransferLightMultiToken` must not sit behind an engine); single-rule setup caveats; `ERC2771Context` / `forwarderIrrevocable` naming; `IRuleEngine.sol` link moved to CMTAT v3.3.0-rc4; two ERC-165 conventions explained; deployment checklist wiring steps; quick start uses non-recursive `git submodule update --init` without `npm install`; "CMTAT ≥ v3.0.0" headings and `setRuleEngine(IRuleEngine)` signature. +- `doc/README.md` §Compatibility: removed the RuleEngine v3.0.0-rc3 row, which linked to a CMTAT `v3.3.0` tag that does not exist yet and was out of order with the rc4 row. +- Add the v3.0.0-rc7 Slither (0.11.5) and Aderyn (0.6.5) reports with their assessment feedback in [doc/security/audits/tools/v3.0.0-rc7](./doc/security/audits/tools/v3.0.0-rc7), run on the final rc7 code (`3055fe2`: six deployables, after the code-quality review fixes), and refresh [AUDIT_OVERVIEW.md](./doc/security/audits/AUDIT_OVERVIEW.md) and the `doc/README.md` tables. Slither: 0 High / 0 Medium / 10 Low / 2 Informational, the same 12 results as rc6 (108 -> 111 contracts). Aderyn: 0 High / 8 Low, the same findings as rc6, 84 -> 90 instances from the two per-file detectors on the three new `*2771` files; nSLOC 683 -> 694. Re-run after the code-quality review fixes: same findings as the intermediate run (112 contracts / 92 instances), only the folded `RuleEngineAccessControlShared` file is gone. Re-run again on the final code (`29556e5`, after the security review fixes F-1 to F-3): Slither output byte-identical; Aderyn 90 -> 91 instances, one `L-5` empty block for the default `_checkBindingTarget` hook (F-3), nSLOC 694 -> 716. Nothing exploitable. The Aderyn `L-2` triage accepted the floating pragma as "the supported range", which was false, so the pragma was corrected (see Changed). +- Regenerate the Surya schema (`doc/schema/surya/`: call graph, inheritance graph and report for each of the 56 files under `src/`), adding `RuleEngine2771`, `RuleEngineOwnable2771` and `RuleEngineOwnable2Step2771`; regenerated again after the deployables moved and `RuleEngine` absorbed the RBAC logic, and once more on the final rc7 code (`3055fe2`, all 55 files; the `RuleEngineBase` inlined table gains `_supportsRuleInterface`). `doc/README.md`: the four inlined Surya tables (`RuleEngineBase`, `VersionModule`, the two binding modules, `ERC3643ComplianceModule`) are refreshed — `RuleEngineBase` listed a `hasRole` it does not have and the wrong `IRuleEngine` base, `VersionModule` the old `IERC3643Base` base; the deployable sections embed the current Surya inheritance graphs next to the older sol2uml diagrams; and the call graph shown is `RuleEngineBase`, where the logic lives, instead of the now-minimal `RuleEngine`. +- Regenerate the sol2uml class diagrams (`doc/schema/sol2uml/`, 16 -> 20 images) on the final rc7 code: the three deployables without a forwarder now show their real surface (no ERC-2771 members, 2-argument constructors), and `RuleEngine2771UML`, `RuleEngineOwnable2771UML`, `RuleEngineOwnable2Step2771UML` and `IRuleUML` (the narrowed interface) are added and embedded in `doc/README.md`, which drops the three "UML predates the split" notes. `doc/script/script_sol2uml.sh` now renders through Graphviz (`sol2uml -f dot`, then `dot -Tpng -Gdpi=96`) instead of sol2uml's headless Chrome, which cannot start where unprivileged user namespaces are disabled (Ubuntu 23.10+ AppArmor). +- Add the v3.0.0-rc7 code-quality review, including the test suite, in [CLAUDE_ANALYSIS.md](./doc/security/audits/tools/v3.0.0-rc7/CLAUDE_ANALYSIS.md), indexed in `AUDIT_OVERVIEW.md` and `doc/README.md`. Nothing in it is a vulnerability. It was run twice: at `4946c87`, then on the final rc7 code (six deployables, `^0.8.27`), re-verifying every finding and re-measuring every gas number. Fixed along the way: the false `^0.8.20` pragma (`F-1`), the stale "MetaTxModule" NatSpec (`G-2`, removed by the split) and a reuse blocker, `Error (3364)` for a host bringing its own `ERC2771Context`, which the ERC-2771 split removed (`J-2`, verified by compile probe). Implemented after it: the view-loop storage reads (`A-3`), the second rule lookup in `messageForTransferRestriction` (`B-1`) and the redundant `contains()` checks in `addRule` / `removeRule` (`B-2`, assessed as adding no security), see Changed. Open decisions it records: 9 remaining stale NatSpec sites; a `*2771` deployable accepting a zero forwarder; the two families implementing the ERC-2771 split differently; CI not running the `erc3643` profile. Coverage is 100% of lines and functions, 41/43 branches at review time (the 2 missing were dead code, removed by `B-2`: now 40/40); mutation testing: 50 mutants over both passes, 0 surviving. +- `doc/technical/RuleEngine-with-CMTAT.md` §4.7: no longer says that every deployable inherits `ERC2771Context` or that `address(0)` disables gasless administration; it names the three `*2771` deployables and points to the contracts without the suffix. +- Remove `doc/schema/cmtat_surya_inheritance_IRuleEngine.sol.png`, a 2025 Surya graph showing `IRuleEngine` extending `IERC1404Extend`, which has not been true since CMTAT v3.2.0. `doc/README.md` §Interface › CMTAT now gives the current inheritance in text (`IRuleEngine` extends `IERC7551Compliance`, `IERC3643IComplianceContract` and `IERC165`; `IRuleEngineERC1404` adds `IERC1404Extend`) and points to the sol2uml diagram of `IRuleEngine`. +- Remove `doc/other/CMTAT/` (`transferred.png`, `checkTransferred.png`): 2025 screenshots of CMTAT code in which `_transferred` still returned a `bool`. `doc/README.md` "Like CMTAT" now quotes the CMTAT v3.3.0-rc4 code of `_checkTransferred`, `_transferred` and `_callRuleEngineTransferred` as text, and its links point to the v3.3.0-rc4 tag. The `CMTATBaseRuleEngine` link was broken, because the file is now `3_CMTATBaseRuleEngine.sol`. +- New dedicated **CMTAT v3.0.0** sections, in `doc/README.md` §How to set it and `doc/technical/RuleEngine-with-CMTAT.md` §2: per-operation routing table for v3.0.0 (mint, burn and the minter `batchTransfer` on the 3-argument overload, `forcedTransfer` bypassing the engine), consequences for spender-keyed rules and the tests that pin them. Previously a note and one bullet. The root `README.md` gains a short CMTAT compatibility table (which RuleEngine for CMTAT v3.0.0, which CMTAT versions rc7 supports). +- Rule documentation checked against the [Rules](https://github.com/CMTA/Rules) source at v0.6.0 (now a reference submodule, see Dependencies): + - `doc/README.md` §Available Rules: the table gains each rule's restriction codes and its ERC-3643 support (✔ / ✔¹ spender check inert / ⚠ use the `…ERC3643` variant / ✘), and is now synced with v0.6.0. `RuleIdentityRegistry` screens the receiver only by default; `RuleWhitelist` enables mint and burn with `allowMint` / `allowBurn` flags; `RuleMintAllowance` is also inert on ERC-3643. + - Corrected: "a same engine can serve several tokens with all read-only rules" was false. `RuleMaxTotalSupply`, `RuleChainlinkPoR` (and their ERC-3643 variants) and `RuleMaxBalance` read one token configured at deployment, and `RuleConditionalTransferLight` keys approvals with no token dimension (`doc/README.md`, `RuleEngine-with-CMTAT.md` §4.4, `RuleEngine-with-ERC3643.md` §4.3). + - The operation rules accept `transferred` only from a caller bound on the rule. The wiring an engine needs (`bindToken(token)` + `bindRuleEngine(engine)` for `RuleConditionalTransferLight`, `bindToken(engine)` for `RuleMintAllowance`) is now documented (`RuleEngine-with-CMTAT.md` §3.4, §4.8). + - Rules up to v0.6.0 are built against RuleEngine v3.0.0-rc6 and advertise the legacy `IRule` ID `0x2497d6cb`, still accepted; stated in both READMEs and both integration guides. `RuleEngine-with-CMTAT.md` §3.4 no longer says that only `0xb1a69752` is accepted. + - `RuleEngine-with-ERC3643.md` §3.4 lists the rules that are inert, need a variant or are unsupported on an ERC-3643 token; §4.2 describes how the production rules handle the `address(0)` sentinel. +- Replace the v3.0.0-rc2 compilation artifacts in `doc/compilation/` with the v3.0.0-rc7 ones, for the six deployables (Foundry `out/` and Hardhat `artifacts/` JSON; solc 0.8.37, EVM Osaka). `doc/README.md` §Compilation points to them, and its contract-size table, last measured on 2026-03-18 for two contracts, now lists the six rc7 deployables. +- Add the v3.0.0-rc6 specification PDFs under `doc/specification/previous_specification/rc6/` and the cover sources; add `doc/script/convert_links_for_pdf_root.sh`, which applies the PDF link conversion of `convert_links_for_pdf.sh` to the root `README.md`. + +### Dependencies + +- Set the Solidity compiler to [0.8.37](https://www.soliditylang.org/blog/2026/09/10/solidity-0.8.37-release-announcement/) in `foundry.toml` (default profile) and `hardhat.config.js`. Checked against the release announcement: none of its bug fixes applies to this codebase or its dependencies. They concern a memory `bytes` element `delete` (only storage-mapping `delete` is used), `--via-ir` spill slots, named-argument custom errors in `require` and constants on the IR pipeline (the project uses the legacy pipeline), and internal function pointers in packed storage (none are used). There is no `pragma experimental`, and Prague is not among the newly deprecated EVM versions. Compiler warnings are the same as with 0.8.36, and the deployed bytecode size of the three deployables is unchanged. The `erc3643` test profile stays on 0.8.30, which the vendored T-REX `Token.sol` pins exactly. +- Set the EVM version from Prague to **Osaka** (Fusaka upgrade, the default of solc 0.8.37) in `foundry.toml` (default profile) and `hardhat.config.js`. The deployed code of the three deployables is identical to the Prague build once the metadata, which records the EVM version, is stripped. It contains no `CLZ`, the only new opcode Osaka gives the compiler, so the contracts also run on chains that have not activated Fusaka. The `erc3643` test profile stays on Prague, because `osaka` is still experimental in solc 0.8.30. +- Update Foundry (forge-std) from v1.14.0 to [v1.17.0](https://github.com/foundry-rs/forge-std/releases/tag/v1.17.0). It is a drop-in update with no test change. It removes the 58 compiler warnings raised by the `error` parameter names in forge-std's `Vm.sol`. +- Update the ERC-3643 submodule (`lib/ERC-3643`) from 4.1.3 to [4.2.0-beta1](https://github.com/ERC-3643/ERC-3643/releases/tag/4.2.0-beta1) (`a708758`, the commit used by the Rules repository). Only the `erc3643` test profile compiles it. +- Add the [Rules](https://github.com/CMTA/Rules) repository as a submodule (`lib/Rules`, [v0.6.0](https://github.com/CMTA/Rules/releases/tag/v0.6.0)), as the reference for the rule documentation. Nothing compiles it: no remapping points to it. +- Update CMTAT submodule to [v3.3.0-rc4](https://github.com/CMTA/CMTAT/releases/tag/v3.3.0-rc4). No change to the interfaces used by the RuleEngine: rc4 only documents the `transferred` overload routing in the `IRuleEngine` NatSpec, replaces `EnumerableSet.at` by `EnumerableSet.pos` in `HolderListModule` (OpenZeppelin 5.7.0 deprecation, already the version of our submodule) and adds upgrade test mocks. Build and full test suite pass unchanged. + ### v3.0.0-rc6 +Commit: `ca75429c581a2eb9043e4719561e941d0b2e1206` + ### Summary Token binding is separated from the ERC-3643 compliance code: `TokenBindingModule` and diff --git a/CLAUDE.md b/CLAUDE.md index f64b8dc3..9a100082 100644 --- a/CLAUDE.md +++ b/CLAUDE.md @@ -8,9 +8,9 @@ AGENTS.md and CLAUDE.md files must always be identical — always update both to **RuleEngine** is a Solidity smart contract system that enforces transfer restrictions for [CMTAT](https://github.com/CMTA/CMTAT) and [ERC-3643](https://eips.ethereum.org/EIPS/eip-3643) tokens. It acts as an external controller that calls pluggable rule contracts on each token transfer, mint, or burn. -- **Version:** 3.0.0 (defined in `src/modules/VersionModule.sol`) -- **Solidity:** ^0.8.20 (compiled with 0.8.36) -- **EVM target:** Prague +- **Version:** 3.0.0-rc7 (defined in `src/modules/VersionModule.sol`; the string carries the release-candidate suffix and must be bumped with each tag — update the `version()` assertions in `test/RuleEngine/RuleEngineDeployment.t.sol`, `test/utils/ERC2771VariantTestBase.sol`, `test/RuleEngineOwnable/RuleEngineOwnableDeployment.t.sol`, `test/RuleEngineOwnable2Step/RuleEngineOwnable2Step.t.sol` and `test/hardhat/RuleEngine.smoke.js` with it) +- **Solidity:** ^0.8.27 (compiled with 0.8.37). `src/` and `script/` declare `^0.8.27`: it is the first version that supports `require(cond, CustomError())` on the legacy pipeline, so do not lower it +- **EVM target:** Osaka (Fusaka upgrade) - **License:** MPL-2.0 ## Build & Test Commands @@ -23,10 +23,18 @@ forge test --match-contract --match-test # Run specific test forge coverage # Code coverage forge coverage --no-match-coverage "(mocks|test)" --report lcov # Production coverage (src/ + script/) forge fmt # Format code +FOUNDRY_PROFILE=erc3643 forge test # Real ERC-3643 token suite (test/ERC3643Real/, solc 0.8.30) +FOUNDRY_INVARIANT_RUNS=256 FOUNDRY_INVARIANT_DEPTH=500 forge test --match-contract InvariantTest # deeper invariant run (foundry.toml caps it at 64 x 50) ``` -Dependencies are git submodules. Initialize with `forge install`, update with `forge update`. -CMTAT submodule also needs `cd lib/CMTAT && npm install` for its OpenZeppelin deps. +`test/ERC3643Real/` deploys the vendored T-REX 4.2.0-beta1 `Token`, which pins `pragma solidity 0.8.30`. It is +skipped by the default profile and built by `[profile.erc3643]` (solc 0.8.30, `out-erc3643/`, context-scoped +`@onchain-id` remapping to the stubs in `test/utils/onchainid/`). Files there must pin `pragma solidity 0.8.30`. +Never move the context-scoped remapping into `remappings.txt`: `hardhat-foundry` rejects it. + +Dependencies are git submodules. Initialize with `git submodule update --init` (non-recursive is enough), update with `forge update`. +`remappings.txt` resolves `@openzeppelin/...` to this repo's own submodules for every file, including the CMTAT sources, +so `cd lib/CMTAT && npm install` and `--recursive` are only needed to run CMTAT's own Hardhat suite. ## Agent Workflow @@ -54,21 +62,24 @@ Use `@openzeppelin/contracts/` for OpenZeppelin imports and `CMTAT/` for CMTAT i ## Architecture -### Three Deployable Contracts +### Six Deployable Contracts ``` -RuleEngine — RBAC via AccessControl (multi-operator) -RuleEngineOwnable — ERC-173 Ownable (single-owner) -RuleEngineOwnable2Step — ERC-173 Ownable2Step (single-owner, two-step handover) +RuleEngine — RBAC via AccessControl (multi-operator), no ERC-2771 +RuleEngine2771 — RBAC via AccessControl + ERC-2771 (immutable trusted forwarder) +RuleEngineOwnable — ERC-173 Ownable (single-owner), no ERC-2771 +RuleEngineOwnable2771 — ERC-173 Ownable + ERC-2771 +RuleEngineOwnable2Step — ERC-173 Ownable2Step (single-owner, two-step handover), no ERC-2771 +RuleEngineOwnable2Step2771 — ERC-173 Ownable2Step + ERC-2771 ``` -All three share their core logic through `RuleEngineBase` directly or via `RuleEngineOwnableShared`. +All six share their core logic through `RuleEngineBase`: `RuleEngine` extends it directly with RBAC, and the four ownable variants go through `RuleEngineOwnableShared`. Each access-control model has a version without ERC-2771 (constructor `(admin|owner_, tokenContract)`) and a `*2771` version with an immutable trusted forwarder (constructor `(admin|owner_, forwarderIrrevocable, tokenContract)`). Every `X2771` extends its counterpart `X` (`RuleEngine2771 is ERC2771ModuleStandalone, RuleEngine`, and likewise for the ownable pair) and adds only `ERC2771ModuleStandalone` plus the three `Context` overrides. The deployables live in `src/deployment/accessControl/` (RBAC) and `src/deployment/ownable/` (ERC-173). ### Inheritance Hierarchy ``` RuleEngineBase (abstract) -├── VersionModule → version() returns "3.0.0" +├── VersionModule → version() returns "3.0.0-rc7" ├── RulesManagementModule → add/remove/set/clear rules, maxRules cap │ ├── AccessControl (OZ) │ └── RulesManagementModuleInvariantStorage → errors, events, roles @@ -83,21 +94,32 @@ RuleEngineBase (abstract) ├── RuleEngineInvariantStorage → errors └── IRuleEngineERC1404 → CMTAT interface -RuleEngine +RuleEngine → no gasless support +├── RuleEngineBase +├── AccessControlEnumerable (OZ) +└── ERC3643ComplianceRolesStorage, RulesManagementModuleRolesStorage → roles + +RuleEngine2771 ├── ERC2771ModuleStandalone → gasless support -└── RuleEngineBase +└── RuleEngine RuleEngineOwnable -├── ERC2771ModuleStandalone → gasless support -├── RuleEngineOwnableShared +├── RuleEngineOwnableShared → no gasless support │ └── RuleEngineBase └── Ownable (OZ) → ERC-173 -RuleEngineOwnable2Step +RuleEngineOwnable2771 ├── ERC2771ModuleStandalone → gasless support -├── RuleEngineOwnableShared +└── RuleEngineOwnable + +RuleEngineOwnable2Step +├── RuleEngineOwnableShared → no gasless support │ └── RuleEngineBase └── Ownable2Step (OZ) → ERC-173 + +RuleEngineOwnable2Step2771 +├── ERC2771ModuleStandalone → gasless support +└── RuleEngineOwnable2Step ``` ### Access Control Pattern @@ -114,7 +136,7 @@ function _onlyTokenBindingManager() internal virtual; // wired by ERC3643ComplianceModule to its own abstract hook: function _onlyComplianceManager() internal virtual; -// RuleEngine overrides with RBAC: +// RuleEngine (and RuleEngine2771, which extends it) overrides with RBAC: function _onlyRulesManager() internal virtual override onlyRole(RULES_MANAGEMENT_ROLE) {} function _onlyRulesLimitManager() internal virtual override onlyRole(DEFAULT_ADMIN_ROLE) {} function _onlyComplianceManager() internal virtual override onlyRole(COMPLIANCE_MANAGER_ROLE) {} @@ -131,21 +153,29 @@ function _onlyComplianceManager() internal virtual override onlyOwner {} Rule validation uses a two-layer override: -1. **`RulesManagementModule._checkRule()`** — checks zero address + duplicates +1. **`RulesManagementModule._checkRule()`** — checks the zero address (duplicates are rejected by `_addRule` through the return value of `_rules.add`) 2. **`RuleEngineBase._checkRule()`** — calls `RulesManagementModule._checkRule()` then validates ERC-165 interface ```solidity // RulesManagementModule (generic checks): function _checkRule(address rule_) internal view virtual { - if (rule_ == address(0x0)) revert ...ZeroNotAllowed(); - if (_rules.contains(rule_)) revert ...AlreadyExists(); + require(rule_ != address(0), RuleEngine_RulesManagementModule_RuleAddressZeroNotAllowed()); } +// RulesManagementModule._addRule (duplicate check): +require(_rules.add(address(rule_)), RuleEngine_RulesManagementModule_RuleAlreadyExists()); + // RuleEngineBase (adds ERC-165 check): function _checkRule(address rule_) internal view virtual override { RulesManagementModule._checkRule(rule_); - if (!ERC165Checker.supportsInterface(rule_, RuleInterfaceId.IRULE_INTERFACE_ID)) - revert RuleEngine_RuleInvalidInterface(); + require(_supportsRuleInterface(rule_), RuleEngine_RuleInvalidInterface()); +} + +// ERC-165 support checked once, then the current IRule ID, then the legacy (pre-rc7) one: +function _supportsRuleInterface(address rule_) internal view virtual returns (bool) { + if (!ERC165Checker.supportsERC165(rule_)) return false; + return ERC165Checker.supportsERC165InterfaceUnchecked(rule_, RuleInterfaceId.IRULE_INTERFACE_ID) + || ERC165Checker.supportsERC165InterfaceUnchecked(rule_, RuleInterfaceId.IRULE_LEGACY_INTERFACE_ID); } ``` @@ -214,7 +244,7 @@ This gives O(1) add/remove/contains and iterable storage. | Interface | Purpose | Where Defined | |-----------|---------|---------------| -| `IRule` | What every rule must implement (extends `IRuleEngineERC1404`) | `src/interfaces/IRule.sol` | +| `IRule` | What every rule must implement: the six functions the engine calls + ERC-165 (extends `IERC1404Extend`, `IERC3643IComplianceContract`, `IERC165`; no `canTransfer*`) | `src/interfaces/IRule.sol` | | `IRulesManagementModule` | Rule CRUD operations | `src/interfaces/IRulesManagementModule.sol` | | `ITokenBinding` | Token binding registry, standard-agnostic | `src/interfaces/ITokenBinding.sol` | | `ITokenBindingExtended` | Batch binding, token self-binding, `getTokenBounds` | `src/interfaces/ITokenBindingExtended.sol` | @@ -222,7 +252,7 @@ This gives O(1) add/remove/contains and iterable storage. | `IRuleEngine` | Full CMTAT integration interface | `lib/CMTAT/contracts/interfaces/engine/IRuleEngine.sol` | **ERC-165 interface IDs:** -- `IRule`: `0x2497d6cb` (`src/modules/library/RuleInterfaceId.sol`) +- `IRule`: `0xb1a69752` (`src/modules/library/RuleInterfaceId.sol`). Narrowed in rc7 (was `0x2497d6cb`, which also covers `canTransfer` / `canTransferFrom`); the engine accepts both, the legacy one as `IRULE_LEGACY_INTERFACE_ID` (`RuleEngineBase._supportsRuleInterface`) - `IERC3643Compliance`: `0x3144991c`, extended: `0x646ba2be`, `IERC7551Compliance`: `0x7157797f` (`ComplianceInterfaceId.sol`) - `IERC1404`: `0xab84a5c8` (`ERC1404InterfaceId.sol`) - `IRuleEngine`: from `CMTAT/library/RuleEngineInterfaceId.sol` @@ -253,9 +283,14 @@ Errors, events, and role constants are centralized in "invariant storage" abstra ``` src/ ├── deployment/ -│ ├── RuleEngine.sol # RBAC variant (deploy this) -│ ├── RuleEngineOwnable.sol # Ownable variant (deploy this) -│ └── RuleEngineOwnable2Step.sol # Ownable2Step variant (deploy this) +│ ├── accessControl/ +│ │ ├── RuleEngine.sol # RBAC variant, no ERC-2771 (deploy this) +│ │ └── RuleEngine2771.sol # RBAC variant with ERC-2771 (deploy this) +│ └── ownable/ +│ ├── RuleEngineOwnable.sol # Ownable variant, no ERC-2771 (deploy this) +│ ├── RuleEngineOwnable2771.sol # Ownable variant with ERC-2771 (deploy this) +│ ├── RuleEngineOwnable2Step.sol # Ownable2Step variant, no ERC-2771 (deploy this) +│ └── RuleEngineOwnable2Step2771.sol # Ownable2Step variant with ERC-2771 (deploy this) ├── RuleEngineBase.sol # Abstract core logic (do not deploy) ├── RuleEngineOwnableShared.sol # Shared logic for ownable variants ├── interfaces/ # IRule, IRulesManagementModule, ITokenBinding(Extended), IERC3643Compliance(Extended) @@ -270,8 +305,13 @@ test/ ├── HelperContractOwnable2Step.sol # Base helper for RuleEngineOwnable2Step tests ├── utils/ # CMTAT deployment helpers ├── RuleEngine/ # Tests for RuleEngine (RBAC) +├── RuleEngine2771/ # Tests for RuleEngine2771 (RBAC + ERC-2771) ├── RuleEngineOwnable/ # Tests for RuleEngineOwnable ├── RuleEngineOwnable2Step/ # Tests for RuleEngineOwnable2Step +├── RuleEngineOwnable2771/ # Tests for RuleEngineOwnable2771 +├── RuleEngineOwnable2Step2771/ # Tests for RuleEngineOwnable2Step2771 +├── ERC3643Real/ # Real T-REX token tests (FOUNDRY_PROFILE=erc3643 only) +├── RuleStandalone/ # A rule set directly as a CMTAT token's rule engine (no RuleEngine) └── RuleWhitelist/ # Tests for the whitelist mock rule script/ # Foundry example/deployment scripts @@ -284,12 +324,15 @@ For detailed test conventions, templates, helper contracts, test addresses, nami Key points: - Tests for `RuleEngine` go in `test/RuleEngine/`, tests for `RuleEngineOwnable` go in `test/RuleEngineOwnable/` - Tests for `RuleEngineOwnable2Step` go in `test/RuleEngineOwnable2Step/` +- Tests for each `*2771` contract go in its own `test//` directory (`RuleEngine2771`, `RuleEngineOwnable2771`, `RuleEngineOwnable2Step2771`) - Use `HelperContract` for RBAC tests, `HelperContractOwnable` for Ownable tests - Use `HelperContractOwnable2Step` for `RuleEngineOwnable2Step` tests - Always use specific error selectors in `vm.expectRevert()` - When adding a feature to `RuleEngineBase`, add tests for **all deployable variants** +- Behaviour shared by the variants is tested once in an abstract base under `test/utils/` (`ERC2771TokenGateTestBase`, `ERC2771VariantTestBase`, `NoForwarderTestBase`, `RuleAggregationTestBase`, `RuleEngineInvariantTestBase`), with a short per-variant file in each `test/RuleEngine*/` directory that only deploys the variant +- Before trusting a new test, check it can fail: break the line it guards and run the suite (the rc7 code-quality review mutation-tests the suite this way) -## RBAC Roles (RuleEngine only) +## RBAC Roles (RuleEngine and RuleEngine2771) | Role | Identifier | Purpose | |------|-----------|---------| @@ -300,12 +343,14 @@ Key points: ## Key Invariants 1. **Only bound tokens** can call `transferred()`, `created()`, `destroyed()` -2. **Rules are validated via ERC-165** before being added — they must support `IRULE_INTERFACE_ID` +2. **Rules are validated via ERC-165** before being added — they must support `IRULE_INTERFACE_ID` or the legacy `IRULE_LEGACY_INTERFACE_ID` 3. **No duplicate rules** — `EnumerableSet` prevents this 4. **No zero-address rules** — checked in `_checkRule` -5. **Admin has all roles** in `RuleEngine` (the `hasRole` override) -6. **Forwarder is immutable** — set at construction, cannot be changed -7. **Rule contracts in `src/mocks/` are reference implementations** — they are useful for testing and examples, not as production rule contracts. Production rules live in a [separate repository](https://github.com/CMTA/Rules). +5. **Admin has all roles** in `RuleEngine` and `RuleEngine2771` (the `hasRole` override in `RuleEngine`, inherited by `RuleEngine2771`) +6. **Forwarder is immutable** — set at construction, cannot be changed (the three `*2771` contracts; the others have none) +7. **Token identity uses `msg.sender`, never `_msgSender()`** — `_checkBoundToken` (`onlyBoundToken`) and the token self-binding check in `_authorizeTokenBindingChange` compare the raw caller so the ERC-2771 forwarder cannot pass as a token; administrative checks keep `_msgSender()` (gasless admin). Pinned by `test/utils/ERC2771TokenGateTestBase.sol` +8. **Rules and bound tokens are disjoint** — `RuleEngineBase._checkBindingTarget` rejects binding a current rule and `_checkRule` rejects adding a bound token as a rule, both with `RuleEngine_RulesManagementModule_RuleAccountCannotReceivePrivileges`. Pinned by `invariant_RulesAndBoundTokensAreDisjoint` +9. **Rule contracts in `src/mocks/` are reference implementations** — they are useful for testing and examples, not as production rule contracts. Production rules live in a [separate repository](https://github.com/CMTA/Rules). ## Solidity Style @@ -314,7 +359,7 @@ Key points: - Function ordering: constructor, receive, fallback, external, public, internal, private (view/pure last within each group) - Function declaration order: visibility, mutability, virtual, override, custom modifiers - All `internal` functions must be marked `virtual`, so inheriting contracts can override them. -- Use `require(condition, CustomError(...))` for custom errors; avoid direct `revert CustomError(...)`. +- Use `require(condition, CustomError(...))` for custom errors; avoid direct `revert CustomError(...)`. `src/` has no conditional `revert` left (the only two are the unconditional ones of `RuleOperationRevertMock`). Note that `require` evaluates the error's arguments even when the check passes: an argument read from storage costs an extra read, so cache it in a local first (see `RulesManagementModule.addRule`). - In `src/`, avoid `super` calls and prefer explicit parent-contract calls (e.g., `AccessControl.grantRole(...)`) for readability and deterministic inheritance behavior. - Section headers: `/* ============ SECTION ============ */` - **No emoji in code comments or NatSpec.** Use a plain word marker instead: `WARNING:`, `NOTE:`, `IMPORTANT:`. Emoji render inconsistently across editors, terminals, `forge doc` output and diffs; they are not searchable (`grep WARNING` finds the marker, `grep ⚠️` depends on the shell); and they encode as multi-byte sequences that can be silently mangled by tooling. This applies to `src/`, `test/` and `script/`. Markdown documentation may use emoji freely — the restriction is Solidity comments only. @@ -327,16 +372,17 @@ Key points: 2. Create an invariant storage contract in `src/modules/library/` for errors/events 3. Add a virtual access control hook (e.g., `_onlyNewManager()`) 4. Have `RuleEngineBase` inherit the module -5. Override the hook in both `RuleEngine` and `RuleEngineOwnable` -6. Add tests in `test/RuleEngine/`, `test/RuleEngineOwnable/`, and `test/RuleEngineOwnable2Step/` +5. Override the hook in `RuleEngine`, `RuleEngineOwnable` and `RuleEngineOwnable2Step` +6. Add tests for all six deployables (one directory each under `test/`), preferably through a shared `test/utils/*TestBase.sol` ### Adding a new rule (mock) 1. Create the rule in `src/mocks/rules/` -2. Implement `IRule` (which extends `IRuleEngineERC1404`) +2. Implement `IRule`; to also support the standalone role (set directly as a CMTAT token's rule engine), implement CMTAT's `IRuleEngineERC1404` too and advertise `RULE_ENGINE_INTERFACE_ID`. The 4-argument `transferred` then needs `override(IRule, IRuleEngine)` 3. Implement ERC-165 with `IRULE_INTERFACE_ID` -4. Add tests using the existing `HelperContract` base +4. `transferred*` hooks may update the rule's own storage but must not make a state-changing external call; external reads must be `view` (`STATICCALL`). Six CMTAT variants have no reentrancy guard around `transferred` (see `doc/technical/RuleEngine-with-CMTAT.md` §4.6). A rule can also be set directly as a CMTAT token's rule engine (§4.8): keep `canTransfer*` consistent with `detectTransferRestriction*`, and a production stateful rule must restrict who calls `transferred` +5. Add tests using the existing `HelperContract` base ### Modifying access control 1. Update the virtual hook in the relevant module -2. Update overrides in **both** `RuleEngine.sol` and `RuleEngineOwnable.sol` +2. Update overrides in `RuleEngine.sol`, `RuleEngineOwnable.sol` and `RuleEngineOwnable2Step.sol` 3. Update tests in all affected test directories diff --git a/README.md b/README.md index 775744c4..f08b88ab 100644 --- a/README.md +++ b/README.md @@ -4,26 +4,39 @@ RuleEngine applies transfer restrictions to [CMTAT](https://github.com/CMTA/CMTA It is an *external controller*: the token calls the engine on every transfer, mint and burn, and the engine forwards the call to a configurable list of pluggable rule contracts. This keeps compliance logic out of the token, lets each issuer compose the rules they need, and avoids growing the token's already large bytecode. -- **Version:** 3.0.0 -- **Solidity:** ^0.8.20 (compiled with 0.8.36) -- **EVM target:** Prague +- **Version:** 3.0.0-rc7 (`version()` returns `"3.0.0-rc7"`) +- **Solidity:** ^0.8.27 (compiled with 0.8.37; 0.8.27 is the first version supporting `require` with a custom error on the legacy pipeline) +- **EVM target:** Osaka (Fusaka upgrade) - **License:** MPL-2.0 **Full documentation: [doc/README.md](./doc/README.md)** — interfaces, Ethereum API, deployment, UML and call graphs, audits, and toolchain usage. > This project has not undergone an audit and is provided as-is without any warranties. +## CMTAT compatibility + +| RuleEngine | CMTAT | Tested against | +|---|---|---| +| **v3.0.0-rc7** (this version) | ≥ v3.0.0 | v3.0.0 (last audited CMTAT release) and v3.3.0-rc4 (target version) | +| earlier v3.0.0 release candidates | ≥ v3.0.0 | their target version, see [doc/README.md § Compatibility](./doc/README.md#compatibility) | +| [v1.0.2.1](https://github.com/CMTA/RuleEngine/releases/tag/v1.0.2.1) | v2.3.0 (audited) | — | + +For a **CMTAT v3.0.0** token, use RuleEngine **v3.0.0-rc7**: it is tested against that version (v1.0.2.1 is for CMTAT v2 only). Up to CMTAT v3.2.0, mint and burn reach the engine without the operator, so spender-keyed rules (per-minter mint allowance) do not apply to them; see [doc/README.md § CMTAT v3.0.0](./doc/README.md#cmtat-v300). + ## Contract Variants -Three deployable contracts share the same core logic and differ only in access control: +Six deployable contracts share the same core logic and differ only in access control and ERC-2771 support. Each access-control model comes in two versions: without ERC-2771, and with an immutable trusted forwarder (`*2771`): -| Contract | Access Control | Use Case | -|----------|---------------|----------| -| `RuleEngine` | Role-based (`AccessControlEnumerable`) | Multi-operator environments with granular permissions | -| `RuleEngineOwnable` | ERC-173 `Ownable` | Single-owner setups, simpler administration | -| `RuleEngineOwnable2Step` | ERC-173 `Ownable2Step` | Single-owner setups with safer ownership handover | +| Contract | Access Control | ERC-2771 (gasless) | Use Case | +|----------|---------------|--------------------|----------| +| `RuleEngine` | Role-based (`AccessControlEnumerable`) | No | Multi-operator environments with granular permissions | +| `RuleEngine2771` | Role-based (`AccessControlEnumerable`) | Yes (immutable trusted forwarder) | Same, with administration through meta-transactions | +| `RuleEngineOwnable` | ERC-173 `Ownable` | No | Single-owner setups, simpler administration | +| `RuleEngineOwnable2771` | ERC-173 `Ownable` | Yes (immutable trusted forwarder) | Same, with administration through meta-transactions | +| `RuleEngineOwnable2Step` | ERC-173 `Ownable2Step` | No | Single-owner setups with safer ownership handover | +| `RuleEngineOwnable2Step2771` | ERC-173 `Ownable2Step` | Yes (immutable trusted forwarder) | Same, with administration through meta-transactions | -All three support ERC-1404 transfer restrictions, the ERC-3643 compliance interface, ERC-2771 meta-transactions (gasless), and multiple token bindings. +All of them support ERC-1404 transfer restrictions, the ERC-3643 compliance interface and multiple token bindings. > **Warning (shared engine across multiple tokens):** one RuleEngine instance can be bound to several tokens, but they must be equally trusted and governed together. ERC-3643 callbacks do not pass the token address to rules, so stateful rules are not safe for mutually untrusted tokens sharing an engine. @@ -40,7 +53,7 @@ The token calls the engine on every transfer, mint and burn. The engine checks t | CMTAT | `transferred(from, to, value)` | `transferred(spender, …)` | `transferred(spender, …)` | `transferred(spender, …)` | | ERC-3643 | `transferred(from, to, value)` | `transferred(from, to, value)` | `created(to, value)` | `destroyed(from, value)` | -CMTAT picks the overload according to whether the operation has a spender. A plain `transfer` has none, so CMTAT calls the 3-argument `transferred(from, to, value)` — the engine is never called with a zero spender. `transferFrom`, `mint` and `burn` do have one (`_msgSender()`), so those call the 4-argument `transferred(spender, from, to, value)`. Whichever entry point is used, the engine then runs the same rule loop. +CMTAT picks the overload according to whether the operation has a spender. A plain `transfer` has none, so CMTAT calls the 3-argument `transferred(from, to, value)` — the engine is never called with a zero spender. `transferFrom`, `mint` and `burn` do have one (`_msgSender()`), so those call the 4-argument `transferred(spender, from, to, value)` — as do `batchMint`, `batchBurn`, `burnFrom`, cross-chain mint/burn and the minter `batchTransfer` (where `spender == from`). CMTAT's `forcedTransfer` does not call the engine at all. Whichever entry point is used, the engine then runs the same rule loop. The complete per-operation table is in [doc/technical/RuleEngine-with-CMTAT.md](./doc/technical/RuleEngine-with-CMTAT.md#2-which-entry-points-cmtat-uses). The view path, `detectTransferRestriction()`, iterates the same rules and returns the first non-zero ERC-1404 restriction code instead of reverting. @@ -58,9 +71,12 @@ RuleEngineBase (abstract) — core logic, shared by all variants │ └── TokenBindingExtendedModule — batch binding, token self-binding └── IRuleEngineERC1404 — CMTAT interface -RuleEngine = RuleEngineBase + AccessControl + ERC2771ModuleStandalone -RuleEngineOwnable = RuleEngineOwnableShared + Ownable + ERC2771ModuleStandalone -RuleEngineOwnable2Step = RuleEngineOwnableShared + Ownable2Step + ERC2771ModuleStandalone +RuleEngine = RuleEngineBase + AccessControlEnumerable +RuleEngine2771 = RuleEngine + ERC2771ModuleStandalone +RuleEngineOwnable = RuleEngineOwnableShared + Ownable +RuleEngineOwnable2771 = RuleEngineOwnable + ERC2771ModuleStandalone +RuleEngineOwnable2Step = RuleEngineOwnableShared + Ownable2Step +RuleEngineOwnable2Step2771 = RuleEngineOwnable2Step + ERC2771ModuleStandalone ``` Token binding is deliberately split in two layers: `TokenBindingModule` / `TokenBindingExtendedModule` hold the whole registry (storage, `bindToken` / `unbindToken` / `isTokenBound`, batch binding, self-binding, the `onlyBoundToken` guard) and depend on nothing but OpenZeppelin, so they can be reused by any project that has to bind tokens; `ERC3643ComplianceModule` / `ERC3643ComplianceExtendedModule` are thin ERC-3643 adapters on top, adding `getTokenBound()` and the compliance-manager vocabulary. `src/mocks/TokenBindingStandaloneMock.sol` shows the registry used on its own, outside any compliance context. @@ -73,10 +89,15 @@ Modules declare access control as **virtual internal hooks** (`_onlyRulesManager src/ ├── RuleEngineBase.sol # abstract core logic (not deployable) ├── RuleEngineOwnableShared.sol # shared logic for the two ownable variants -├── deployment/ # the three deployable contracts -│ ├── RuleEngine.sol -│ ├── RuleEngineOwnable.sol -│ └── RuleEngineOwnable2Step.sol +├── deployment/ # the six deployable contracts, one directory per access-control model +│ ├── accessControl/ # RBAC (AccessControlEnumerable) +│ │ ├── RuleEngine.sol +│ │ └── RuleEngine2771.sol +│ └── ownable/ # ERC-173 (Ownable / Ownable2Step) +│ ├── RuleEngineOwnable.sol +│ ├── RuleEngineOwnable2771.sol +│ ├── RuleEngineOwnable2Step.sol +│ └── RuleEngineOwnable2Step2771.sol ├── interfaces/ # IRule, IRulesManagementModule, ITokenBinding(Extended), │ # IERC3643Compliance(Extended) ├── modules/ # VersionModule, RulesManagementModule, TokenBinding(Extended)Module, @@ -95,25 +116,30 @@ doc/ # full documentation, schemas, coverage, aud Production rules are maintained at [github.com/CMTA/Rules](https://github.com/CMTA/Rules), in two families: -- **Validation rules (read-only)** — evaluate eligibility without mutating state: `RuleWhitelist`, `RuleBlacklist`, `RuleSanctionList`, `RuleIdentityRegistry`, `RuleSpenderWhitelist`, `RuleERC2980`, `RuleMaxTotalSupply` -- **Operation rules (read-write)** — may update rule state on transfer: `RuleConditionalTransferLight` +- **Validation rules (read-only)** — evaluate eligibility without mutating state: `RuleWhitelist`, `RuleWhitelistWrapper`, `RuleReceiverWhitelist`, `RuleBlacklist`, `RuleSanctionsList`, `RuleIdentityRegistry`, `RuleSpenderWhitelist`, `RuleERC2980`, `RuleMaxTotalSupply` / `RuleMaxTotalSupplyERC3643`, `RuleMaxBalance`, `RuleChainlinkPoR` / `RuleChainlinkPoRERC3643` +- **Operation rules (read-write)** — may update rule state on transfer: `RuleConditionalTransferLight`, `RuleMintAllowance`, and `RuleConditionalTransferLightMultiToken` (set directly on each token, never behind a RuleEngine) -To be usable by the engine, a rule must implement `IRule` and advertise it through ERC-165. Restriction codes should stay unique across the composed rule set. +The Rules repository is the source of truth for this list; see [doc/README.md § Available Rules](./doc/README.md#available-rules) for details and caveats: restriction codes, ERC-3643 support per rule, rules that protect one token per instance, and how to bind the operation rules to the engine. + +To be usable by the engine, a rule must implement `IRule` and advertise it through ERC-165 (`0xb1a69752` since v3.0.0-rc7; the older `0x2497d6cb`, which also covers `canTransfer` / `canTransferFrom` and is advertised by Rules up to v0.6.0, is still accepted). Restriction codes should stay unique across the composed rule set. ## Quick start Dependencies are git submodules. ```bash -git submodule update --init --recursive # or: forge install -cd lib/CMTAT && npm install && cd ../.. # CMTAT's own OpenZeppelin deps +git submodule update --init # non-recursive is enough: remappings.txt resolves OpenZeppelin + # to this repo's own submodules, including for the CMTAT sources forge build # compile forge test # run the test suite +FOUNDRY_PROFILE=erc3643 forge test # tests against the real ERC-3643 token (T-REX 4.2.0-beta1, solc 0.8.30) forge coverage # code coverage forge fmt # format ``` +`--recursive` and `cd lib/CMTAT && npm install` are only needed to run CMTAT's own Hardhat suite from inside `lib/CMTAT`. + See [doc/README.md](./doc/README.md) for deployment scripts, the production deployment checklist, and Hardhat usage. Parts of this project were written with the help of AI coding assistants, principally Claude Code (Anthropic) and Codex (OpenAI). diff --git a/doc/README.md b/doc/README.md index 11909631..421df885 100644 --- a/doc/README.md +++ b/doc/README.md @@ -58,25 +58,29 @@ The RuleEngine is an external contract used to apply transfer restrictions to an ## Contract Variants -Three deployable contracts are available: +Six deployable contracts are available. Each access-control model comes without ERC-2771 and with it (`*2771`, immutable trusted forwarder): | Contract | Access Control | Interface | Use Case | |----------|---------------|-----------|----------| -| `RuleEngine` | Role-Based (AccessControlEnumerable) | RBAC roles | Multi-operator environments with granular permissions | -| `RuleEngineOwnable` | ERC-173 Ownership | `Ownable` | Single-owner setups, simpler administration | -| `RuleEngineOwnable2Step` | ERC-173 Ownership (two-step transfer) | `Ownable2Step` | Single-owner setups with safer ownership handover | +| `RuleEngine` | Role-Based (AccessControlEnumerable) | RBAC roles | Multi-operator environments with granular permissions, no ERC-2771 | +| `RuleEngine2771` | Role-Based (AccessControlEnumerable) | RBAC roles + ERC-2771 | Same as `RuleEngine`, administrable through an immutable trusted forwarder (gasless) | +| `RuleEngineOwnable` | ERC-173 Ownership | `Ownable` | Single-owner setups, simpler administration, no ERC-2771 | +| `RuleEngineOwnable2771` | ERC-173 Ownership | `Ownable` + ERC-2771 | Same as `RuleEngineOwnable`, administrable through a trusted forwarder (gasless) | +| `RuleEngineOwnable2Step` | ERC-173 Ownership (two-step transfer) | `Ownable2Step` | Single-owner setups with safer ownership handover, no ERC-2771 | +| `RuleEngineOwnable2Step2771` | ERC-173 Ownership (two-step transfer) | `Ownable2Step` + ERC-2771 | Same as `RuleEngineOwnable2Step`, administrable through a trusted forwarder (gasless) | ERC-3643 compliance specification indicates the use of ERC-173. > The standard relies on ERC-173 to define contract ownership, with the owner having the responsibility of setting the Compliance parameters and binding the Compliance to a Token contract. -All deployable contracts share the same core functionality (`RuleEngineBase`, directly or through `RuleEngineOwnableShared`) and support: +All deployable contracts share the same core functionality (`RuleEngineBase`, extended directly by `RuleEngine` or through `RuleEngineOwnableShared`) and support: - ERC-1404 transfer restrictions - ERC-3643 compliance interface -- ERC-2771 meta-transactions (gasless) - Multiple token bindings +ERC-2771 meta-transactions (gasless) are supported by the three `*2771` contracts only. `RuleEngine`, `RuleEngineOwnable` and `RuleEngineOwnable2Step` have no trusted forwarder: every caller is the raw `msg.sender`. Pick the `*2771` version of an access-control model only when its operators should administer the engine through a forwarder. + > **Warning (shared engine across multiple tokens):** A "multi-tenant" setup here means one RuleEngine instance is shared by several token contracts (all bound through `bindToken`). In this setup, tokens must be equally trusted and governed together. ERC-3643 callbacks (`transferred`, `created`, `destroyed`) do not pass the token address to rules, so stateful/accounting rules are not safe for mutually untrusted tokens sharing the same engine. ## Motivation @@ -93,7 +97,7 @@ There are several reasons to do this: - The RuleEngine can be used inside other contracts besides CMTAT. For instance, the RuleEngine has been used in [our contract to distribute dividends](https://www.taurushq.com/blog/equity-tokenization-how-to-pay-dividend-on-chain-using-cmtat/). - - A same deployed `RuleEngine` can also be used with several different tokens if the rules allow it, which is the case for all read-only rules. + - A same deployed `RuleEngine` can also be used with several different tokens if the rules allow it. This is the case for most read-only rules, but not for the supply and balance caps (`RuleMaxTotalSupply`, `RuleChainlinkPoR`, `RuleMaxBalance`), which read one token configured at deployment, nor for the operation rules. See [Available Rules](#available-rules). Why use this `RuleEngine` contract instead of setting the `rule` directly in the token contract? @@ -101,7 +105,9 @@ Why use this `RuleEngine` contract instead of setting the `rule` directly in the When may the use of `RuleEngine` not be appropriate? -- If you plan to call only one rule (e.g a whitelist rule), it could make sense to directly set the rule in the token contract instead of using a RuleEngine. This will simplify configuration and reduce runtime gas costs. +- If you plan to call only one rule (e.g a whitelist rule), it could make sense to directly set the rule in the token contract instead of using a RuleEngine. This will simplify configuration and reduce runtime gas costs. Two exceptions: + - **ERC-3643 tokens need the engine.** The token calls `bindToken` from `setCompliance`, and `created` / `destroyed` on mint and burn. The engine implements the full compliance surface; most rules (all validation rules) do not, so `setCompliance(rule)` or a later mint/burn reverts. + - **Some rules must be set directly on the token.** [`RuleConditionalTransferLightMultiToken`](https://github.com/CMTA/Rules/blob/main/doc/technical/contracts/RuleConditionalTransferLightMultiToken.md) keys its approvals on the calling token (`msg.sender`); behind an engine the caller is the engine, so every transfer reverts or approvals are stranded. See [Available Rules](#available-rules). ## How it works @@ -114,7 +120,7 @@ _Diagram source: [doc/schema/plantuml/ruleengine-overview.puml](./schema/plantum 1. The token holders initiate a transfer transaction on the token contract. -2. The transfer function inside the token calls the ERC-3643 function `transferred` from the RuleEngine with the following parameters inside: `from, to, value`. +2. The transfer function inside the token calls the RuleEngine: `transferred(from, to, value)` for a plain transfer, `transferred(spender, from, to, value)` for any CMTAT operation with an operator (`transferFrom`, mint, burn), or `created` / `destroyed` for an ERC-3643 mint / burn. See [Like CMTAT](#like-cmtat) for the complete routing. 3. The Rule Engine calls each rule separately. If the transfer is not authorized by the rule, the rule must directly revert (no return value). CMTAT and ERC-3643 tokens use **disjoint entry points** on the RuleEngine, so each has its own sequence diagram. The 4-argument `transferred(spender, from, to, value)` is declared by CMTAT's `IRuleEngine` and is never reached by an ERC-3643 token; conversely `created` / `destroyed` are declared by `IERC3643Compliance` and are never called by CMTAT. Only the 3-argument `transferred(from, to, value)` is shared. @@ -141,12 +147,16 @@ _Diagram source: [doc/schema/plantuml/ruleengine-flow-erc3643.puml](./schema/pla | RuleEngine version | Compatible Versions | | ------------------------------------------------------------ | ------------------------------------------------------------ | +| **v3.0.0-rc7** | CMTAT ≥ v3.0.0
CMTAT target version: [v3.3.0-rc4](https://github.com/CMTA/CMTAT/releases/tag/v3.3.0-rc4) | +| **v3.0.0-rc6** | CMTAT ≥ v3.0.0
CMTAT target version: [v3.3.0-rc3](https://github.com/CMTA/CMTAT/releases/tag/v3.3.0-rc3) | +| **v3.0.0-rc5** | CMTAT ≥ v3.0.0
CMTAT target version: [v3.3.0-rc3](https://github.com/CMTA/CMTAT/releases/tag/v3.3.0-rc3) | | **v3.0.0-rc4** | CMTAT ≥ v3.0.0
CMTAT target version: [v3.3.0-rc1](https://github.com/CMTA/CMTAT/releases/tag/v3.3.0-rc1) | -| **v3.0.0-rc3** | CMTAT ≥ v3.0.0
CMTAT target version: [v3.3.0](https://github.com/CMTA/CMTAT/releases/tag/v3.3.0) | | **v3.0.0-rc2** | CMTAT ≥ v3.0.0
CMTAT target version: [v3.2.0](https://github.com/CMTA/CMTAT/releases/tag/v3.2.0) | | **[v1.0.2.1](https://github.com/CMTA/RuleEngine/releases/tag/v1.0.2.1)** | CMTAT v2.3.0 (audited) | -#### CMTAT v3.0.0 +> **Note (CMTAT v3.0.0 – v3.2.0):** the engine works with every CMTAT ≥ v3.0.0, but on v3.0.0 – v3.2.0 mint, burn and the minter `batchTransfer` reach the engine on the **3-argument** `transferred` (no spender). Spender-keyed rules (a per-minter mint allowance, minter screening) are therefore inert on those versions. The 4-argument routing of mint and burn starts with CMTAT v3.3.0, see [CMTAT v3.0.0](#cmtat-v300) and [Like CMTAT](#like-cmtat). + +#### CMTAT ≥ v3.0.0 CMTAT provides the following function to set a RuleEngine inside a CMTAT token: @@ -156,6 +166,16 @@ setRuleEngine(IRuleEngine ruleEngine_) This function is defined in the extension module `ValidationModuleRuleEngine` +#### CMTAT v3.0.0 + +CMTAT v3.0.0, the last audited CMTAT release, is the oldest version the engine supports, and is tested against it (`lib/CMTATv3.0.0`). The engine needs no change, but the token routes operations differently from v3.3.0: + +- `transfer` → 3-argument `transferred(from, to, value)`; `transferFrom` → 4-argument `transferred(spender, from, to, value)`, as on later versions. +- `mint` / `burn` (and their batch, cross-chain and `burnFrom` forms, and the minter `batchTransfer`) → **3-argument**, with no operator. Since v3.3.0 they take the 4-argument overload. +- Consequence: a spender-keyed rule (per-minter mint allowance, minter screening) is inert on mint and burn up to v3.2.0, while rules enforced on the 3-argument path apply normally. + +Table, consequences and tests: [RuleEngine-with-CMTAT.md §CMTAT v3.0.0](./technical/RuleEngine-with-CMTAT.md#cmtat-v300). Pinned by `test/RuleEngine/RulesManagementModuleTest/CMTATOperationRoutingV3.t.sol`. + #### ERC-3643 token [ERC-3643](https://eips.ethereum.org/EIPS/eip-3643) defined the following function in the standard interface to set a compliance contract @@ -205,46 +225,76 @@ Recommended operational sequence: While the RuleEngine has been designed for CMTAT and ERC-3643 tokens, it can be used with other contracts to apply transfer restrictions. -For that, the only thing to do is to import in your contract the interface `IRuleEngine`(CMTAT) or `IERC3643Compliance` (ERC-3643), which declares the corresponding functions to call by the token contract. This interface can be found [here](https://github.com/CMTA/CMTAT/blob/23a1e59f913d079d0c09d32fafbd95ab2d426093/contracts/interfaces/engine/IRuleEngine.sol). +For that, the only thing to do is to import in your contract the interface `IRuleEngine`(CMTAT) or `IERC3643Compliance` (ERC-3643), which declares the corresponding functions to call by the token contract. This interface can be found [here](https://github.com/CMTA/CMTAT/blob/v3.3.0-rc4/contracts/interfaces/engine/IRuleEngine.sol) (CMTAT v3.3.0-rc4, the version this project is tested against; also available locally in `lib/CMTAT/contracts/interfaces/engine/IRuleEngine.sol`). If you need non-standard helper functions (batch bind/unbind, self-binding approval APIs, multi-token getter), use `IERC3643ComplianceExtended`. ### Like CMTAT -Before each ERC-20 transfer, mint, or burn, CMTAT calls the RuleEngine through the internal function `_checkTransferred`, which dispatches to one of two `transferred` overloads depending on whether a non-zero spender is present. +Before each ERC-20 transfer, mint, or burn, CMTAT calls the RuleEngine from `ValidationModuleRuleEngine._transferred` (reached through `_checkTransferred`). The external call is isolated in `_callRuleEngineTransferred`, which dispatches to one of two `transferred` overloads depending on whether a non-zero spender is present. ```solidity -// Called when spender == address(0) +// Called when spender == address(0): direct `transfer` only function transferred(address from, address to, uint256 value) -// Called when spender != address(0) +// Called when spender != address(0): every other operation function transferred(address spender, address from, address to, uint256 value) ``` #### CMTAT v3.3.0 — mint and burn use the spender path -Since CMTAT v3.3.0, **mint and burn operations also go through the 4-argument overload**, with the operator (minter or burner) passed as `spender`: +Since CMTAT v3.3.0, **every operation initiated by an operator goes through the 4-argument overload**, with the operator passed as `spender`. The routing is documented in the `IRuleEngine.transferred` NatSpec since CMTAT v3.3.0-rc4: -| Operation | `spender` | `from` | `to` | -|-----------|-----------|--------|------| -| `transfer` / `transferFrom` | caller / approved spender | token holder | recipient | -| `mint` | minter (`_msgSender()`) | `address(0)` | recipient | -| `burn` | burner (`_msgSender()`) | token holder | `address(0)` | +| Operation | Overload | `spender` | `from` | `to` | +|-----------|----------|-----------|--------|------| +| `transfer` | 3-argument | — | token holder | recipient | +| `transferFrom` | 4-argument | approved spender | token holder | recipient | +| `mint` / `batchMint` / `crosschainMint` / mint leg of `burnAndMint` | 4-argument | minter / bridge (`_msgSender()`) | `address(0)` | recipient | +| `burn` / `batchBurn` / `burnFrom` / self-burn / `crosschainBurn` / burn leg of `burnAndMint` | 4-argument | burner / bridge (`_msgSender()`) | token holder | `address(0)` | +| minter `batchTransfer` | 4-argument | minter (`_msgSender()`) | minter (**`spender == from`**) | recipient | +| `forcedTransfer` (enforcer) | **not called** | — | — | — | -The 3-argument overload is only called when `spender == address(0)`, which does not occur in normal CMTAT v3.3.0 flows. +The 3-argument overload is therefore only called for a direct `transfer`. `forcedTransfer` moves tokens without calling the engine, so stateful rules are not notified (unlike ERC-3643 T-REX, whose `forcedTransfer` notifies compliance). The reference list is CMTAT's [`ruleengine-integration.md`](https://github.com/CMTA/CMTAT/blob/v3.3.0-rc4/doc/technical/ruleengine-integration.md); see also [RuleEngine-with-CMTAT.md §2](./technical/RuleEngine-with-CMTAT.md#2-which-entry-points-cmtat-uses). Up to CMTAT v3.2.0, mint, burn and the minter `batchTransfer` used the 3-argument overload. > **Rule authoring note:** Rules that check the `spender` argument in `transferred(spender, from, to, value)` must explicitly handle the mint (`from == address(0)`) and burn (`to == address(0)`) cases. A spender check that is intended only for `transferFrom` will also fire for mints and burns unless the rule skips it when `from` or `to` is the zero address. See `RuleWhitelist` and `RuleSpenderWhitelist` in the Rules repository for reference implementations. -For example, CMTAT defines the interaction with the RuleEngine inside a specific module, [ValidationModuleRuleEngine](https://github.com/CMTA/CMTAT/blob/master/contracts/modules/wrapper/extensions/ValidationModule/ValidationModuleRuleEngine.sol) and [CMTATBaseRuleEngine](https://github.com/CMTA/CMTAT/blob/master/contracts/modules/1_CMTATBaseRuleEngine.sol). +For example, CMTAT defines the interaction with the RuleEngine inside a specific module, [ValidationModuleRuleEngine](https://github.com/CMTA/CMTAT/blob/v3.3.0-rc4/contracts/modules/wrapper/extensions/ValidationModule/ValidationModuleRuleEngine.sol), and calls it from [CMTATBaseRuleEngine](https://github.com/CMTA/CMTAT/blob/v3.3.0-rc4/contracts/modules/3_CMTATBaseRuleEngine.sol) (code below from CMTAT v3.3.0-rc4). -- ValidationModuleRuleEngine +- `CMTATBaseRuleEngine`: the token's common checks run first, then the RuleEngine hook. -![transferred](./other/CMTAT/transferred.png) +```solidity +function _checkTransferred(address spender, address from, address to, uint256 value) internal virtual override(CMTATBaseCommon) { + CMTATBaseCommon._checkTransferred(spender, from, to, value); + ValidationModuleRuleEngine._transferred(spender, from, to, value); +} +``` -- CMTATBaseRuleEngine +- `ValidationModuleRuleEngine`: the generic module checks (pause, freeze, …) revert on failure, then the engine is called if one is set. The overload is chosen in `_callRuleEngineTransferred`. That function is `virtual`, so the Standard, Snapshot and ERC-7551 variants wrap it in a `nonReentrant` guard. -![checkTransferred](./other/CMTAT/checkTransferred.png) +```solidity +function _transferred(address spender, address from, address to, uint256 value) internal virtual { + _canTransferGenericByModuleAndRevert(spender, from, to); + IRuleEngine ruleEngine_ = ruleEngine(); + if (address(ruleEngine_) != address(0)) { + _callRuleEngineTransferred(ruleEngine_, spender, from, to, value); + } +} + +function _callRuleEngineTransferred( + IRuleEngine ruleEngine_, + address spender, + address from, + address to, + uint256 value +) internal virtual { + if (spender != address(0)) { + ruleEngine_.transferred(spender, from, to, value); + } else { + ruleEngine_.transferred(from, to, value); + } +} +``` -This function `_transferred` is called before each transfer/burn/mint through the internal function `_checkTransferred`. +`_checkTransferred` is called before each transfer, mint and burn. Since CMTAT v3.2.0, `_transferred` no longer returns a `bool` (it did up to v3.1.0): a rejected operation reverts in the module checks or in the engine itself. ### Like ERC-3643 @@ -271,11 +321,12 @@ function destroyed(address from, uint256 value) external; ### CMTAT -The `RuleEngine` base interface is defined in the CMTAT repository. +The `RuleEngine` base interface is defined in the CMTAT repository ([`IRuleEngine.sol`](https://github.com/CMTA/CMTAT/blob/v3.3.0-rc4/contracts/interfaces/engine/IRuleEngine.sol)). -![cmtat_surya_inheritance_IRuleEngine.sol](./schema/cmtat_surya_inheritance_IRuleEngine.sol.png) +- `IRuleEngine` extends `IERC7551Compliance` (which extends `IERC3643ComplianceRead`), `IERC3643IComplianceContract` and `IERC165`. +- `IRuleEngineERC1404` extends `IERC1404Extend` (which extends `IERC1404`) and `IRuleEngine`. The engine implements this one, since the token exposes ERC-1404. -It inherits from several others interfaces: `IERC1404`, `IERC1404Extend`, `IERC7551Compliance`, `IERC3643ComplianceContract` +Since CMTAT v3.2.0, `IRuleEngine` no longer extends `IERC1404Extend`. See the [IRuleEngine](#iruleengine) section for its sol2uml diagram. ```solidity // IRuleEngine @@ -345,21 +396,21 @@ The RuleEngine modules are split as follows: The toolchain includes the following components, where the versions are the latest ones that we tested: -- Foundry (forge-std) [v1.14.0](https://github.com/foundry-rs/forge-std/releases/tag/v1.14.0) -- Solidity [0.8.36](https://docs.soliditylang.org/en/v0.8.36/) -- OpenZeppelin Contracts (submodule) [v5.6.1](https://github.com/OpenZeppelin/openzeppelin-contracts/releases/tag/v5.6.1) -- CMTAT [v3.3.0](https://github.com/CMTA/CMTAT/releases/tag/v3.3.0) +- Foundry (forge-std) [v1.17.0](https://github.com/foundry-rs/forge-std/releases/tag/v1.17.0) +- Solidity [0.8.37](https://docs.soliditylang.org/en/v0.8.37/) +- OpenZeppelin Contracts (submodule) [v5.7.0](https://github.com/OpenZeppelin/openzeppelin-contracts/releases/tag/v5.7.0) +- CMTAT [v3.3.0-rc4](https://github.com/CMTA/CMTAT/releases/tag/v3.3.0-rc4) ### Access Control Two access control mechanisms are available depending on which contract you deploy: -#### RuleEngine (RBAC - AccessControlEnumerable) +#### RuleEngine and RuleEngine2771 (RBAC - AccessControlEnumerable) -The `RuleEngine` contract uses Role-Based Access Control (RBAC) via OpenZeppelin's `AccessControlEnumerable`. +The `RuleEngine` and `RuleEngine2771` contracts use Role-Based Access Control (RBAC) via OpenZeppelin's `AccessControlEnumerable`, wired once in `RuleEngine`; `RuleEngine2771` extends it. They differ only in ERC-2771 support. Each module defines the roles useful to restrict its functions. The contract overrides the OpenZeppelin function `hasRole` to give by default all the roles to the `admin`. -`RulesManagementModule` itself is access-control agnostic; RBAC is wired at the concrete `RuleEngine` level. +`RulesManagementModule` itself is access-control agnostic; RBAC is wired in `RuleEngine`. Note: this `hasRole` override does not add the admin address to each role's enumerable member set. As a result, `getRoleMember` / `getRoleMemberCount` for a specific role do not include the admin unless that role is explicitly granted. See also [docs.openzeppelin.com - AccessControlEnumerable](https://docs.openzeppelin.com/contracts/5.x/api/access#AccessControlEnumerable) @@ -386,7 +437,7 @@ See also [docs.openzeppelin.com - Ownable2Step](https://docs.openzeppelin.com/co The table below summarizes which ERC-165 interfaces are advertised by each deployment version via `supportsInterface(bytes4)`. -| Interface | Interface ID | RuleEngine (RBAC deployment) | RuleEngineOwnable deployment | RuleEngineOwnable2Step deployment | +| Interface | Interface ID | RuleEngine / RuleEngine2771 (RBAC deployments) | RuleEngineOwnable / RuleEngineOwnable2771 | RuleEngineOwnable2Step / RuleEngineOwnable2Step2771 | | --- | --- | --- | --- | --- | | `IERC165` | `0x01ffc9a7` | ✔ | ✔ | ✔ | | `IRuleEngine` | `0x20c49ce7` | ✔ | ✔ | ✔ | @@ -400,16 +451,25 @@ The table below summarizes which ERC-165 interfaces are advertised by each deplo | `IAccessControl` | `0x7965db0b` | ✔ | ✘ | ✘ | | `IAccessControlEnumerable` | `0x5a05180f` | ✔ | ✘ | ✘ | -The six interfaces common to all three variants come from `RuleEngineBase._supportsRuleEngineBaseInterface`; -each deployable adds the IDs of its own access-control model on top. +The six interfaces common to all variants come from `RuleEngineBase._supportsRuleEngineBaseInterface`; +each deployable adds the IDs of its own access-control model on top. ERC-2771 has no ERC-165 id, so each `*2771` +contract advertises exactly the same set as its counterpart without a forwarder (pinned by +`test/utils/ERC2771VariantTestBase.sol`). Notes: -- `RuleEngine` advertises OpenZeppelin RBAC interfaces because it inherits `AccessControlEnumerable`. +- `RuleEngine` / `RuleEngine2771` advertise OpenZeppelin RBAC interfaces because `RuleEngine` inherits `AccessControlEnumerable` and `RuleEngine2771` extends `RuleEngine`. - `RuleEngineOwnable` / `RuleEngineOwnable2Step` intentionally do not advertise `IAccessControl`. - `Ownable2Step` specific interface ID is defined in `Ownable2StepInterfaceId` and includes only `pendingOwner()` and `acceptOwnership()`. -- **`IRule` (`0x2497d6cb`) is deliberately absent from this table.** The engine does not implement `IRule`; it +- **Two ERC-165 conventions coexist, both on purpose.** `IRuleEngine` (`0x20c49ce7`) is CMTAT's constant and is computed **without** `IERC165.supportsInterface`; `IRule` (`0xb1a69752`) is computed **with** it (`RuleInterfaceId` XORs in `IERC165`). Both values are the ones deployed tokens and rules already check, and both are pinned by `test/RuleEngine/IRuleInterfaceId.t.sol`: do not "fix" one to match the other. +- **`IRule` (`0xb1a69752`) is deliberately absent from this table.** The engine does not implement `IRule`; it *requires* it of every rule, checking it in `_checkRule` before a rule is added. Do not expect - `ruleEngine.supportsInterface(0x2497d6cb)` to return true. + `ruleEngine.supportsInterface(0xb1a69752)` to return true. +- **`IRule` was narrowed in v3.0.0-rc7.** It requires the six functions the engine calls (`transferred` x2, + `detectTransferRestriction(From)`, `messageForTransferRestriction`, `canReturnTransferRestrictionCode`) plus + ERC-165, and no longer `canTransfer` / `canTransferFrom`. The ID moved from `0x2497d6cb` to `0xb1a69752`. + **The engine accepts both**: the legacy ID (`RuleInterfaceId.IRULE_LEGACY_INTERFACE_ID`) describes a superset + of the current interface, so rules built before rc7 can still be added. A contract advertising neither, or + not implementing ERC-165 correctly, is rejected with `RuleEngine_RuleInvalidInterface`. - **The IDs are computed from the interfaces, not hardcoded** — see `ComplianceInterfaceId`, `RuleInterfaceId` and `ERC1404InterfaceId`, and `test/RuleEngine/IRuleInterfaceId.t.sol`, which pins each one to the wire value above. `type(I).interfaceId` counts only the functions `I` declares *directly*, so every constant XORs the @@ -488,22 +548,51 @@ contract's surface. #### RuleEngine ![RuleEngineUML](./schema/sol2uml/RuleEngineUML.png) +![RuleEngine2771UML](./schema/sol2uml/RuleEngine2771UML.png) + +![surya_inheritance_RuleEngine](./schema/surya/surya_inheritance/surya_inheritance_RuleEngine.sol.png) +![surya_inheritance_RuleEngine2771](./schema/surya/surya_inheritance/surya_inheritance_RuleEngine2771.sol.png) + +``` +RuleEngine +├── RuleEngineBase (core functionality) +├── AccessControlEnumerable (RBAC) +├── ERC3643ComplianceRolesStorage +└── RulesManagementModuleRolesStorage + +RuleEngine2771 +├── ERC2771ModuleStandalone (gasless support) +└── RuleEngine +``` + +`RuleEngine` and `RuleEngine2771` differ only by ERC-2771: same constructor checks, roles, `grantRole` / `hasRole` overrides and ERC-165 answers, all held by `RuleEngine`. `RuleEngine2771` extends `RuleEngine` (the same pattern as `RuleEngineOwnable2771` / `RuleEngineOwnable2Step2771`) and adds the immutable trusted forwarder and the `_msgSender` / `_msgData` / `_contextSuffixLength` overrides. + #### RuleEngineOwnable ![RuleEngineOwnableUML](./schema/sol2uml/RuleEngineOwnableUML.png) `RuleEngineOwnable` shares the same base functionality as `RuleEngine` but uses ERC-173 ownership instead of RBAC. +![RuleEngineOwnable2771UML](./schema/sol2uml/RuleEngineOwnable2771UML.png) + +![surya_inheritance_RuleEngineOwnable](./schema/surya/surya_inheritance/surya_inheritance_RuleEngineOwnable.sol.png) +![surya_inheritance_RuleEngineOwnable2771](./schema/surya/surya_inheritance/surya_inheritance_RuleEngineOwnable2771.sol.png) +![surya_inheritance_RuleEngineOwnableShared](./schema/surya/surya_inheritance/surya_inheritance_RuleEngineOwnableShared.sol.png) + ``` RuleEngineOwnable -├── ERC2771ModuleStandalone (gasless support) -├── RuleEngineBase (core functionality) -│ ├── VersionModule -│ ├── RulesManagementModule -│ ├── ERC3643ComplianceModule (core ERC-3643) -│ ├── ERC3643ComplianceExtendedModule (project extensions) -│ └── IRuleEngineERC1404 +├── RuleEngineOwnableShared (shared ownable deployment logic) +│ └── RuleEngineBase (core functionality) +│ ├── VersionModule +│ ├── RulesManagementModule +│ ├── ERC3643ComplianceModule (core ERC-3643) +│ ├── ERC3643ComplianceExtendedModule (project extensions) +│ └── IRuleEngineERC1404 └── Ownable (ERC-173 access control) + +RuleEngineOwnable2771 +├── ERC2771ModuleStandalone (gasless support) +└── RuleEngineOwnable ``` **Key differences from RuleEngine:** @@ -518,9 +607,13 @@ RuleEngineOwnable `RuleEngineOwnable2Step` shares the same base functionality as `RuleEngineOwnable` but uses OpenZeppelin's `Ownable2Step` for safer ownership handover. +![RuleEngineOwnable2Step2771UML](./schema/sol2uml/RuleEngineOwnable2Step2771UML.png) + +![surya_inheritance_RuleEngineOwnable2Step](./schema/surya/surya_inheritance/surya_inheritance_RuleEngineOwnable2Step.sol.png) +![surya_inheritance_RuleEngineOwnable2Step2771](./schema/surya/surya_inheritance/surya_inheritance_RuleEngineOwnable2Step2771.sol.png) + ``` RuleEngineOwnable2Step -├── ERC2771ModuleStandalone (gasless support) ├── RuleEngineOwnableShared (shared ownable deployment logic) │ └── RuleEngineBase │ ├── VersionModule @@ -529,12 +622,19 @@ RuleEngineOwnable2Step │ ├── ERC3643ComplianceExtendedModule (project extensions) │ └── IRuleEngineERC1404 └── Ownable2Step (ERC-173 access control with pending owner) + +RuleEngineOwnable2Step2771 +├── ERC2771ModuleStandalone (gasless support) +└── RuleEngineOwnable2Step ``` +Each ownable `*2771` contract is its counterpart plus the immutable trusted forwarder and the `_msgSender` / `_msgData` / `_contextSuffixLength` overrides; constructor checks, `transferOwnership` guard, hooks and ERC-165 are inherited unchanged. + **Key differences from RuleEngineOwnable:** - Uses a two-step ownership transfer flow: `transferOwnership()` then `acceptOwnership()` - The current owner retains privileges until the pending owner accepts ownership -- Reuses `RuleEngineOwnableShared` for constructor, ERC-165 (via OpenZeppelin `ERC165`), and ERC-2771 behavior +- The rule-account guard runs at nomination and again at acceptance: a pending owner that has been added as a rule cannot call `acceptOwnership()` until it is removed from the rule set +- Reuses `RuleEngineOwnableShared` for the constructor and ERC-165 (via OpenZeppelin `ERC165`) - Implements ERC-173 interface (`supportsInterface(0x7f5828d0)` returns `true`) - Implements Ownable2Step-specific ERC-165 interface (`supportsInterface(0x9ab669ef)` returns `true`), covering `pendingOwner()` and `acceptOwnership()` @@ -544,9 +644,11 @@ RuleEngineOwnable2Step ### Graph -Here is the surya graph of the main contract: +Here is the surya graph of `RuleEngineBase`, which holds the logic shared by the six deployables (each deployable +only adds its constructor, access-control hooks and, for the `*2771` contracts, the ERC-2771 overrides; their own +graphs are in [doc/schema/surya/surya_graph](./schema/surya/surya_graph/)): -![surya_graph_RuleEngine](./schema/surya/surya_graph/surya_graph_RuleEngine.sol.png) +![surya_graph_RuleEngineBase](./schema/surya/surya_graph/surya_graph_RuleEngineBase.sol.png) ## Functionality @@ -554,7 +656,7 @@ Several functionalities are not implemented because it makes more sense to direc The RuleEngine can be removed from the main token contract by calling these dedicated functions -- CMTAT v3.0.0: `setRuleEngine(address ruleEngine)` +- CMTAT ≥ v3.0.0: `setRuleEngine(IRuleEngine ruleEngine_)` - ERC-3643 token: `setCompliance(address _compliance)` ### Available Rules @@ -563,53 +665,90 @@ Rules are maintained in a dedicated repository: [github.com/CMTA/Rules](https:// Rules can be used in two ways: -- Directly on CMTAT (single-rule setup, no RuleEngine orchestration). +- Directly on CMTAT (single-rule setup, no RuleEngine orchestration: `token.setRuleEngine(rule)`). Every rule of the Rules repository advertises `RULE_ENGINE_INTERFACE_ID` for this role. **Not for ERC-3643**: the token calls `bindToken`, `created` and `destroyed`, which the validation rules do not implement — use the engine. No bound-token gate stands in front of the rule, so a stateful rule must restrict who calls its `transferred`; see [RuleEngine-with-CMTAT.md §4.8](./technical/RuleEngine-with-CMTAT.md#48-a-single-rule-can-be-the-tokens-rule-engine). Tested with the reference rules in `test/RuleStandalone/`. - Through this RuleEngine (multi-rule orchestration with sequential execution). +> **Warning:** `RuleConditionalTransferLightMultiToken` must be set **directly on each token** and never added to a RuleEngine: it keys approvals on the calling token (`msg.sender`), which is the engine when it sits behind one. It nevertheless advertises `IRule`, so `addRule` accepts it. See its [documentation](https://github.com/CMTA/Rules/blob/main/doc/technical/contracts/RuleConditionalTransferLightMultiToken.md). + Rule families: | Family | Behavior | Examples | | --- | --- | --- | -| Validation rules (read-only) | Evaluate transfer eligibility without mutating rule state | `RuleWhitelist`, `RuleBlacklist`, `RuleSanctionList`, `RuleIdentityRegistry`, `RuleSpenderWhitelist`, `RuleERC2980`, `RuleMaxTotalSupply` | -| Operation rules (read-write) | Evaluate transfer eligibility and can update rule-specific state on transfer | `RuleConditionalTransferLight` | +| Validation rules (read-only) | Evaluate transfer eligibility without mutating rule state | `RuleWhitelist`, `RuleWhitelistWrapper`, `RuleReceiverWhitelist`, `RuleBlacklist`, `RuleSanctionsList`, `RuleIdentityRegistry`, `RuleSpenderWhitelist`, `RuleERC2980`, `RuleMaxTotalSupply`, `RuleMaxTotalSupplyERC3643`, `RuleMaxBalance`, `RuleChainlinkPoR`, `RuleChainlinkPoRERC3643` | +| Operation rules (read-write) | Evaluate transfer eligibility and can update rule-specific state on transfer | `RuleConditionalTransferLight`, `RuleConditionalTransferLightMultiToken`, `RuleMintAllowance` | Additional integration notes: -- For RuleEngine integration, a rule must implement `IRule` (including ERC-165 support for the Rule interface ID). +- For RuleEngine integration, a rule must implement `IRule` and advertise its ERC-165 ID `0xb1a69752`. Since v3.0.0-rc7 that ID no longer includes `canTransfer` / `canTransferFrom`. A rule advertising only the older `0x2497d6cb` is still accepted. **This is the case of every rule up to Rules v0.6.0**, which is built against RuleEngine v3.0.0-rc6 and advertises `0x2497d6cb`. - RuleEngine executes configured rules in order and reverts on the first failing rule in state-changing paths. -- Restriction codes should remain unique across the composed rule set. Keep CMTAT-reserved ranges free and use dedicated code ranges per rule +- Restriction codes should remain unique across the composed rule set. Keep CMTAT-reserved ranges free and use dedicated code ranges per rule. The Rules repository uses codes `21` to `83` (see the table below); `RuleWhitelist` and `RuleWhitelistWrapper` share `21`–`25`, and the two conditional-transfer rules share `46`, with the same messages. +- **The operation rules restrict who calls `transferred`.** Their hooks accept only the bound token or, for `RuleConditionalTransferLight`, a separately bound engine. Behind a RuleEngine the rule must therefore be told about the engine, or every transfer reverts: + - `RuleConditionalTransferLight`: `bindToken(token)` **and** `bindRuleEngine(engine)`. Approvals are keyed `(from, to, value)` with no token dimension, so bind only an engine that serves **this one token**. + - `RuleMintAllowance`: `bindToken(engine)` (the caller it accepts is the engine, not the token). +- **Some validation rules protect one token per instance.** `RuleMaxTotalSupply`, `RuleChainlinkPoR`, their ERC-3643 variants and `RuleMaxBalance` read `totalSupply()` / `balanceOf()` from a token configured at deployment, not from the token that triggered the check (the engine does not forward it). An instance added to an engine bound to several tokens checks every token against the configured one. Deploy one instance per token, or one engine per token. See [RuleEngine-with-CMTAT.md §4.4](./technical/RuleEngine-with-CMTAT.md#44-one-engine-shared-by-several-tokens-is-not-neutral). +- **ERC-3643 compatibility differs per rule.** An ERC-3643 token never forwards a spender and calls compliance *after* it moves the value, so spender legs are inert, the stock cap rules count the amount twice, and `RuleMintAllowance` debits nothing. The `ERC-3643` column below summarises the Rules repository's per-rule [compatibility matrix](https://github.com/CMTA/Rules/blob/main/doc/technical/guides/RULE_SEMANTICS.md#6-erc-3643-compatibility--which-rules-actually-work-on-a-t-rex-token). - For the latest list of production rules, audits, and status, use the Rules repository as the source of truth. #### Rules details -Here is a summary tab of available rules, see [github.com/CMTA/Rules](https://github.com/CMTA/Rules) - -| Rule | Type
[read-only / read-write] | Description | -| ------------------------------------------------------------ | ----------------------------------- | ------------------------------------------------------------ | -| RuleWhitelist | Read-only | This rule can be used to restrict transfers from/to only addresses inside a whitelist. | -| RuleWhitelistWrapper | Read-Only | This rule can be used to restrict transfers from/to only addresses inside a group of whitelist rules managed by different operators. | -| RuleBlacklist | Read-Only | This rule can be used to forbid transfer from/to addresses in the blacklist | -| RuleSanctionList | Read-Only | The purpose of this contract is to use the oracle contract from [Chainalysis](https://go.chainalysis.com/chainalysis-oracle-docs.html) to forbid transfer from/to an address included in a sanctions designation (US, EU, or UN). | -| RuleMaxTotalSupply | Read-Only | This rule limits minting so that the total supply never exceeds a configured maximum. | -| RuleIdentityRegistry | Read-Only | This rule checks the ERC-3643 Identity Registry for transfer participants when configured. | -| RuleSpenderWhitelist | Read-Only | This rule blocks `transferFrom` when the spender is not in the whitelist. Direct transfers are always allowed. | -| RuleERC2980 | Read-Only | ERC-2980 Swiss Compliant rule combining a whitelist (recipient-only) and a frozenlist (blocks sender, recipient, and spender for `transferFrom`). Frozenlist takes priority over whitelist. | -| RuleConditionalTransferLight | Read-Write | This rule requires that transfers have to be approved by an operator before being executed. Each approval is consumed once and the same transfer can be approved multiple times. | -| [RuleConditionalTransfer](https://github.com/CMTA/RuleConditionalTransfer) (external) | Read-Write | Full-featured approval-based transfer rule implementing Swiss law *Vinkulierung*. Supports automatic approval after three months, automatic transfer execution, and a conditional whitelist for address pairs that bypass approval. Maintained in a separate repository. | -| [RuleSelf](https://github.com/rya-sge/ruleself) (community) | — | Use [Self](https://self.xyz), a zero-knowledge identity solution to determine which is allowed to interact with the token.
Community-maintained rule project. Not developed or maintained by CMTA. | +Here is a summary tab of available rules, see [github.com/CMTA/Rules](https://github.com/CMTA/Rules), which remains the source of truth (this table was last synced with Rules **v0.6.0**). `IdentityRegistryWhitelist`, also in that repository, is an identity registry, not a rule: it implements no `IRule` and must never be added to a RuleEngine. + +ERC-3643 column: ✔ works; ✔¹ works, but a spender check or flag never fires (the token forwards no spender); ⚠ use the `…ERC3643` variant; ✘ not supported or inert. + +| Rule | Type | Codes | ERC-3643 | Description | +| ---- | ---- | ----- | -------- | ----------- | +| RuleWhitelist | Read-only | 21–25 | ✔¹ | Restricts transfers to addresses inside a whitelist. Mint and burn are enabled by `allowMint` / `allowBurn` flags; `address(0)` can never be listed. | +| RuleWhitelistWrapper | Read-only | 21–25 | ✔¹ | Restricts transfers to addresses listed in at least one of several whitelist rules managed by different operators. Child rules must declare themselves allow-lists; wrappers cannot be nested. | +| RuleBlacklist | Read-only | 36–38 | ✔¹ | Forbids transfers from/to blacklisted addresses. | +| RuleSanctionsList | Read-only | 30–32 | ✔¹ | Uses the [Chainalysis](https://go.chainalysis.com/chainalysis-oracle-docs.html) sanctions oracle to forbid transfers from/to an address included in a sanctions designation (US, EU, or UN). | +| RuleMaxTotalSupply | Read-only | 50, 51 | ⚠ | Limits minting so that the total supply never exceeds a configured maximum. For CMTAT. One token per instance. | +| RuleMaxTotalSupplyERC3643 | Read-only | 50, 51 | ✔ | Same cap, for ERC-3643 tokens, which mint first and notify compliance afterwards. Not interchangeable with `RuleMaxTotalSupply`. | +| RuleMaxBalance | Read-only | 82, 83 | ✘ | Caps how many tokens a single address may hold, with operator-managed exemptions. CMTAT only. One token per instance. | +| RuleChainlinkPoR | Read-only | 75–79 | ⚠ | Caps minting at the reserves reported by a [Chainlink Proof of Reserve](https://docs.chain.link/data-feeds/proof-of-reserve) feed. For CMTAT. One token per instance. | +| RuleChainlinkPoRERC3643 | Read-only | 75–79 | ✔ | Same reserve cap, for ERC-3643 tokens. Not interchangeable with `RuleChainlinkPoR`. | +| RuleReceiverWhitelist | Read-only | 81 | ✔ | Whitelist screening only the receiver, reproducing ERC-3643's eligibility rule. | +| RuleIdentityRegistry | Read-only | 55–57 | ✔¹ | Checks the ERC-3643 Identity Registry. Screens the receiver only by default, as ERC-3643 requires; sender and spender checks are opt-in flags. | +| RuleSpenderWhitelist | Read-only | 66 | ✘ | Blocks `transferFrom` when the spender is not in the whitelist. Direct transfers are always allowed. Inert on ERC-3643, which forwards no spender. | +| RuleERC2980 | Read-only | 60–65 | ✔¹ | ERC-2980 Swiss Compliant rule combining a whitelist (recipient-only) and a frozenlist (blocks sender, recipient, and spender for `transferFrom`). Frozenlist takes priority over whitelist. | +| RuleConditionalTransferLight | Read-write | 46 | ✔ | Transfers must be approved by an operator before being executed. Each approval is consumed once and the same transfer can be approved multiple times. Behind an engine: `bindToken(token)` and `bindRuleEngine(engine)`, with an engine serving this token only. | +| RuleConditionalTransferLightMultiToken | Read-write | 46 | ✘ | Same approval mechanism, with approvals scoped per token. **Set it directly on each token, never behind a RuleEngine** (see the warning above). | +| RuleMintAllowance | Read-write | 70 | ✘ | Per-minter mint quota, debited on each mint. Uses the operator that CMTAT ≥ v3.3.0 passes as `spender` on the 4-argument `transferred`; inert on earlier CMTAT versions and on ERC-3643 (every mint passes). Behind an engine: `bindToken(engine)`. Pre-check with `canTransferFrom`, not `canTransfer`. | +| [RuleConditionalTransfer](https://github.com/CMTA/RuleConditionalTransfer) (external) | Read-write | — | — | Full-featured approval-based transfer rule implementing Swiss law *Vinkulierung*. Supports automatic approval after three months, automatic transfer execution, and a conditional whitelist for address pairs that bypass approval. Maintained in a separate repository. | +| [RuleSelf](https://github.com/rya-sge/ruleself) (community) | — | — | — | Use [Self](https://self.xyz), a zero-knowledge identity solution to determine which is allowed to interact with the token.
Community-maintained rule project. Not developed or maintained by CMTA. | ### Gasless support (ERC-2771) ![surya_inheritance_ERC2771ModuleStandalone.sol](./schema/surya/surya_inheritance/surya_inheritance_ERC2771ModuleStandalone.sol.png) -The RuleEngine supports client-side gasless transactions using the standard [ERC-2771](https://eips.ethereum.org/EIPS/eip-2771). +`RuleEngine2771`, `RuleEngineOwnable2771` and `RuleEngineOwnable2Step2771` support client-side gasless transactions using the standard [ERC-2771](https://eips.ethereum.org/EIPS/eip-2771). `RuleEngine`, `RuleEngineOwnable` and `RuleEngineOwnable2Step` do not: deploy the `*2771` version of the access-control model you need a forwarder for. -The contract uses the OpenZeppelin contract `ERC2771ContextUpgradeable`, which allows a contract to get the original client with `_msgSender()` instead of the feepayer given by `msg.sender`. +The contract uses the OpenZeppelin contract `ERC2771Context` (through `ERC2771ModuleStandalone`), which allows a contract to get the original client with `_msgSender()` instead of the feepayer given by `msg.sender`. -At deployment, the parameter `forwarder` inside the RuleEngine contract constructor has to be set with the defined address of the forwarder. +At deployment, the constructor parameter `forwarderIrrevocable` of a `*2771` contract has to be set with the address of the forwarder. To disable ERC-2771, deploy the version without the `2771` suffix rather than passing `address(0)`. After deployment, the forwarder is immutable and can not be changed. +#### Token calls are never resolved through the forwarder + +ERC-2771 lets the trusted forwarder name the sender of a call: when `msg.sender` is the forwarder, `_msgSender()` returns the address appended to the calldata. This is what makes gasless administration possible, and the engine's administrative checks rely on it. + +Two checks, however, identify a **token** rather than a person, and they compare the raw `msg.sender` instead: + +| Check | Where | Identifies | Resolved with | +|---|---|---|---| +| `onlyBoundToken` (`_checkBoundToken`) on `transferred`, `created`, `destroyed` | `TokenBindingModule` | the bound token calling the engine | **`msg.sender`** | +| Token self-binding in `bindToken` / `unbindToken` (ERC-3643 `setCompliance`) | `TokenBindingExtendedModule._authorizeTokenBindingChange` | the approved token binding itself | **`msg.sender`** | +| Rule management, binding manager, `setMaxRules`, self-binding approval, roles / ownership | the access-control hooks of each deployable | an operator | `_msgSender()` (relayable) | + +**Purpose of the fix (v3.0.0-rc7).** Up to rc6, both token checks used `_msgSender()`. A trusted forwarder could therefore append a bound token's address to a call and pass as that token: + +- **Forged callbacks.** By calling `transferred` / `created` / `destroyed` "as" a bound token, the forwarder drove every rule with no token movement. Read-only rules are unaffected, but stateful rules were not: a per-minter mint quota could be consumed with no mint, and a one-time transfer approval could be used up so that the real transfer then fails. +- **Forged self-unbinding.** By calling `unbindToken(token)` "as" a token approved for self-binding, the forwarder could unbind it. Every transfer, mint and burn of that token then reverted until an operator re-bound it. + +A signature-verifying forwarder never produces such a call, because a token contract cannot sign a request. The exposure was a buggy, malicious or permissive forwarder, which is fixed at deployment. The fix removes that dependency: a token always calls the engine directly from its own `transfer`, `mint`, `burn` or `setCompliance`, never through a forwarder, so for every legitimate token call `msg.sender == _msgSender()`, and comparing `msg.sender` rejects only the impersonation. Operators can still bind and unbind tokens, and manage rules, through signed meta-transactions. CMTAT makes the same choice for its bridge gate (`ERC20CrossChainModule.onlyTokenBridge`). + +The behaviour is pinned for the three ERC-2771 deployables by `test/RuleEngine2771/ERC2771TokenGate.t.sol`, `test/RuleEngineOwnable2771/ERC2771TokenGate.t.sol` and `test/RuleEngineOwnable2Step2771/ERC2771TokenGate.t.sol` (shared suite `test/utils/ERC2771TokenGateTestBase.sol`). See also [RuleEngine-with-CMTAT.md §4.7](./technical/RuleEngine-with-CMTAT.md#47-the-trusted-forwarder-cannot-act-as-a-token). + References: - [OpenZeppelin Meta Transactions](https://docs.openzeppelin.com/contracts/5.x/api/metatx) @@ -644,6 +783,20 @@ Similar to the pause functionality, the RuleEngine can be directly removed from #### RuleEngine Constructor +```solidity +constructor( + address admin, + address tokenContract +) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| admin | address | Address granted DEFAULT_ADMIN_ROLE (has all roles); must not be zero | +| tokenContract | address | Token to bind at deployment (can be zero) | + +#### RuleEngine2771 Constructor + ```solidity constructor( address admin, @@ -654,11 +807,27 @@ constructor( | Parameter | Type | Description | |-----------|------|-------------| -| admin | address | Address granted DEFAULT_ADMIN_ROLE (has all roles) | -| forwarderIrrevocable | address | ERC-2771 trusted forwarder address (can be zero) | +| admin | address | Address granted DEFAULT_ADMIN_ROLE (has all roles); must not be zero | +| forwarderIrrevocable | address | ERC-2771 trusted forwarder address, immutable | | tokenContract | address | Token to bind at deployment (can be zero) | -#### RuleEngineOwnable Constructor +> Up to v3.0.0-rc6, `RuleEngine` took the three parameters of `RuleEngine2771`. A deployment script that passes a forwarder must switch to `RuleEngine2771`; one that passes `address(0)` drops the middle argument. + +#### RuleEngineOwnable and RuleEngineOwnable2Step Constructors + +```solidity +constructor( + address owner_, + address tokenContract +) +``` + +| Parameter | Type | Description | +|-----------|------|-------------| +| owner_ | address | Address set as contract owner (ERC-173); must not be zero (`OwnableInvalidOwner`) | +| tokenContract | address | Token to bind at deployment (can be zero) | + +#### RuleEngineOwnable2771 and RuleEngineOwnable2Step2771 Constructors ```solidity constructor( @@ -670,10 +839,12 @@ constructor( | Parameter | Type | Description | |-----------|------|-------------| -| owner_ | address | Address set as contract owner (ERC-173) | -| forwarderIrrevocable | address | ERC-2771 trusted forwarder address (can be zero) | +| owner_ | address | Address set as contract owner (ERC-173); must not be zero (`OwnableInvalidOwner`) | +| forwarderIrrevocable | address | ERC-2771 trusted forwarder address, immutable | | tokenContract | address | Token to bind at deployment (can be zero) | +> Up to v3.0.0-rc6, `RuleEngineOwnable` and `RuleEngineOwnable2Step` took the three parameters of their `*2771` versions. A deployment script that passes a forwarder must switch to the `*2771` contract; one that passes `address(0)` drops the middle argument. + ### RuleEngineBase ![RuleEngineBaseUML](./schema/sol2uml/RuleEngineBaseUML.png) @@ -681,21 +852,27 @@ constructor( #### Contracts Description Table -| Contract | Type | Bases | | | -| :----------------: | :---------------------------: | :----------------------------------------------------------: | :------------: | :------------: | -| └ | **Function Name** | **Visibility** | **Mutability** | **Modifiers** | -| | | | | | -| **RuleEngineBase** | Implementation | VersionModule, RulesManagementModule, ERC3643ComplianceExtendedModule, RuleEngineInvariantStorage, IRuleEngine | | | -| └ | transferred | Public ❗️ | 🛑 | onlyBoundToken | -| └ | transferred | Public ❗️ | 🛑 | onlyBoundToken | -| └ | created | Public ❗️ | 🛑 | onlyBoundToken | -| └ | destroyed | Public ❗️ | 🛑 | onlyBoundToken | -| └ | detectTransferRestriction | Public ❗️ | | NO❗️ | -| └ | detectTransferRestrictionFrom | Public ❗️ | | NO❗️ | -| └ | canTransfer | Public ❗️ | | NO❗️ | -| └ | canTransferFrom | Public ❗️ | | NO❗️ | -| └ | messageForTransferRestriction | Public ❗️ | | NO❗️ | -| └ | hasRole | Public ❗️ | | NO❗️ | +| Contract | Type | Bases | | | +|:----------:|:-------------------:|:----------------:|:----------------:|:---------------:| +| └ | **Function Name** | **Visibility** | **Mutability** | **Modifiers** | +|||||| +| **RuleEngineBase** | Implementation | VersionModule, RulesManagementModule, ERC3643ComplianceExtendedModule, RuleEngineInvariantStorage, IRuleEngineERC1404 ||| +| └ | transferred | Public ❗️ | 🛑 | onlyBoundToken | +| └ | transferred | Public ❗️ | 🛑 | onlyBoundToken | +| └ | created | Public ❗️ | 🛑 | onlyBoundToken | +| └ | destroyed | Public ❗️ | 🛑 | onlyBoundToken | +| └ | detectTransferRestriction | Public ❗️ | |NO❗️ | +| └ | detectTransferRestrictionFrom | Public ❗️ | |NO❗️ | +| └ | messageForTransferRestriction | Public ❗️ | |NO❗️ | +| └ | canTransfer | Public ❗️ | |NO❗️ | +| └ | canTransferFrom | Public ❗️ | |NO❗️ | +| └ | _detectTransferRestriction | Internal 🔒 | | | +| └ | _detectTransferRestrictionFrom | Internal 🔒 | | | +| └ | _messageForTransferRestriction | Internal 🔒 | | | +| └ | _checkRule | Internal 🔒 | | | +| └ | _checkBindingTarget | Internal 🔒 | | | +| └ | _supportsRuleInterface | Internal 🔒 | | | +| └ | _supportsRuleEngineBaseInterface | Internal 🔒 | | | ##### Legend @@ -705,6 +882,16 @@ constructor( | 🛑 | Function can modify state | | 💵 | Function is payable | +#### IRule + +![IRuleUML](./schema/sol2uml/IRuleUML.png) + +What every rule implements (`src/interfaces/IRule.sol`). The diagram shows the two functions `IRule` declares +itself; it also inherits `IERC1404Extend` (`detectTransferRestriction`, `detectTransferRestrictionFrom`, +`messageForTransferRestriction`), `IERC3643IComplianceContract` (3-argument `transferred`) and `IERC165`, all +described below. ERC-165 ID `0xb1a69752`; the legacy `0x2497d6cb` (which also includes `canTransfer` / +`canTransferFrom`) is still accepted by the engine. + #### IRuleEngine ![IRuleEngineUML](./schema/sol2uml/IRuleEngineUML.png) @@ -996,12 +1183,12 @@ This is an extension of {ERC-1404} with an additional `spender` parameter to enf #### Contracts Description Table -| Contract | Type | Bases | | | -| :---------------: | :---------------: | :------------: | :------------: | :-----------: | -| └ | **Function Name** | **Visibility** | **Mutability** | **Modifiers** | -| | | | | | -| **VersionModule** | Implementation | IERC3643Base | | | -| └ | version | Public ❗️ | | NO❗️ | +| Contract | Type | Bases | | | +|:----------:|:-------------------:|:----------------:|:----------------:|:---------------:| +| └ | **Function Name** | **Visibility** | **Mutability** | **Modifiers** | +|||||| +| **VersionModule** | Implementation | IERC3643Version ||| +| └ | version | Public ❗️ | |NO❗️ | #### version() @@ -1017,14 +1204,14 @@ returns (string memory version_) **Description** -Returns the current version of the token contract. -Useful for identifying which version of the smart contract is deployed and in use. +Returns the current version of the RuleEngine contract (currently `"3.0.0-rc7"`). +Useful for identifying which version of the smart contract is deployed and in use. Release candidates carry their `-rcN` suffix, so the string matches the release tag. **Return** | Name | Type | Description | | ---------- | ------ | ------------------------------------------------------------ | -| `version_` | string | The version string of the token implementation (e.g., "1.0.0"). | +| `version_` | string | The version string of the RuleEngine implementation (e.g., "3.0.0-rc7"). | @@ -1053,23 +1240,30 @@ under `ERC3643ComplianceExtendedModule`, since that is the form in which the Rul #### Contracts Description Table -| Contract | Type | Bases | | | -| :----------------------------: | :---------------: | :-------------------------------------------: | :------------: | :----------------------: | -| └ | **Function Name** | **Visibility** | **Mutability** | **Modifiers** | -| | | | | | -| **TokenBindingModule** | Implementation | Context, ITokenBinding | | | -| └ | bindToken | Public ❗️ | 🛑 | NO❗️ | -| └ | unbindToken | Public ❗️ | 🛑 | NO❗️ | -| └ | isTokenBound | Public ❗️ | | NO❗️ | -| └ | _bindToken | Internal 🔒 | 🛑 | | -| └ | _unbindToken | Internal 🔒 | 🛑 | | -| **TokenBindingExtendedModule** | Implementation | TokenBindingModule, ITokenBindingExtended | | | -| └ | bindTokens | Public ❗️ | 🛑 | onlyTokenBindingManager | -| └ | unbindTokens | Public ❗️ | 🛑 | onlyTokenBindingManager | -| └ | setTokenSelfBindingApproval | Public ❗️ | 🛑 | onlyTokenBindingManager | -| └ | setTokenSelfBindingApprovalBatch | Public ❗️ | 🛑 | onlyTokenBindingManager | -| └ | isTokenSelfBindingApproved | Public ❗️ | | NO❗️ | -| └ | getTokenBounds | Public ❗️ | | NO❗️ | +| Contract | Type | Bases | | | +|:----------:|:-------------------:|:----------------:|:----------------:|:---------------:| +| └ | **Function Name** | **Visibility** | **Mutability** | **Modifiers** | +|||||| +| **TokenBindingModule** | Implementation | Context, ITokenBinding, TokenBindingModuleInvariantStorage ||| +| └ | bindToken | Public ❗️ | 🛑 |NO❗️ | +| └ | unbindToken | Public ❗️ | 🛑 |NO❗️ | +| └ | isTokenBound | Public ❗️ | |NO❗️ | +| └ | _bindToken | Internal 🔒 | 🛑 | | +| └ | _checkBindingTarget | Internal 🔒 | | | +| └ | _unbindToken | Internal 🔒 | 🛑 | | +| └ | _authorizeTokenBindingChange | Internal 🔒 | 🛑 | | +| └ | _onlyTokenBindingManager | Internal 🔒 | 🛑 | | +| └ | _checkBoundToken | Internal 🔒 | | | +| **TokenBindingExtendedModule** | Implementation | TokenBindingModule, ITokenBindingExtended ||| +| └ | bindTokens | Public ❗️ | 🛑 | onlyTokenBindingManager | +| └ | unbindTokens | Public ❗️ | 🛑 | onlyTokenBindingManager | +| └ | setTokenSelfBindingApproval | Public ❗️ | 🛑 | onlyTokenBindingManager | +| └ | setTokenSelfBindingApprovalBatch | Public ❗️ | 🛑 | onlyTokenBindingManager | +| └ | isTokenSelfBindingApproved | Public ❗️ | |NO❗️ | +| └ | getTokenBounds | Public ❗️ | |NO❗️ | +| └ | _unbindToken | Internal 🔒 | 🛑 | | +| └ | _setTokenSelfBindingApproval | Internal 🔒 | 🛑 | | +| └ | _authorizeTokenBindingChange | Internal 🔒 | 🛑 | | ### ERC3643ComplianceModule @@ -1085,13 +1279,14 @@ variants). The compliance callbacks `transferred`, `created` and `destroyed` are #### Contracts Description Table -| Contract | Type | Bases | | | -| :-------------------------: | :---------------: | :-------------------------------: | :------------: | :-----------: | -| └ | **Function Name** | **Visibility** | **Mutability** | **Modifiers** | -| | | | | | -| **ERC3643ComplianceModule** | Implementation | TokenBindingModule, IERC3643Compliance | | | -| └ | getTokenBound | Public ❗️ | | NO❗️ | -| └ | _onlyTokenBindingManager | Internal 🔒 | 🛑 | | +| Contract | Type | Bases | | | +|:----------:|:-------------------:|:----------------:|:----------------:|:---------------:| +| └ | **Function Name** | **Visibility** | **Mutability** | **Modifiers** | +|||||| +| **ERC3643ComplianceModule** | Implementation | TokenBindingModule, IERC3643Compliance ||| +| └ | getTokenBound | Public ❗️ | |NO❗️ | +| └ | _onlyTokenBindingManager | Internal 🔒 | 🛑 | | +| └ | _onlyComplianceManager | Internal 🔒 | 🛑 | | ### ERC3643ComplianceExtendedModule @@ -1554,6 +1749,7 @@ Here is the list of report performed with [Slither](https://github.com/crytic/sl | Version | Report | Assessment | | ------- | ------ | ---------- | +| v3.0.0-rc7 | [slither-report.md](./security/audits/tools/v3.0.0-rc7/slither-report.md) | [slither-report-feedback.md](./security/audits/tools/v3.0.0-rc7/slither-report-feedback.md) | | v3.0.0-rc6 | [slither-report.md](./security/audits/tools/v3.0.0-rc6/slither-report.md) | [slither-report-feedback.md](./security/audits/tools/v3.0.0-rc6/slither-report-feedback.md) | | v3.0.0-rc5 | [slither-report.md](./security/audits/tools/v3.0.0-rc5/slither-report.md) | [slither-report-feedback.md](./security/audits/tools/v3.0.0-rc5/slither-report-feedback.md) | | v3.0.0-rc4 | [slither-report.md](./security/audits/tools/v3.0.0-rc4/slither-report.md) | [slither-report-feedback.md](./security/audits/tools/v3.0.0-rc4/slither-report-feedback.md) | @@ -1564,7 +1760,7 @@ Here is the list of report performed with [Slither](https://github.com/crytic/sl slither . --checklist --filter-paths "openzeppelin-contracts|test|CMTAT|forge-std|mocks" > slither-report.md ``` -Latest run (v3.0.0-rc6, 108 contracts analysed, mocks excluded): 2 finding categories — +Latest run (v3.0.0-rc7, `29556e5`, 111 contracts analysed, mocks excluded; findings unchanged from rc6): 2 finding categories — 0 High · 0 Medium · 10 Low · 2 Informational. **Nothing to fix.** | ID | Detector | Impact | Instances | Assessment | @@ -1582,23 +1778,24 @@ aderyn -x mocks --output aderyn-report.md | Version | Report | Assessment | | ------- | ------ | ---------- | +| v3.0.0-rc7 | [aderyn-report.md](./security/audits/tools/v3.0.0-rc7/aderyn-report.md) | [aderyn-report-feedback.md](./security/audits/tools/v3.0.0-rc7/aderyn-report-feedback.md) | | v3.0.0-rc6 | [aderyn-report.md](./security/audits/tools/v3.0.0-rc6/aderyn-report.md) | [aderyn-report-feedback.md](./security/audits/tools/v3.0.0-rc6/aderyn-report-feedback.md) | | v3.0.0-rc5 | [aderyn-report.md](./security/audits/tools/v3.0.0-rc5/aderyn-report.md) | [aderyn-report-feedback.md](./security/audits/tools/v3.0.0-rc5/aderyn-report-feedback.md) | | v3.0.0-rc4 | [aderyn-report.md](./security/audits/tools/v3.0.0-rc4/aderyn-report.md) | [aderyn-report-feedback.md](./security/audits/tools/v3.0.0-rc4/aderyn-report-feedback.md) | | v3.0.0-rc3 | [aderyn-report.md](./security/audits/tools/v3.0.0-rc3/aderyn-report.md) | [aderyn-report-feedback.md](./security/audits/tools/v3.0.0-rc3/aderyn-report-feedback.md) | | v3.0.0-rc2 | [aderyn-report.md](./security/audits/tools/v3.0.0-rc2/aderyn-report.md) | [aderyn-report-feedback.md](./security/audits/tools/v3.0.0-rc2/aderyn-report-feedback.md) | -Latest run (v3.0.0-rc6): 28 Solidity files, 683 nSLOC, mocks excluded. +Latest run (v3.0.0-rc7, `29556e5`): 31 Solidity files, 716 nSLOC, mocks excluded. Findings unchanged from rc6. -0 High · 8 Low (84 instances). **Nothing to fix.** +0 High · 8 Low (91 instances). **Nothing to fix.** | ID | Finding | Instances | Assessment | |----|---------|-----------|------------| | L-1 | Centralization Risk | 14 | Accepted by design — privileged compliance tool | -| L-2 | Unspecific Solidity Pragma | 23 | Accepted by design — intentional for library reusability | -| L-3 | PUSH0 Opcode | 28 | Not applicable — project targets Prague EVM | +| L-2 | Unspecific Solidity Pragma | 26 | Accepted by design — intentional for library reusability | +| L-3 | PUSH0 Opcode | 31 | Not applicable — project targets the Osaka EVM, which has PUSH0 (since Shanghai) | | L-4 | Modifier Invoked Only Once | 1 | Accepted by design — keeps hook-style access-control abstraction | -| L-5 | Empty Block | 9 | Accepted by design — access-control hook pattern | +| L-5 | Empty Block | 10 | Accepted by design — access-control hook pattern, and the default binding-target hook | | L-6 | Loop Contains `require`/`revert` | 4 | Accepted by design — `setRules` and `bindTokens`/`unbindTokens` are atomic batch operations | | L-7 | Costly Operations Inside Loop | 4 | Accepted — unavoidable `SSTORE` in batch operations | | L-8 | Unchecked Return | 1 | Accepted — `_grantRole` return is irrelevant in constructor | @@ -1616,7 +1813,7 @@ Here a summary of the main documentation | Token binding module (reusable outside this project) | [doc/technical/TokenBinding-module.md](./technical/TokenBinding-module.md) | | Toolchain | [doc/TOOLCHAIN.md](./TOOLCHAIN.md) | | Surya report | [doc/schema/surya](./schema/surya/) | -| Code-quality review | [doc/security/audits/tools/v3.0.0-rc6/CLAUDE_ANALYSIS.md](./security/audits/tools/v3.0.0-rc6/CLAUDE_ANALYSIS.md) | +| Code-quality review (incl. tests) | [doc/security/audits/tools/v3.0.0-rc7/CLAUDE_ANALYSIS.md](./security/audits/tools/v3.0.0-rc7/CLAUDE_ANALYSIS.md) | | Script review | [doc/security/audits/tools/v3.0.0-rc5/CLAUDE_ANALYSIS_SCRIPT.md](./security/audits/tools/v3.0.0-rc5/CLAUDE_ANALYSIS_SCRIPT.md) | | Audit overview | [doc/security/audits/AUDIT_OVERVIEW.md](./security/audits/AUDIT_OVERVIEW.md) | @@ -1635,13 +1832,13 @@ Parts of this project were written with the help of AI coding assistants, princi Here are the settings for [Hardhat](https://hardhat.org) and [Foundry](https://getfoundry.sh). - `hardhat.config.js` - - Solidity [v0.8.36](https://docs.soliditylang.org/en/v0.8.36/) - - EVM version: Prague (Pectra upgrade) + - Solidity [v0.8.37](https://docs.soliditylang.org/en/v0.8.37/) + - EVM version: Osaka (Fusaka upgrade) - Optimizer: true, 200 runs - `foundry.toml` - - Solidity [v0.8.36](https://docs.soliditylang.org/en/v0.8.36/) - - EVM version: Prague (Pectra upgrade) + - Solidity [v0.8.37](https://docs.soliditylang.org/en/v0.8.37/) + - EVM version: Osaka (Fusaka upgrade) - Optimizer: true, 200 runs @@ -1679,24 +1876,31 @@ The official documentation is available in the Foundry [website](https://book.ge forge build # Build specific contract -forge build --contracts src/deployment/RuleEngine.sol -forge build --contracts src/deployment/RuleEngineOwnable.sol -forge build --contracts src/deployment/RuleEngineOwnable2Step.sol +forge build --contracts src/deployment/accessControl/RuleEngine.sol +forge build --contracts src/deployment/ownable/RuleEngineOwnable.sol +forge build --contracts src/deployment/ownable/RuleEngineOwnable2Step.sol ``` + +The compiled artifacts of the six deployables for v3.0.0-rc7 (ABI, bytecode, metadata; solc 0.8.37, EVM Osaka, optimizer 200 runs) are committed in [doc/compilation/v3.0.0-rc7](./compilation/v3.0.0-rc7): `foundry/` holds the `forge build` output (`out/`), `hardhat/` the `npx hardhat compile` output (`artifacts/`, the `.dbg.json` files point to a `build-info` file that is not committed). Both toolchains produce the same runtime bytecode size. + ### Contract size ```bash forge build --sizes ``` -Latest output (`2026-03-18`) for the main RuleEngine contracts: +Latest output (`2026-10-16`, v3.0.0-rc7) for the six deployables: | Contract | Runtime Size (B) | Initcode Size (B) | Runtime Margin (B) | Initcode Margin (B) | |----------|------------------:|------------------:|--------------------:|---------------------:| -| RuleEngine | 6,756 | 7,805 | 17,820 | 41,347 | -| RuleEngineOwnable | 6,170 | 6,833 | 18,406 | 42,319 | +| RuleEngine | 7,997 | 8,943 | 16,579 | 40,209 | +| RuleEngine2771 | 8,400 | 9,616 | 16,176 | 39,536 | +| RuleEngineOwnable | 6,970 | 7,708 | 17,606 | 41,444 | +| RuleEngineOwnable2771 | 7,368 | 8,161 | 17,208 | 40,991 | +| RuleEngineOwnable2Step | 7,219 | 7,982 | 17,357 | 41,170 | +| RuleEngineOwnable2Step2771 | 7,657 | 8,475 | 16,919 | 40,677 | -Both `RuleEngine` and `RuleEngineOwnable` remain well below the EIP-170 runtime limit. `RuleEngineOwnable` is slightly smaller because `Ownable` has less overhead than `AccessControl`. +All six remain well below the EIP-170 runtime limit (24,576 B). The ownable variants are smaller because `Ownable` has less overhead than `AccessControlEnumerable`, and each `*2771` variant adds about 400 B for the trusted forwarder. ### Testing @@ -1718,6 +1922,14 @@ Generate gas report forge test --gas-report ``` +The tests that deploy the real ERC-3643 token (T-REX 4.2.0-beta1, `pragma solidity 0.8.30`) run in a dedicated profile and are skipped by the default one: + +```bash +FOUNDRY_PROFILE=erc3643 forge test +``` + +CI runs both profiles (`.github/workflows/ci.yml`). See [RuleEngine-with-ERC3643.md §4.8](./technical/RuleEngine-with-ERC3643.md#48-the-real-t-rex-token-is-tested-in-a-separate-foundry-profile). + See also the test framework's [official documentation](https://book.getfoundry.sh/forge/tests), and that of the [test commands](https://book.getfoundry.sh/reference/forge/test-commands). There is also a small Hardhat smoke test to confirm the main `RuleEngine` contract can be compiled and deployed through Hardhat: @@ -1758,8 +1970,10 @@ The official documentation is available in the Foundry [website](https://getfoun | Scenario | Recommended Contract | |----------|---------------------| | Multiple operators with different permissions | `RuleEngine` | +| Multiple operators, administration through gasless meta-transactions | `RuleEngine2771` | | Single administrator | `RuleEngineOwnable` | | Single administrator with safer ownership handover | `RuleEngineOwnable2Step` | +| Any of the above, administered through gasless meta-transactions | the same contract with the `2771` suffix | | Integration with existing RBAC systems | `RuleEngine` | | Simpler deployment and management | `RuleEngineOwnable` | @@ -1811,11 +2025,13 @@ forge script script/RuleEngineScript.s.sol:RuleEngineScript --rpc-url=127.0.0.1: #### Production Deployment Checklist -- Choose the deployable variant: `RuleEngine`, `RuleEngineOwnable`, or `RuleEngineOwnable2Step`. -- Choose the trusted forwarder address, or use `address(0)` if ERC-2771 support is not needed. +- Choose the access-control model (`RuleEngine`, `RuleEngineOwnable` or `RuleEngineOwnable2Step`), then whether it needs ERC-2771. +- If ERC-2771 support is needed, deploy the `*2771` version and choose its trusted forwarder address; otherwise deploy the version without the suffix. A forwarder must be a signature-verifying ERC-2771 forwarder: it can relay administrative calls (rule management, binding) on behalf of any operator who signs them. It cannot act as a token (see [Gasless support](#gasless-support-erc-2771)). - Decide whether the token should be bound in the constructor or later via `bindToken`. +- **CMTAT:** bind the token on the engine (`engine.bindToken(cmtat)`, or the constructor's `tokenContract` argument) — CMTAT never self-binds, and an engine with no bound token rejects every transfer with `TokenBinding_UnauthorizedCaller`. Then point the token at the engine with `cmtat.setRuleEngine(engine)` (token `DEFAULT_ADMIN_ROLE`), or pass it at token construction. +- **ERC-3643:** grant `setTokenSelfBindingApproval(token, true)` on the engine **before** calling `token.setCompliance(engine)`, which self-binds the token. - Source production rule contracts from the [CMTA/Rules](https://github.com/CMTA/Rules) repository, not from `src/mocks/`. -- Verify post-deployment permissions: owner for ownable variants, or admin plus role assignments for the RBAC variant. +- Verify post-deployment permissions: owner for ownable variants, or admin plus role assignments for the RBAC variants. ### Solidity style guideline diff --git a/doc/TOOLCHAIN.md b/doc/TOOLCHAIN.md index f3c6e6c9..cb445c8a 100644 --- a/doc/TOOLCHAIN.md +++ b/doc/TOOLCHAIN.md @@ -52,9 +52,9 @@ Warning: The current tested baseline is: -- Solidity: [0.8.36](https://docs.soliditylang.org/en/v0.8.36/) -- OpenZeppelin Contracts (submodule): [v5.6.1](https://github.com/OpenZeppelin/openzeppelin-contracts/releases/tag/v5.6.1) -- CMTAT: [v3.2.0](https://github.com/CMTA/CMTAT/releases/tag/v3.2.0) +- Solidity: [0.8.37](https://docs.soliditylang.org/en/v0.8.37/) +- OpenZeppelin Contracts (submodule): [v5.7.0](https://github.com/OpenZeppelin/openzeppelin-contracts/releases/tag/v5.7.0) +- CMTAT: [v3.3.0-rc4](https://github.com/CMTA/CMTAT/releases/tag/v3.3.0-rc4) @@ -114,7 +114,7 @@ npm run-script surya:graph ``` ```bash -npx surya graph src/deployment/RuleEngine.sol | dot -Tpng > surya_graph_RuleEngine.png +npx surya graph src/deployment/accessControl/RuleEngine.sol | dot -Tpng > surya_graph_RuleEngine.png ``` #### Report diff --git a/doc/compilation/v3.0.0-rc2/foundry/RuleEngine.sol/RuleEngine.json b/doc/compilation/v3.0.0-rc2/foundry/RuleEngine.sol/RuleEngine.json deleted file mode 100644 index c6d205d6..00000000 --- a/doc/compilation/v3.0.0-rc2/foundry/RuleEngine.sol/RuleEngine.json +++ /dev/null @@ -1 +0,0 @@ -{"abi":[{"type":"constructor","inputs":[{"name":"admin","type":"address","internalType":"address"},{"name":"forwarderIrrevocable","type":"address","internalType":"address"},{"name":"tokenContract","type":"address","internalType":"address"}],"stateMutability":"nonpayable"},{"type":"function","name":"COMPLIANCE_MANAGER_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"DEFAULT_ADMIN_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"RULES_MANAGEMENT_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"addRule","inputs":[{"name":"rule_","type":"address","internalType":"contract IRule"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"bindToken","inputs":[{"name":"token","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"canTransfer","inputs":[{"name":"from","type":"address","internalType":"address"},{"name":"to","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"canTransferFrom","inputs":[{"name":"spender","type":"address","internalType":"address"},{"name":"from","type":"address","internalType":"address"},{"name":"to","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"clearRules","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"containsRule","inputs":[{"name":"rule_","type":"address","internalType":"contract IRule"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"created","inputs":[{"name":"to","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"destroyed","inputs":[{"name":"from","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"detectTransferRestriction","inputs":[{"name":"from","type":"address","internalType":"address"},{"name":"to","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint8","internalType":"uint8"}],"stateMutability":"view"},{"type":"function","name":"detectTransferRestrictionFrom","inputs":[{"name":"spender","type":"address","internalType":"address"},{"name":"from","type":"address","internalType":"address"},{"name":"to","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint8","internalType":"uint8"}],"stateMutability":"view"},{"type":"function","name":"getRoleAdmin","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"getRoleMember","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"index","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"getRoleMemberCount","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getRoleMembers","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"","type":"address[]","internalType":"address[]"}],"stateMutability":"view"},{"type":"function","name":"getTokenBound","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"getTokenBounds","inputs":[],"outputs":[{"name":"","type":"address[]","internalType":"address[]"}],"stateMutability":"view"},{"type":"function","name":"grantRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"hasRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"isTokenBound","inputs":[{"name":"token","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"isTrustedForwarder","inputs":[{"name":"forwarder","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"messageForTransferRestriction","inputs":[{"name":"restrictionCode","type":"uint8","internalType":"uint8"}],"outputs":[{"name":"","type":"string","internalType":"string"}],"stateMutability":"view"},{"type":"function","name":"removeRule","inputs":[{"name":"rule_","type":"address","internalType":"contract IRule"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"renounceRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"callerConfirmation","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"revokeRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"rule","inputs":[{"name":"ruleId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"rules","inputs":[],"outputs":[{"name":"","type":"address[]","internalType":"address[]"}],"stateMutability":"view"},{"type":"function","name":"rulesCount","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"setRules","inputs":[{"name":"rules_","type":"address[]","internalType":"contract IRule[]"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"supportsInterface","inputs":[{"name":"interfaceId","type":"bytes4","internalType":"bytes4"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"transferred","inputs":[{"name":"spender","type":"address","internalType":"address"},{"name":"from","type":"address","internalType":"address"},{"name":"to","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"transferred","inputs":[{"name":"from","type":"address","internalType":"address"},{"name":"to","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"trustedForwarder","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"unbindToken","inputs":[{"name":"token","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"version","inputs":[],"outputs":[{"name":"version_","type":"string","internalType":"string"}],"stateMutability":"view"},{"type":"event","name":"AddRule","inputs":[{"name":"rule","type":"address","indexed":true,"internalType":"contract IRule"}],"anonymous":false},{"type":"event","name":"ClearRules","inputs":[],"anonymous":false},{"type":"event","name":"RemoveRule","inputs":[{"name":"rule","type":"address","indexed":true,"internalType":"contract IRule"}],"anonymous":false},{"type":"event","name":"RoleAdminChanged","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"previousAdminRole","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"newAdminRole","type":"bytes32","indexed":true,"internalType":"bytes32"}],"anonymous":false},{"type":"event","name":"RoleGranted","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"account","type":"address","indexed":true,"internalType":"address"},{"name":"sender","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"RoleRevoked","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"account","type":"address","indexed":true,"internalType":"address"},{"name":"sender","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"TokenBound","inputs":[{"name":"token","type":"address","indexed":false,"internalType":"address"}],"anonymous":false},{"type":"event","name":"TokenUnbound","inputs":[{"name":"token","type":"address","indexed":false,"internalType":"address"}],"anonymous":false},{"type":"error","name":"AccessControlBadConfirmation","inputs":[]},{"type":"error","name":"AccessControlUnauthorizedAccount","inputs":[{"name":"account","type":"address","internalType":"address"},{"name":"neededRole","type":"bytes32","internalType":"bytes32"}]},{"type":"error","name":"RuleEngine_AdminWithAddressZeroNotAllowed","inputs":[]},{"type":"error","name":"RuleEngine_ERC3643Compliance_InvalidTokenAddress","inputs":[]},{"type":"error","name":"RuleEngine_ERC3643Compliance_OperationNotSuccessful","inputs":[]},{"type":"error","name":"RuleEngine_ERC3643Compliance_TokenAlreadyBound","inputs":[]},{"type":"error","name":"RuleEngine_ERC3643Compliance_TokenNotBound","inputs":[]},{"type":"error","name":"RuleEngine_ERC3643Compliance_UnauthorizedCaller","inputs":[]},{"type":"error","name":"RuleEngine_RuleInvalidInterface","inputs":[]},{"type":"error","name":"RuleEngine_RulesManagementModule_ArrayIsEmpty","inputs":[]},{"type":"error","name":"RuleEngine_RulesManagementModule_OperationNotSuccessful","inputs":[]},{"type":"error","name":"RuleEngine_RulesManagementModule_RuleAddressZeroNotAllowed","inputs":[]},{"type":"error","name":"RuleEngine_RulesManagementModule_RuleAlreadyExists","inputs":[]},{"type":"error","name":"RuleEngine_RulesManagementModule_RuleDoNotMatch","inputs":[]}],"bytecode":{"object":"0x60a060405234801561000f575f5ffd5b5060405161200438038061200483398101604081905261002e91610385565b6001600160a01b03808316608052831661005b57604051630872273360e21b815260040160405180910390fd5b6001600160a01b038116156100735761007381610086565b61007d5f8461013d565b50505050610424565b6001600160a01b0381166100ad576040516301b8831760e71b815260040160405180910390fd5b6100b8600282610173565b156100d65760405163f423354760e01b815260040160405180910390fd5b6100e1600282610194565b6100fe57604051631b4ddcf360e11b815260040160405180910390fd5b6040516001600160a01b03821681527f2de35142b19ed5a07796cf30791959c592018f70b1d2d7c460eef8ffe713692b9060200160405180910390a150565b5f8061014984846101a8565b9050801561016a575f8481526005602052604090206101689084610194565b505b90505b92915050565b6001600160a01b0381165f908152600183016020526040812054151561016a565b5f61016a836001600160a01b03841661023a565b5f6101b3838361027f565b610233575f8381526004602090815260408083206001600160a01b03861684529091529020805460ff191660011790556101eb6102f1565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a450600161016d565b505f61016d565b5f81815260018301602052604081205461023357508154600181810184555f84815260208082209093018490558454848252828601909352604090209190915561016d565b6001600160a01b0381165f9081527f17ef568e3e12ab5b9c7254a8d58478811de00f9e6eb34345acd53bf8fd09d3ec602052604081205460ff16156102c65750600161016d565b505f8281526004602090815260408083206001600160a01b038516845290915290205460ff1661016d565b5f6102fa6102ff565b905090565b5f366014808210801590610317575061031733610345565b1561033d5761032a36828403815f6103c5565b610333916103ec565b60601c9250505090565b339250505090565b5f61034f60805190565b6001600160a01b0316826001600160a01b0316149050919050565b80516001600160a01b0381168114610380575f5ffd5b919050565b5f5f5f60608486031215610397575f5ffd5b6103a08461036a565b92506103ae6020850161036a565b91506103bc6040850161036a565b90509250925092565b5f5f858511156103d3575f5ffd5b838611156103df575f5ffd5b5050820193919092039150565b80356001600160601b0319811690601484101561041d576001600160601b0319601485900360031b81901b82161691505b5092915050565b608051611bba61044a5f395f8181610364015281816103dc01526113460152611bba5ff3fe608060405234801561000f575f5ffd5b506004361061021e575f3560e01c80638d2ea7721161012a578063bc13eacc116100b4578063db18af6c11610079578063db18af6c14610534578063df21950f14610547578063e3c4602c1461055a578063e46638e61461056d578063e54621d214610580575f5ffd5b8063bc13eacc146104ce578063ca15c873146104d6578063d32c7bb5146104e9578063d4ce14151461050e578063d547741f14610521575f5ffd5b80639b11c115116100fa5780639b11c11514610472578063a217fddf14610499578063a3246ad3146104a0578063b043572e146104b3578063b27aef3a146104bb575f5ffd5b80638d2ea772146104265780639010d07c1461043957806391d148541461044c578063993e8b951461045f575f5ffd5b806354e4b945116101ab5780636a3edf281161017b5780636a3edf28146103a75780637157797f146103c75780637da0a877146103da5780637f4ab1dd146104005780638baf29b414610413575f5ffd5b806354e4b9451461031757806354fd4d501461032a578063572b6c05146103545780635f8dead314610394575f5ffd5b806336568abe116101f157806336568abe146102b65780633e5af4ca146102c95780633ff5aa02146102dc57806340db3b50146102ef57806352f6747a14610302575f5ffd5b806301ffc9a71461022257806303c26bcd1461024a578063248a9ca31461027f5780632f2ff15d146102a1575b5f5ffd5b61023561023036600461174a565b610588565b60405190151581526020015b60405180910390f35b6102717fe5c50d0927e06141e032cb9a67e1d7092dc85c0b0825191f7e1cede60002856881565b604051908152602001610241565b61027161028d366004611771565b5f9081526004602052604090206001015490565b6102b46102af36600461179c565b6105a7565b005b6102b46102c436600461179c565b6105d1565b6102b46102d73660046117ca565b610619565b6102b46102ea366004611818565b61062d565b6102b46102fd366004611818565b610641565b61030a610652565b6040516102419190611833565b610235610325366004611818565b610662565b6040805180820190915260058152640332e302e360dc1b60208201525b604051610241919061187e565b610235610362366004611818565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0390811691161490565b6102b46103a23660046118b3565b61066d565b6103af610684565b6040516001600160a01b039091168152602001610241565b6102356103d53660046117ca565b6106a6565b7f00000000000000000000000000000000000000000000000000000000000000006103af565b61034761040e3660046118eb565b6106c3565b6102b4610421366004611906565b6106ce565b6102b46104343660046118b3565b6106e1565b6103af610447366004611944565b6106f4565b61023561045a36600461179c565b610712565b61023561046d366004611818565b610784565b6102717fea5f4eb72290e50c32abd6c23e45de3d8300b3286e1cbc2e293114b92e034e5e81565b6102715f81565b61030a6104ae366004611771565b610790565b6102b46107a9565b6102b46104c9366004611964565b6107bb565b6102716108e7565b6102716104e4366004611771565b6108f1565b6104fc6104f73660046117ca565b610907565b60405160ff9091168152602001610241565b6104fc61051c366004611906565b61091d565b6102b461052f36600461179c565b610929565b6103af610542366004611771565b61094d565b6102b4610555366004611818565b61096f565b6102b4610568366004611818565b6109a7565b61023561057b366004611906565b610a15565b61030a610a2e565b5f61059282610a3a565b806105a157506105a182610aa5565b92915050565b5f828152600460205260409020600101546105c181610ac9565b6105cb8383610ada565b50505050565b6105d9610b0d565b6001600160a01b0316816001600160a01b03161461060a5760405163334bd91960e11b815260040160405180910390fd5b6106148282610b16565b505050565b610621610b41565b6105cb84848484610b71565b610635610c13565b61063e81610c3d565b50565b610649610c13565b61063e81610cf5565b606061065d5f610d7e565b905090565b5f6105a18183610d8a565b610675610b41565b6106805f8383610dab565b5050565b5f5f6106906002610e44565b11156106a15761065d60025f610e4d565b505f90565b5f806106b486868686610907565b60ff161490505b949350505050565b60606105a182610e58565b6106d6610b41565b610614838383610dab565b6106e9610b41565b610680825f83610dab565b5f82815260056020526040812061070b9083610e4d565b9392505050565b6001600160a01b0381165f9081527f17ef568e3e12ab5b9c7254a8d58478811de00f9e6eb34345acd53bf8fd09d3ec602052604081205460ff1615610759575060016105a1565b505f8281526004602090815260408083206001600160a01b038516845290915290205460ff166105a1565b5f6105a1600283610d8a565b5f8181526005602052604090206060906105a190610d7e565b6107b1610fa2565b6107b9610fcc565b565b6107c3610fa2565b5f8190036107e4576040516359203cb960e01b815260040160405180910390fd5b5f6107ee5f610e44565b11156107fc576107fc610fcc565b5f5b818110156106145761083583838381811061081b5761081b6119d5565b90506020020160208101906108309190611818565b610ffd565b61086683838381811061084a5761084a6119d5565b905060200201602081019061085f9190611818565b5f90611034565b6108835760405163f280d16160e01b815260040160405180910390fd5b828282818110610895576108956119d5565b90506020020160208101906108aa9190611818565b6001600160a01b03167f60305ce6c9104acd0969d358f926bf391174340660aaf5e6215261fd6847bf4660405160405180910390a26001016107fe565b5f61065d5f610e44565b5f8181526005602052604081206105a190610e44565b5f61091485858585611048565b95945050505050565b5f6106bb848484611113565b5f8281526004602052604090206001015461094381610ac9565b6105cb8383610b16565b5f6109575f610e44565b821015610968576105a15f83610e4d565b505f919050565b610977610fa2565b6109815f82610d8a565b61099e57604051632cdc3a4160e21b815260040160405180910390fd5b61063e816111d5565b6109af610fa2565b6109b881610ffd565b6109c25f82611034565b6109df5760405163f280d16160e01b815260040160405180910390fd5b6040516001600160a01b038216907f60305ce6c9104acd0969d358f926bf391174340660aaf5e6215261fd6847bf46905f90a250565b5f80610a2285858561091d565b60ff1614949350505050565b606061065d6002610d7e565b5f6001600160e01b031982166320c49ce760e01b1480610a6a57506001600160e01b031982166378a8de7d60e01b145b80610a8557506001600160e01b03198216630c51264760e21b145b806105a157506001600160e01b03198216637157797f60e01b1492915050565b5f6001600160e01b03198216635a05180f60e01b14806105a157506105a182611232565b61063e81610ad5610b0d565b611266565b5f5f610ae684846112a3565b9050801561070b575f848152600560205260409020610b059084611034565b509392505050565b5f61065d611335565b5f5f610b22848461139f565b9050801561070b575f848152600560205260409020610b059084611428565b610b54610b4c610b0d565b600290610d8a565b6107b95760405163e39b3c8f60e01b815260040160405180910390fd5b5f610b7b5f610e44565b90505f5b81811015610c0b57610b915f82610e4d565b604051631f2d7a6560e11b81526001600160a01b03888116600483015287811660248301528681166044830152606482018690529190911690633e5af4ca906084015f604051808303815f87803b158015610bea575f5ffd5b505af1158015610bfc573d5f5f3e3d5ffd5b50505050806001019050610b7f565b505050505050565b7fe5c50d0927e06141e032cb9a67e1d7092dc85c0b0825191f7e1cede60002856861063e81610ac9565b6001600160a01b038116610c64576040516301b8831760e71b815260040160405180910390fd5b610c6f600282610d8a565b15610c8d5760405163f423354760e01b815260040160405180910390fd5b610c98600282611034565b610cb557604051631b4ddcf360e11b815260040160405180910390fd5b6040516001600160a01b03821681527f2de35142b19ed5a07796cf30791959c592018f70b1d2d7c460eef8ffe713692b906020015b60405180910390a150565b610d00600282610d8a565b610d1d57604051636a2b488360e11b815260040160405180910390fd5b610d28600282611428565b610d4557604051631b4ddcf360e11b815260040160405180910390fd5b6040516001600160a01b03821681527f28a4ca7134a3b3f9aff286e79ad3daadb4a06d1b43d037a3a98bdc074edd9b7a90602001610cea565b60605f61070b8361143c565b6001600160a01b0381165f908152600183016020526040812054151561070b565b5f610db55f610e44565b90505f5b81811015610e3d57610dcb5f82610e4d565b6040516322ebca6d60e21b81526001600160a01b0387811660048301528681166024830152604482018690529190911690638baf29b4906064015f604051808303815f87803b158015610e1c575f5ffd5b505af1158015610e2e573d5f5f3e3d5ffd5b50505050806001019050610db9565b5050505050565b5f6105a1825490565b5f61070b8383611495565b60605f610e636108e7565b90505f5b81811015610f6657610e788161094d565b604051633e822efb60e11b815260ff861660048201526001600160a01b039190911690637d045df690602401602060405180830381865afa158015610ebf573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ee391906119e9565b15610f5e57610ef18161094d565b604051637f4ab1dd60e01b815260ff861660048201526001600160a01b039190911690637f4ab1dd906024015f60405180830381865afa158015610f37573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526106bb9190810190611a1c565b600101610e67565b505060408051808201909152601881527f556e6b6e6f776e207265737472696374696f6e20636f64650000000000000000602082015292915050565b7fea5f4eb72290e50c32abd6c23e45de3d8300b3286e1cbc2e293114b92e034e5e61063e81610ac9565b6040517fdbf61473843cd9be1c9791ce51ef66d0da6c9026d62ba80c1ca433b13fb729b2905f90a16107b95f6114bb565b611006816114c4565b61101781632497d6cb60e01b611513565b61063e57604051639952e34360e01b815260040160405180910390fd5b5f61070b836001600160a01b03841661152e565b5f5f6110526108e7565b90505f5b81811015611107575f6110688261094d565b60405163d32c7bb560e01b81526001600160a01b038a811660048301528981166024830152888116604483015260648201889052919091169063d32c7bb590608401602060405180830381865afa1580156110c5573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110e99190611acf565b905060ff8116156110fe5792506106bb915050565b50600101611056565b505f9695505050505050565b5f5f61111d6108e7565b90505f5b818110156111ca575f6111338261094d565b60405163d4ce141560e01b81526001600160a01b038981166004830152888116602483015260448201889052919091169063d4ce141590606401602060405180830381865afa158015611188573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111ac9190611acf565b905060ff8116156111c157925061070b915050565b50600101611121565b505f95945050505050565b6111df5f82611428565b6111fc5760405163f280d16160e01b815260040160405180910390fd5b6040516001600160a01b038216907f6d83315c9718799346b67584ec64301b1457e989c8e35a8e2982a7776c04bfc4905f90a250565b5f6001600160e01b03198216637965db0b60e01b14806105a157506301ffc9a760e01b6001600160e01b03198316146105a1565b6112708282610712565b6106805760405163e2517d3f60e01b81526001600160a01b03821660048201526024810183905260440160405180910390fd5b5f6112ae8383610712565b61132e575f8381526004602090815260408083206001600160a01b03861684529091529020805460ff191660011790556112e6610b0d565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45060016105a1565b505f6105a1565b5f36601480821080159061137157507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031633145b156113975761138436828403815f611aea565b61138d91611b11565b60601c9250505090565b339250505090565b5f6113aa8383610712565b1561132e575f8381526004602090815260408083206001600160a01b03861684529091529020805460ff191690556113e0610b0d565b6001600160a01b0316826001600160a01b0316847ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a45060016105a1565b5f61070b836001600160a01b038416611573565b6060815f0180548060200260200160405190810160405280929190818152602001828054801561148957602002820191905f5260205f20905b815481526020019060010190808311611475575b50505050509050919050565b5f825f0182815481106114aa576114aa6119d5565b905f5260205f200154905092915050565b61063e8161165d565b6001600160a01b0381166114eb5760405163f9d152fb60e01b815260040160405180910390fd5b6114f55f82610d8a565b1561063e5760405163cc790a4b60e01b815260040160405180910390fd5b5f61151d836116b6565b801561070b575061070b83836116f5565b5f81815260018301602052604081205461132e57508154600181810184555f8481526020808220909301849055845484825282860190935260409020919091556105a1565b5f818152600183016020526040812054801561164d575f611595600183611b51565b85549091505f906115a890600190611b51565b9050808214611607575f865f0182815481106115c6576115c66119d5565b905f5260205f200154905080875f0184815481106115e6576115e66119d5565b5f918252602080832090910192909255918252600188019052604090208390555b855486908061161857611618611b70565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f9055600193505050506105a1565b5f9150506105a1565b5092915050565b5f611666825490565b90505f5b818110156116af57826001015f845f01838154811061168b5761168b6119d5565b905f5260205f20015481526020019081526020015f205f905580600101905061166a565b50505f9055565b5f6116c8826301ffc9a760e01b6116f5565b15610968575f806116e1846001600160e01b0319611716565b915091508180156106bb5750159392505050565b5f5f5f6117028585611716565b915091508180156109145750949350505050565b6301ffc9a760e01b5f818152600483905290819060208260248188617530fa92505f511515601f3d11169150509250929050565b5f6020828403121561175a575f5ffd5b81356001600160e01b03198116811461070b575f5ffd5b5f60208284031215611781575f5ffd5b5035919050565b6001600160a01b038116811461063e575f5ffd5b5f5f604083850312156117ad575f5ffd5b8235915060208301356117bf81611788565b809150509250929050565b5f5f5f5f608085870312156117dd575f5ffd5b84356117e881611788565b935060208501356117f881611788565b9250604085013561180881611788565b9396929550929360600135925050565b5f60208284031215611828575f5ffd5b813561070b81611788565b602080825282518282018190525f918401906040840190835b818110156118735783516001600160a01b031683526020938401939092019160010161184c565b509095945050505050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b5f5f604083850312156118c4575f5ffd5b82356118cf81611788565b946020939093013593505050565b60ff8116811461063e575f5ffd5b5f602082840312156118fb575f5ffd5b813561070b816118dd565b5f5f5f60608486031215611918575f5ffd5b833561192381611788565b9250602084013561193381611788565b929592945050506040919091013590565b5f5f60408385031215611955575f5ffd5b50508035926020909101359150565b5f5f60208385031215611975575f5ffd5b823567ffffffffffffffff81111561198b575f5ffd5b8301601f8101851361199b575f5ffd5b803567ffffffffffffffff8111156119b1575f5ffd5b8560208260051b84010111156119c5575f5ffd5b6020919091019590945092505050565b634e487b7160e01b5f52603260045260245ffd5b5f602082840312156119f9575f5ffd5b8151801515811461070b575f5ffd5b634e487b7160e01b5f52604160045260245ffd5b5f60208284031215611a2c575f5ffd5b815167ffffffffffffffff811115611a42575f5ffd5b8201601f81018413611a52575f5ffd5b805167ffffffffffffffff811115611a6c57611a6c611a08565b604051601f8201601f19908116603f0116810167ffffffffffffffff81118282101715611a9b57611a9b611a08565b604052818152828201602001861015611ab2575f5ffd5b8160208401602083015e5f91810160200191909152949350505050565b5f60208284031215611adf575f5ffd5b815161070b816118dd565b5f5f85851115611af8575f5ffd5b83861115611b04575f5ffd5b5050820193919092039150565b80356bffffffffffffffffffffffff198116906014841015611656576bffffffffffffffffffffffff1960149490940360031b84901b1690921692915050565b818103818111156105a157634e487b7160e01b5f52601160045260245ffd5b634e487b7160e01b5f52603160045260245ffdfea2646970667358221220b03f8c635c82b542156a657e05e1b25daf4da0550801960bc81efa2b41c0ae9d64736f6c63430008220033","sourceMap":"787:2684:163:-:0;;;1052:393;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;1542:37:135;;;;;1204:19:163;::::1;1200:100;;1246:43;;-1:-1:-1::0;;;1246:43:163::1;;;;;;;;;;;1200:100;-1:-1:-1::0;;;;;1313:27:163;::::1;::::0;1309:83:::1;;1356:25;1367:13:::0;1356:10:::1;:25::i;:::-;1401:37;2232:4:126;1432:5:163::0;1401:10:::1;:37::i;:::-;;1052:393:::0;;;787:2684;;3688:459:186;-1:-1:-1;;;;;3750:19:186;;3742:80;;;;-1:-1:-1;;;3742:80:186;;;;;;;;;;;;3841:28;:12;3863:5;3841:21;:28::i;:::-;3840:29;3832:88;;;;-1:-1:-1;;;3832:88:186;;;;;;;;;;;;4029:23;:12;4046:5;4029:16;:23::i;:::-;4021:87;;;;-1:-1:-1;;;4021:87:186;;;;;;;;;;;;4123:17;;-1:-1:-1;;;;;743:32:231;;725:51;;4123:17:186;;713:2:231;698:18;4123:17:186;;;;;;;3688:459;:::o;2777:257:130:-;2863:4;;2894:31;2911:4;2917:7;2894:16;:31::i;:::-;2879:46;;2939:7;2935:69;;;2962:18;;;;:12;:18;;;;;:31;;2985:7;2962:22;:31::i;:::-;;2935:69;3020:7;-1:-1:-1;2777:257:130;;;;;:::o;16041:165:158:-;-1:-1:-1;;;;;16174:23:158;;16121:4;5238:21;;;:14;;;:21;;;;;;:26;;16144:55;5142:129;15089:150;15159:4;15182:50;15187:3;-1:-1:-1;;;;;15207:23:158;;15182:4;:50::i;6145:316:126:-;6222:4;6243:22;6251:4;6257:7;6243;:22::i;:::-;6238:217;;6281:12;;;;:6;:12;;;;;;;;-1:-1:-1;;;;;6281:29:126;;;;;;;;;:36;;-1:-1:-1;;6281:36:126;6313:4;6281:36;;;6363:12;:10;:12::i;:::-;-1:-1:-1;;;;;6336:40:126;6354:7;-1:-1:-1;;;;;6336:40:126;6348:4;6336:40;;;;;;;;;;-1:-1:-1;6397:4:126;6390:11;;6238:217;-1:-1:-1;6439:5:126;6432:12;;2538:406:158;2601:4;5238:21;;;:14;;;:21;;;;;;2617:321;;-1:-1:-1;2659:23:158;;;;;;;;:11;:23;;;;;;;;;;;;;2841:18;;2817:21;;;:14;;;:21;;;;;;:42;;;;2873:11;;1630:349:163;-1:-1:-1;;;;;2920:29:126;;1787:4:163;2920:29:126;;;:12;;:29;:12;:29;;;;;1807:166:163;;;-1:-1:-1;1884:4:163;1877:11;;1807:166;-1:-1:-1;2897:4:126;2920:12;;;:6;:12;;;;;;;;-1:-1:-1;;;;;2920:29:126;;;;;;;;;;;;1919:43:163;;2796:154;2883:14;2916:27;:25;:27::i;:::-;2909:34;;2796:154;:::o;2248:471:135:-;2310:7;2354:8;3609:2;2445:37;;;;;;:71;;-1:-1:-1;2486:30:135;2505:10;2486:18;:30::i;:::-;2441:272;;;2583:47;:8;2592:36;;;2583:8;;:47;:::i;:::-;2575:56;;;:::i;:::-;2567:65;;2560:72;;;;2248:471;:::o;2441:272::-;735:10:143;2677:25:135;;;;2248:471;:::o;1874:137::-;1950:4;1986:18;1749:17;;;1666:107;1986:18;-1:-1:-1;;;;;1973:31:135;:9;-1:-1:-1;;;;;1973:31:135;;1966:38;;1874:137;;;:::o;14:177:231:-;93:13;;-1:-1:-1;;;;;135:31:231;;125:42;;115:70;;181:1;178;171:12;115:70;14:177;;;:::o;196:378::-;284:6;292;300;353:2;341:9;332:7;328:23;324:32;321:52;;;369:1;366;359:12;321:52;392:40;422:9;392:40;:::i;:::-;382:50;;451:49;496:2;485:9;481:18;451:49;:::i;:::-;441:59;;519:49;564:2;553:9;549:18;519:49;:::i;:::-;509:59;;196:378;;;;;:::o;787:331::-;892:9;903;945:8;933:10;930:24;927:44;;;967:1;964;957:12;927:44;996:6;986:8;983:20;980:40;;;1016:1;1013;1006:12;980:40;-1:-1:-1;;1042:23:231;;;1087:25;;;;;-1:-1:-1;787:331:231:o;1123:350::-;1244:19;;-1:-1:-1;;;;;;1281:32:231;;;1333:2;1325:11;;1322:145;;;-1:-1:-1;;;;;;1395:2:231;1391:12;;;1388:1;1384:20;1380:50;;;1372:59;;1368:89;;-1:-1:-1;1322:145:231;;1123:350;;;;:::o;:::-;787:2684:163;;;;;;;;;;;;;;;;;;;;;;","linkReferences":{}},"deployedBytecode":{"object":"0x608060405234801561000f575f5ffd5b506004361061021e575f3560e01c80638d2ea7721161012a578063bc13eacc116100b4578063db18af6c11610079578063db18af6c14610534578063df21950f14610547578063e3c4602c1461055a578063e46638e61461056d578063e54621d214610580575f5ffd5b8063bc13eacc146104ce578063ca15c873146104d6578063d32c7bb5146104e9578063d4ce14151461050e578063d547741f14610521575f5ffd5b80639b11c115116100fa5780639b11c11514610472578063a217fddf14610499578063a3246ad3146104a0578063b043572e146104b3578063b27aef3a146104bb575f5ffd5b80638d2ea772146104265780639010d07c1461043957806391d148541461044c578063993e8b951461045f575f5ffd5b806354e4b945116101ab5780636a3edf281161017b5780636a3edf28146103a75780637157797f146103c75780637da0a877146103da5780637f4ab1dd146104005780638baf29b414610413575f5ffd5b806354e4b9451461031757806354fd4d501461032a578063572b6c05146103545780635f8dead314610394575f5ffd5b806336568abe116101f157806336568abe146102b65780633e5af4ca146102c95780633ff5aa02146102dc57806340db3b50146102ef57806352f6747a14610302575f5ffd5b806301ffc9a71461022257806303c26bcd1461024a578063248a9ca31461027f5780632f2ff15d146102a1575b5f5ffd5b61023561023036600461174a565b610588565b60405190151581526020015b60405180910390f35b6102717fe5c50d0927e06141e032cb9a67e1d7092dc85c0b0825191f7e1cede60002856881565b604051908152602001610241565b61027161028d366004611771565b5f9081526004602052604090206001015490565b6102b46102af36600461179c565b6105a7565b005b6102b46102c436600461179c565b6105d1565b6102b46102d73660046117ca565b610619565b6102b46102ea366004611818565b61062d565b6102b46102fd366004611818565b610641565b61030a610652565b6040516102419190611833565b610235610325366004611818565b610662565b6040805180820190915260058152640332e302e360dc1b60208201525b604051610241919061187e565b610235610362366004611818565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0390811691161490565b6102b46103a23660046118b3565b61066d565b6103af610684565b6040516001600160a01b039091168152602001610241565b6102356103d53660046117ca565b6106a6565b7f00000000000000000000000000000000000000000000000000000000000000006103af565b61034761040e3660046118eb565b6106c3565b6102b4610421366004611906565b6106ce565b6102b46104343660046118b3565b6106e1565b6103af610447366004611944565b6106f4565b61023561045a36600461179c565b610712565b61023561046d366004611818565b610784565b6102717fea5f4eb72290e50c32abd6c23e45de3d8300b3286e1cbc2e293114b92e034e5e81565b6102715f81565b61030a6104ae366004611771565b610790565b6102b46107a9565b6102b46104c9366004611964565b6107bb565b6102716108e7565b6102716104e4366004611771565b6108f1565b6104fc6104f73660046117ca565b610907565b60405160ff9091168152602001610241565b6104fc61051c366004611906565b61091d565b6102b461052f36600461179c565b610929565b6103af610542366004611771565b61094d565b6102b4610555366004611818565b61096f565b6102b4610568366004611818565b6109a7565b61023561057b366004611906565b610a15565b61030a610a2e565b5f61059282610a3a565b806105a157506105a182610aa5565b92915050565b5f828152600460205260409020600101546105c181610ac9565b6105cb8383610ada565b50505050565b6105d9610b0d565b6001600160a01b0316816001600160a01b03161461060a5760405163334bd91960e11b815260040160405180910390fd5b6106148282610b16565b505050565b610621610b41565b6105cb84848484610b71565b610635610c13565b61063e81610c3d565b50565b610649610c13565b61063e81610cf5565b606061065d5f610d7e565b905090565b5f6105a18183610d8a565b610675610b41565b6106805f8383610dab565b5050565b5f5f6106906002610e44565b11156106a15761065d60025f610e4d565b505f90565b5f806106b486868686610907565b60ff161490505b949350505050565b60606105a182610e58565b6106d6610b41565b610614838383610dab565b6106e9610b41565b610680825f83610dab565b5f82815260056020526040812061070b9083610e4d565b9392505050565b6001600160a01b0381165f9081527f17ef568e3e12ab5b9c7254a8d58478811de00f9e6eb34345acd53bf8fd09d3ec602052604081205460ff1615610759575060016105a1565b505f8281526004602090815260408083206001600160a01b038516845290915290205460ff166105a1565b5f6105a1600283610d8a565b5f8181526005602052604090206060906105a190610d7e565b6107b1610fa2565b6107b9610fcc565b565b6107c3610fa2565b5f8190036107e4576040516359203cb960e01b815260040160405180910390fd5b5f6107ee5f610e44565b11156107fc576107fc610fcc565b5f5b818110156106145761083583838381811061081b5761081b6119d5565b90506020020160208101906108309190611818565b610ffd565b61086683838381811061084a5761084a6119d5565b905060200201602081019061085f9190611818565b5f90611034565b6108835760405163f280d16160e01b815260040160405180910390fd5b828282818110610895576108956119d5565b90506020020160208101906108aa9190611818565b6001600160a01b03167f60305ce6c9104acd0969d358f926bf391174340660aaf5e6215261fd6847bf4660405160405180910390a26001016107fe565b5f61065d5f610e44565b5f8181526005602052604081206105a190610e44565b5f61091485858585611048565b95945050505050565b5f6106bb848484611113565b5f8281526004602052604090206001015461094381610ac9565b6105cb8383610b16565b5f6109575f610e44565b821015610968576105a15f83610e4d565b505f919050565b610977610fa2565b6109815f82610d8a565b61099e57604051632cdc3a4160e21b815260040160405180910390fd5b61063e816111d5565b6109af610fa2565b6109b881610ffd565b6109c25f82611034565b6109df5760405163f280d16160e01b815260040160405180910390fd5b6040516001600160a01b038216907f60305ce6c9104acd0969d358f926bf391174340660aaf5e6215261fd6847bf46905f90a250565b5f80610a2285858561091d565b60ff1614949350505050565b606061065d6002610d7e565b5f6001600160e01b031982166320c49ce760e01b1480610a6a57506001600160e01b031982166378a8de7d60e01b145b80610a8557506001600160e01b03198216630c51264760e21b145b806105a157506001600160e01b03198216637157797f60e01b1492915050565b5f6001600160e01b03198216635a05180f60e01b14806105a157506105a182611232565b61063e81610ad5610b0d565b611266565b5f5f610ae684846112a3565b9050801561070b575f848152600560205260409020610b059084611034565b509392505050565b5f61065d611335565b5f5f610b22848461139f565b9050801561070b575f848152600560205260409020610b059084611428565b610b54610b4c610b0d565b600290610d8a565b6107b95760405163e39b3c8f60e01b815260040160405180910390fd5b5f610b7b5f610e44565b90505f5b81811015610c0b57610b915f82610e4d565b604051631f2d7a6560e11b81526001600160a01b03888116600483015287811660248301528681166044830152606482018690529190911690633e5af4ca906084015f604051808303815f87803b158015610bea575f5ffd5b505af1158015610bfc573d5f5f3e3d5ffd5b50505050806001019050610b7f565b505050505050565b7fe5c50d0927e06141e032cb9a67e1d7092dc85c0b0825191f7e1cede60002856861063e81610ac9565b6001600160a01b038116610c64576040516301b8831760e71b815260040160405180910390fd5b610c6f600282610d8a565b15610c8d5760405163f423354760e01b815260040160405180910390fd5b610c98600282611034565b610cb557604051631b4ddcf360e11b815260040160405180910390fd5b6040516001600160a01b03821681527f2de35142b19ed5a07796cf30791959c592018f70b1d2d7c460eef8ffe713692b906020015b60405180910390a150565b610d00600282610d8a565b610d1d57604051636a2b488360e11b815260040160405180910390fd5b610d28600282611428565b610d4557604051631b4ddcf360e11b815260040160405180910390fd5b6040516001600160a01b03821681527f28a4ca7134a3b3f9aff286e79ad3daadb4a06d1b43d037a3a98bdc074edd9b7a90602001610cea565b60605f61070b8361143c565b6001600160a01b0381165f908152600183016020526040812054151561070b565b5f610db55f610e44565b90505f5b81811015610e3d57610dcb5f82610e4d565b6040516322ebca6d60e21b81526001600160a01b0387811660048301528681166024830152604482018690529190911690638baf29b4906064015f604051808303815f87803b158015610e1c575f5ffd5b505af1158015610e2e573d5f5f3e3d5ffd5b50505050806001019050610db9565b5050505050565b5f6105a1825490565b5f61070b8383611495565b60605f610e636108e7565b90505f5b81811015610f6657610e788161094d565b604051633e822efb60e11b815260ff861660048201526001600160a01b039190911690637d045df690602401602060405180830381865afa158015610ebf573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ee391906119e9565b15610f5e57610ef18161094d565b604051637f4ab1dd60e01b815260ff861660048201526001600160a01b039190911690637f4ab1dd906024015f60405180830381865afa158015610f37573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526106bb9190810190611a1c565b600101610e67565b505060408051808201909152601881527f556e6b6e6f776e207265737472696374696f6e20636f64650000000000000000602082015292915050565b7fea5f4eb72290e50c32abd6c23e45de3d8300b3286e1cbc2e293114b92e034e5e61063e81610ac9565b6040517fdbf61473843cd9be1c9791ce51ef66d0da6c9026d62ba80c1ca433b13fb729b2905f90a16107b95f6114bb565b611006816114c4565b61101781632497d6cb60e01b611513565b61063e57604051639952e34360e01b815260040160405180910390fd5b5f61070b836001600160a01b03841661152e565b5f5f6110526108e7565b90505f5b81811015611107575f6110688261094d565b60405163d32c7bb560e01b81526001600160a01b038a811660048301528981166024830152888116604483015260648201889052919091169063d32c7bb590608401602060405180830381865afa1580156110c5573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110e99190611acf565b905060ff8116156110fe5792506106bb915050565b50600101611056565b505f9695505050505050565b5f5f61111d6108e7565b90505f5b818110156111ca575f6111338261094d565b60405163d4ce141560e01b81526001600160a01b038981166004830152888116602483015260448201889052919091169063d4ce141590606401602060405180830381865afa158015611188573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111ac9190611acf565b905060ff8116156111c157925061070b915050565b50600101611121565b505f95945050505050565b6111df5f82611428565b6111fc5760405163f280d16160e01b815260040160405180910390fd5b6040516001600160a01b038216907f6d83315c9718799346b67584ec64301b1457e989c8e35a8e2982a7776c04bfc4905f90a250565b5f6001600160e01b03198216637965db0b60e01b14806105a157506301ffc9a760e01b6001600160e01b03198316146105a1565b6112708282610712565b6106805760405163e2517d3f60e01b81526001600160a01b03821660048201526024810183905260440160405180910390fd5b5f6112ae8383610712565b61132e575f8381526004602090815260408083206001600160a01b03861684529091529020805460ff191660011790556112e6610b0d565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45060016105a1565b505f6105a1565b5f36601480821080159061137157507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031633145b156113975761138436828403815f611aea565b61138d91611b11565b60601c9250505090565b339250505090565b5f6113aa8383610712565b1561132e575f8381526004602090815260408083206001600160a01b03861684529091529020805460ff191690556113e0610b0d565b6001600160a01b0316826001600160a01b0316847ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a45060016105a1565b5f61070b836001600160a01b038416611573565b6060815f0180548060200260200160405190810160405280929190818152602001828054801561148957602002820191905f5260205f20905b815481526020019060010190808311611475575b50505050509050919050565b5f825f0182815481106114aa576114aa6119d5565b905f5260205f200154905092915050565b61063e8161165d565b6001600160a01b0381166114eb5760405163f9d152fb60e01b815260040160405180910390fd5b6114f55f82610d8a565b1561063e5760405163cc790a4b60e01b815260040160405180910390fd5b5f61151d836116b6565b801561070b575061070b83836116f5565b5f81815260018301602052604081205461132e57508154600181810184555f8481526020808220909301849055845484825282860190935260409020919091556105a1565b5f818152600183016020526040812054801561164d575f611595600183611b51565b85549091505f906115a890600190611b51565b9050808214611607575f865f0182815481106115c6576115c66119d5565b905f5260205f200154905080875f0184815481106115e6576115e66119d5565b5f918252602080832090910192909255918252600188019052604090208390555b855486908061161857611618611b70565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f9055600193505050506105a1565b5f9150506105a1565b5092915050565b5f611666825490565b90505f5b818110156116af57826001015f845f01838154811061168b5761168b6119d5565b905f5260205f20015481526020019081526020015f205f905580600101905061166a565b50505f9055565b5f6116c8826301ffc9a760e01b6116f5565b15610968575f806116e1846001600160e01b0319611716565b915091508180156106bb5750159392505050565b5f5f5f6117028585611716565b915091508180156109145750949350505050565b6301ffc9a760e01b5f818152600483905290819060208260248188617530fa92505f511515601f3d11169150509250929050565b5f6020828403121561175a575f5ffd5b81356001600160e01b03198116811461070b575f5ffd5b5f60208284031215611781575f5ffd5b5035919050565b6001600160a01b038116811461063e575f5ffd5b5f5f604083850312156117ad575f5ffd5b8235915060208301356117bf81611788565b809150509250929050565b5f5f5f5f608085870312156117dd575f5ffd5b84356117e881611788565b935060208501356117f881611788565b9250604085013561180881611788565b9396929550929360600135925050565b5f60208284031215611828575f5ffd5b813561070b81611788565b602080825282518282018190525f918401906040840190835b818110156118735783516001600160a01b031683526020938401939092019160010161184c565b509095945050505050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b5f5f604083850312156118c4575f5ffd5b82356118cf81611788565b946020939093013593505050565b60ff8116811461063e575f5ffd5b5f602082840312156118fb575f5ffd5b813561070b816118dd565b5f5f5f60608486031215611918575f5ffd5b833561192381611788565b9250602084013561193381611788565b929592945050506040919091013590565b5f5f60408385031215611955575f5ffd5b50508035926020909101359150565b5f5f60208385031215611975575f5ffd5b823567ffffffffffffffff81111561198b575f5ffd5b8301601f8101851361199b575f5ffd5b803567ffffffffffffffff8111156119b1575f5ffd5b8560208260051b84010111156119c5575f5ffd5b6020919091019590945092505050565b634e487b7160e01b5f52603260045260245ffd5b5f602082840312156119f9575f5ffd5b8151801515811461070b575f5ffd5b634e487b7160e01b5f52604160045260245ffd5b5f60208284031215611a2c575f5ffd5b815167ffffffffffffffff811115611a42575f5ffd5b8201601f81018413611a52575f5ffd5b805167ffffffffffffffff811115611a6c57611a6c611a08565b604051601f8201601f19908116603f0116810167ffffffffffffffff81118282101715611a9b57611a9b611a08565b604052818152828201602001861015611ab2575f5ffd5b8160208401602083015e5f91810160200191909152949350505050565b5f60208284031215611adf575f5ffd5b815161070b816118dd565b5f5f85851115611af8575f5ffd5b83861115611b04575f5ffd5b5050820193919092039150565b80356bffffffffffffffffffffffff198116906014841015611656576bffffffffffffffffffffffff1960149490940360031b84901b1690921692915050565b818103818111156105a157634e487b7160e01b5f52601160045260245ffd5b634e487b7160e01b5f52603160045260245ffdfea2646970667358221220b03f8c635c82b542156a657e05e1b25daf4da0550801960bc81efa2b41c0ae9d64736f6c63430008220033","sourceMap":"787:2684:163:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2029:296;;;;;;:::i;:::-;;:::i;:::-;;;470:14:231;;463:22;445:41;;433:2;418:18;2029:296:163;;;;;;;;729:86:186;;779:36;729:86;;;;;643:25:231;;;631:2;616:18;729:86:186;497:177:231;3776:120:126;;;;;;:::i;:::-;3841:7;3867:12;;;:6;:12;;;;;:22;;;;3776:120;4192:136;;;;;;:::i;:::-;;:::i;:::-;;5294:245;;;;;;:::i;:::-;;:::i;1726:276:161:-;;;;;;:::i;:::-;;:::i;1846:114:186:-;;;;;;:::i;:::-;;:::i;2223:118::-;;;;;;:::i;:::-;;:::i;4499:136:187:-;;;:::i;:::-;;;;;;;:::i;3804:158::-;;;;;;:::i;:::-;;:::i;692:129:188:-;807:7;;;;;;;;;;;;-1:-1:-1;;;807:7:188;;;;692:129;;;;;;;:::i;1874:137:135:-;;;;;;:::i;:::-;1749:17;-1:-1:-1;;;;;1973:31:135;;;;;;;1874:137;2328:155:161;;;;;;:::i;:::-;;:::i;2564:382:186:-;;;:::i;:::-;;;-1:-1:-1;;;;;4193:32:231;;;4175:51;;4163:2;4148:18;2564:382:186;4029:203:231;4340:311:161;;;;;;:::i;:::-;;:::i;1666:107:135:-;1749:17;1666:107;;3695:240:161;;;;;;:::i;:::-;;:::i;2071:212::-;;;;;;:::i;:::-;;:::i;2528:161::-;;;;;;:::i;:::-;;:::i;1555:142:130:-;;;;;;:::i;:::-;;:::i;1630:349:163:-;;;;;;:::i;:::-;;:::i;2386:133:186:-;;;;;;:::i;:::-;;:::i;1199:82:192:-;;1247:34;1199:82;;2187:49:126;;2232:4;2187:49;;2539:136:130;;;;;;:::i;:::-;;:::i;2485:117:187:-;;;:::i;1781:640::-;;;;;;:::i;:::-;;:::i;3608:132::-;;;:::i;1865:131:130:-;;;;;;:::i;:::-;;:::i;3363:282:161:-;;;;;;:::i;:::-;;:::i;:::-;;;6452:4:231;6440:17;;;6422:36;;6410:2;6395:18;3363:282:161;6280:184:231;3065:242:161;;;;;;:::i;:::-;;:::i;4608:138:126:-;;;;;;:::i;:::-;;:::i;4026:409:187:-;;;;;;:::i;:::-;;:::i;3258:234::-;;;;;;:::i;:::-;;:::i;2923:271::-;;;;;;:::i;:::-;;:::i;3999:281:161:-;;;;;;:::i;:::-;;:::i;2991:119:186:-;;;:::i;2029:296:163:-;2188:4;2215:45;2248:11;2215:32;:45::i;:::-;:103;;;;2264:54;2306:11;2264:41;:54::i;:::-;2208:110;2029:296;-1:-1:-1;;2029:296:163:o;4192:136:126:-;3841:7;3867:12;;;:6;:12;;;;;:22;;;2464:16;2475:4;2464:10;:16::i;:::-;4296:25:::1;4307:4;4313:7;4296:10;:25::i;:::-;;4192:136:::0;;;:::o;5294:245::-;5409:12;:10;:12::i;:::-;-1:-1:-1;;;;;5387:34:126;:18;-1:-1:-1;;;;;5387:34:126;;5383:102;;5444:30;;-1:-1:-1;;;5444:30:126;;;;;;;;;;;5383:102;5495:37;5507:4;5513:18;5495:11;:37::i;:::-;;5294:245;;:::o;1726:276:161:-;1217:18:186;:16;:18::i;:::-;1935:60:161::1;1970:7;1979:4;1985:2;1989:5;1935:34;:60::i;1846:114:186:-:0;1302:24;:22;:24::i;:::-;1936:17:::1;1947:5;1936:10;:17::i;:::-;1846:114:::0;:::o;2223:118::-;1302:24;:22;:24::i;:::-;2315:19:::1;2328:5;2315:12;:19::i;4499:136:187:-:0;4578:16;4613:15;:6;:13;:15::i;:::-;4606:22;;4499:136;:::o;3804:158::-;3901:4;3924:31;3901:4;3948:5;3924:15;:31::i;2328:155:161:-;1217:18:186;:16;:18::i;:::-;2441:35:161::1;2462:1;2466:2;2470:5;2441:12;:35::i;:::-;2328:155:::0;;:::o;2564:382:186:-;2627:7;2674:1;2650:21;:12;:19;:21::i;:::-;:25;2646:294;;;2863:18;:12;2879:1;2863:15;:18::i;2646:294::-;-1:-1:-1;2927:1:186;;2564:382::o;4340:311:161:-;4521:4;;4548:55;4578:7;4587:4;4593:2;4597:5;4548:29;:55::i;:::-;:96;;;4541:103;;4340:311;;;;;;;:::o;3695:240::-;3845:13;3881:47;3912:15;3881:30;:47::i;2071:212::-;1217:18:186;:16;:18::i;:::-;2247:29:161::1;2260:4;2266:2;2270:5;2247:12;:29::i;2528:161::-:0;1217:18:186;:16;:18::i;:::-;2645:37:161::1;2658:4;2672:1;2676:5;2645:12;:37::i;1555:142:130:-:0;1636:7;1662:18;;;:12;:18;;;;;:28;;1684:5;1662:21;:28::i;:::-;1655:35;1555:142;-1:-1:-1;;;1555:142:130:o;1630:349:163:-;-1:-1:-1;;;;;2920:29:126;;1787:4:163;2920:29:126;;;:12;;:29;:12;:29;;;;;1807:166:163;;;-1:-1:-1;1884:4:163;1877:11;;1807:166;-1:-1:-1;2897:4:126;2920:12;;;:6;:12;;;;;;;;-1:-1:-1;;;;;2920:29:126;;;;;;;;;;;;1919:43:163;;2386:133:186;2461:4;2484:28;:12;2506:5;2484:21;:28::i;2539:136:130:-;2641:18;;;;:12;:18;;;;;2606:16;;2641:27;;:25;:27::i;2485:117:187:-;643:19;:17;:19::i;:::-;2582:13:::1;:11;:13::i;:::-;2485:117::o:0;1781:640::-;643:19;:17;:19::i;:::-;1920:1:::1;1903:18:::0;;;1899:103:::1;;1944:47;;-1:-1:-1::0;;;1944:47:187::1;;;;;;;;;;;1899:103;2033:1;2015:15;:6;:13;:15::i;:::-;:19;2011:63;;;2050:13;:11;:13::i;:::-;2088:9;2083:332;2103:17:::0;;::::1;2083:332;;;2141:30;2160:6;;2167:1;2160:9;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;2141:10;:30::i;:::-;2277;2296:6;;2303:1;2296:9;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;2277:6;::::0;:10:::1;:30::i;:::-;2269:98;;;;-1:-1:-1::0;;;2269:98:187::1;;;;;;;;;;;;2394:6;;2401:1;2394:9;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;2386:18:187::1;;;;;;;;;;;2122:3;;2083:332;;3608:132:::0;3692:7;3718:15;:6;:13;:15::i;1865:131:130:-;1936:7;1962:18;;;:12;:18;;;;;:27;;:25;:27::i;3363:282:161:-;3554:5;3582:56;3613:7;3622:4;3628:2;3632:5;3582:30;:56::i;:::-;3575:63;3363:282;-1:-1:-1;;;;;3363:282:161:o;3065:242::-;3229:5;3257:43;3284:4;3290:2;3294:5;3257:26;:43::i;4608:138:126:-;3841:7;3867:12;;;:6;:12;;;;;:22;;;2464:16;2475:4;2464:10;:16::i;:::-;4713:26:::1;4725:4;4731:7;4713:11;:26::i;4026:409:187:-:0;4118:7;4150:15;:6;:13;:15::i;:::-;4141:6;:24;4137:292;;;4353:17;:6;4363;4353:9;:17::i;4137:292::-;-1:-1:-1;4416:1:187;;4026:409;-1:-1:-1;4026:409:187:o;3258:234::-;643:19;:17;:19::i;:::-;3374:31:::1;:6;3398:5:::0;3374:15:::1;:31::i;:::-;3366:91;;;;-1:-1:-1::0;;;3366:91:187::1;;;;;;;;;;;;3467:18;3479:5;3467:11;:18::i;2923:271::-:0;643:19;:17;:19::i;:::-;3028:26:::1;3047:5;3028:10;:26::i;:::-;3072;:6;3091:5:::0;3072:10:::1;:26::i;:::-;3064:94;;;;-1:-1:-1::0;;;3064:94:187::1;;;;;;;;;;;;3173:14;::::0;-1:-1:-1;;;;;3173:14:187;::::1;::::0;::::1;::::0;;;::::1;2923:271:::0;:::o;3999:281:161:-;4163:4;;4190:42;4216:4;4222:2;4226:5;4190:25;:42::i;:::-;:83;;;;3999:281;-1:-1:-1;;;;3999:281:161:o;2991:119:186:-;3047:16;3082:21;:12;:19;:21::i;7167:427:161:-;7252:4;-1:-1:-1;;;;;;7275:61:161;;-1:-1:-1;;;7275:61:161;;:143;;-1:-1:-1;;;;;;;7352:66:161;;-1:-1:-1;;;7352:66:161;7275:143;:227;;;-1:-1:-1;;;;;;;7434:68:161;;-1:-1:-1;;;7434:68:161;7275:227;:312;;;-1:-1:-1;;;;;;;7518:69:161;;-1:-1:-1;;;7518:69:161;7268:319;7167:427;-1:-1:-1;;7167:427:161:o;758:212:130:-;843:4;-1:-1:-1;;;;;;866:57:130;;-1:-1:-1;;;866:57:130;;:97;;;927:36;951:11;927:23;:36::i;3165:103:126:-;3231:30;3242:4;3248:12;:10;:12::i;:::-;3231:10;:30::i;2777:257:130:-;2863:4;2879:12;2894:31;2911:4;2917:7;2894:16;:31::i;:::-;2879:46;;2939:7;2935:69;;;2962:18;;;;:12;:18;;;;;:31;;2985:7;2962:22;:31::i;:::-;;3020:7;2777:257;-1:-1:-1;;;2777:257:130:o;2796:154:163:-;2883:14;2916:27;:25;:27::i;3137:262:130:-;3224:4;3240:12;3255:32;3273:4;3279:7;3255:17;:32::i;:::-;3240:47;;3301:7;3297:72;;;3324:18;;;;:12;:18;;;;;:34;;3350:7;3324:25;:34::i;4153:188:186:-;4217:35;4239:12;:10;:12::i;:::-;4217;;:21;:35::i;:::-;4212:123;;4275:49;;-1:-1:-1;;;4275:49:186;;;;;;;;;;;7278:284:187;7385:19;7407:15;:6;:13;:15::i;:::-;7385:37;-1:-1:-1;7437:9:187;7432:124;7456:11;7452:1;:15;7432:124;;;7494:12;:6;7504:1;7494:9;:12::i;:::-;7488:57;;-1:-1:-1;;;7488:57:187;;-1:-1:-1;;;;;7213:32:231;;;7488:57:187;;;7195:51:231;7282:32;;;7262:18;;;7255:60;7351:32;;;7331:18;;;7324:60;7400:18;;;7393:34;;;7488:31:187;;;;;;;7167:19:231;;7488:57:187;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7469:3;;;;;7432:124;;;;7375:187;7278:284;;;;:::o;2505:96:163:-;779:36:186;2464:16:126;2475:4;2464:10;:16::i;3688:459:186:-;-1:-1:-1;;;;;3750:19:186;;3742:80;;;;-1:-1:-1;;;3742:80:186;;;;;;;;;;;;3841:28;:12;3863:5;3841:21;:28::i;:::-;3840:29;3832:88;;;;-1:-1:-1;;;3832:88:186;;;;;;;;;;;;4029:23;:12;4046:5;4029:16;:23::i;:::-;4021:87;;;;-1:-1:-1;;;4021:87:186;;;;;;;;;;;;4123:17;;-1:-1:-1;;;;;4193:32:231;;4175:51;;4123:17:186;;4163:2:231;4148:18;4123:17:186;;;;;;;;3688:459;:::o;3310:372::-;3374:28;:12;3396:5;3374:21;:28::i;:::-;3366:83;;;;-1:-1:-1;;;3366:83:186;;;;;;;;;;;;3558:26;:12;3578:5;3558:19;:26::i;:::-;3550:90;;;;-1:-1:-1;;;3550:90:186;;;;;;;;;;;;3656:19;;-1:-1:-1;;;;;4193:32:231;;4175:51;;3656:19:186;;4163:2:231;4148:18;3656:19:186;4029:203:231;17440:273:158;17503:16;17531:22;17556:19;17564:3;17556:7;:19::i;16041:165::-;-1:-1:-1;;;;;16174:23:158;;16121:4;5238:21;;;:14;;;:21;;;;;;:26;;16144:55;5142:129;6464:258:187;6554:19;6576:15;:6;:13;:15::i;:::-;6554:37;-1:-1:-1;6606:9:187;6601:115;6625:11;6621:1;:15;6601:115;;;6663:12;:6;6673:1;6663:9;:12::i;:::-;6657:48;;-1:-1:-1;;;6657:48:187;;-1:-1:-1;;;;;7658:32:231;;;6657:48:187;;;7640:51:231;7727:32;;;7707:18;;;7700:60;7776:18;;;7769:34;;;6657:31:187;;;;;;;7613:18:231;;6657:48:187;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6638:3;;;;;6601:115;;;;6544:178;6464:258;;;:::o;16287:115:158:-;16350:7;16376:19;16384:3;5434:18;;5352:107;16744:156;16818:7;16868:22;16872:3;16884:5;16868:3;:22::i;6166:449:161:-;6260:13;6285:19;6307:12;:10;:12::i;:::-;6285:34;-1:-1:-1;6334:9:161;6329:237;6353:11;6349:1;:15;6329:237;;;6395:7;6400:1;6395:4;:7::i;:::-;6389:64;;-1:-1:-1;;;6389:64:161;;6452:4:231;6440:17;;6389:64:161;;;6422:36:231;-1:-1:-1;;;;;6389:47:161;;;;;;;6395:18:231;;6389:64:161;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;6385:171;;;6486:7;6491:1;6486:4;:7::i;:::-;6480:61;;-1:-1:-1;;;6480:61:161;;6452:4:231;6440:17;;6480:61:161;;;6422:36:231;-1:-1:-1;;;;;6480:44:161;;;;;;;6395:18:231;;6480:61:161;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;6480:61:161;;;;;;;;;;;;:::i;6385:171::-;6366:3;;6329:237;;;-1:-1:-1;;6575:33:161;;;;;;;;;;;;;;;;;;6166:449;-1:-1:-1;;6166:449:161:o;2606:89:163:-;1247:34:192;2464:16:126;2475:4;2464:10;:16::i;4914:98:187:-;4969:12;;;;;;;4991:14;:6;:12;:14::i;6719:261:161:-;6795:23;6812:5;6795:16;:23::i;:::-;6833:74;6865:5;-1:-1:-1;;;6833:31:161;:74::i;:::-;6828:146;;6930:33;;-1:-1:-1;;;6930:33:161;;;;;;;;;;;15089:150:158;15159:4;15182:50;15187:3;-1:-1:-1;;;;;15207:23:158;;15182:4;:50::i;5314:528:161:-;5475:5;5496:19;5518:12;:10;:12::i;:::-;5496:34;-1:-1:-1;5545:9:161;5540:242;5564:11;5560:1;:15;5540:242;;;5596:17;5622:7;5627:1;5622:4;:7::i;:::-;5616:70;;-1:-1:-1;;;5616:70:161;;-1:-1:-1;;;;;7213:32:231;;;5616:70:161;;;7195:51:231;7282:32;;;7262:18;;;7255:60;7351:32;;;7331:18;;;7324:60;7400:18;;;7393:34;;;5616:44:161;;;;;;;7167:19:231;;5616:70:161;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;5596:90;-1:-1:-1;5704:15:161;;;;5700:72;;5746:11;-1:-1:-1;5739:18:161;;-1:-1:-1;;5739:18:161;5700:72;-1:-1:-1;5577:3:161;;5540:242;;;-1:-1:-1;5804:30:161;5791:44;5314:528;-1:-1:-1;;;;;;5314:528:161:o;4850:458::-;4958:5;4975:19;4997:12;:10;:12::i;:::-;4975:34;-1:-1:-1;5024:9:161;5019:229;5043:11;5039:1;:15;5019:229;;;5075:17;5101:7;5106:1;5101:4;:7::i;:::-;5095:57;;-1:-1:-1;;;5095:57:161;;-1:-1:-1;;;;;7658:32:231;;;5095:57:161;;;7640:51:231;7727:32;;;7707:18;;;7700:60;7776:18;;;7769:34;;;5095:40:161;;;;;;;7613:18:231;;5095:57:161;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;5075:77;-1:-1:-1;5170:15:161;;;;5166:72;;5212:11;-1:-1:-1;5205:18:161;;-1:-1:-1;;5205:18:161;5166:72;-1:-1:-1;5056:3:161;;5019:229;;;-1:-1:-1;5270:30:161;5257:44;4850:458;-1:-1:-1;;;;;4850:458:161:o;5239:277:187:-;5388:29;:6;5410:5;5388:13;:29::i;:::-;5380:97;;;;-1:-1:-1;;;5380:97:187;;;;;;;;;;;;5492:17;;-1:-1:-1;;;;;5492:17:187;;;;;;;;5239:277;:::o;2531:202:126:-;2616:4;-1:-1:-1;;;;;;2639:47:126;;-1:-1:-1;;;2639:47:126;;:87;;-1:-1:-1;;;;;;;;;;829:40:152;;;2690:36:126;730:146:152;3398:197:126;3486:22;3494:4;3500:7;3486;:22::i;:::-;3481:108;;3531:47;;-1:-1:-1;;;3531:47:126;;-1:-1:-1;;;;;9612:32:231;;3531:47:126;;;9594:51:231;9661:18;;;9654:34;;;9567:18;;3531:47:126;;;;;;;6145:316;6222:4;6243:22;6251:4;6257:7;6243;:22::i;:::-;6238:217;;6281:12;;;;:6;:12;;;;;;;;-1:-1:-1;;;;;6281:29:126;;;;;;;;;:36;;-1:-1:-1;;6281:36:126;6313:4;6281:36;;;6363:12;:10;:12::i;:::-;-1:-1:-1;;;;;6336:40:126;6354:7;-1:-1:-1;;;;;6336:40:126;6348:4;6336:40;;;;;;;;;;-1:-1:-1;6397:4:126;6390:11;;6238:217;-1:-1:-1;6439:5:126;6432:12;;2248:471:135;2310:7;2354:8;3609:2;2445:37;;;;;;:71;;-1:-1:-1;1749:17:135;-1:-1:-1;;;;;1973:31:135;2505:10;1973:31;2486:30;2441:272;;;2583:47;:8;2592:36;;;2583:8;;:47;:::i;:::-;2575:56;;;:::i;:::-;2567:65;;2560:72;;;;2248:471;:::o;2441:272::-;735:10:143;2677:25:135;;;;2248:471;:::o;6698:317:126:-;6776:4;6796:22;6804:4;6810:7;6796;:22::i;:::-;6792:217;;;6866:5;6834:12;;;:6;:12;;;;;;;;-1:-1:-1;;;;;6834:29:126;;;;;;;;;:37;;-1:-1:-1;;6834:37:126;;;6917:12;:10;:12::i;:::-;-1:-1:-1;;;;;6890:40:126;6908:7;-1:-1:-1;;;;;6890:40:126;6902:4;6890:40;;;;;;;;;;-1:-1:-1;6951:4:126;6944:11;;15407:156:158;15480:4;15503:53;15511:3;-1:-1:-1;;;;;15531:23:158;;15503:7;:53::i;6459:109::-;6515:16;6550:3;:11;;6543:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6459:109;;;:::o;5801:118::-;5868:7;5894:3;:11;;5906:5;5894:18;;;;;;;;:::i;:::-;;;;;;;;;5887:25;;5801:118;;;;:::o;15877:83::-;15935:18;15942:3;15935:6;:18::i;5593:313:187:-;-1:-1:-1;;;;;5664:21:187;;5660:119;;5708:60;;-1:-1:-1;;;5708:60:187;;;;;;;;;;;5660:119;5792:22;:6;5808:5;5792:15;:22::i;:::-;5788:112;;;5837:52;;-1:-1:-1;;;5837:52:187;;;;;;;;;;;1465:283:153;1552:4;1660:23;1675:7;1660:14;:23::i;:::-;:81;;;;;1687:54;1720:7;1729:11;1687:32;:54::i;2538:406:158:-;2601:4;5238:21;;;:14;;;:21;;;;;;2617:321;;-1:-1:-1;2659:23:158;;;;;;;;:11;:23;;;;;;;;;;;;;2841:18;;2817:21;;;:14;;;:21;;;;;;:42;;;;2873:11;;3112:1368;3178:4;3307:21;;;:14;;;:21;;;;;;3343:13;;3339:1135;;3710:18;3731:12;3742:1;3731:8;:12;:::i;:::-;3777:18;;3710:33;;-1:-1:-1;3757:17:158;;3777:22;;3798:1;;3777:22;:::i;:::-;3757:42;;3832:9;3818:10;:23;3814:378;;3861:17;3881:3;:11;;3893:9;3881:22;;;;;;;;:::i;:::-;;;;;;;;;3861:42;;4028:9;4002:3;:11;;4014:10;4002:23;;;;;;;;:::i;:::-;;;;;;;;;;;;:35;;;;4141:25;;;:14;;;:25;;;;;:36;;;3814:378;4270:17;;:3;;:17;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;4373:3;:14;;:21;4388:5;4373:21;;;;;;;;;;;4366:28;;;4416:4;4409:11;;;;;;;3339:1135;4458:5;4451:12;;;;;3339:1135;3184:1296;3112:1368;;;;:::o;4824:237::-;4875:11;4889:12;4897:3;5434:18;;5352:107;4889:12;4875:26;-1:-1:-1;4916:9:158;4911:96;4935:3;4931:1;:7;4911:96;;;4966:3;:14;;:30;4981:3;:11;;4993:1;4981:14;;;;;;;;:::i;:::-;;;;;;;;;4966:30;;;;;;;;;;;4959:37;;;4940:3;;;;;4911:96;;;-1:-1:-1;;5039:11:158;33920:23:140;;2328:155:161:o;719:528:153:-;783:4;976:68;1009:7;-1:-1:-1;;;976:32:153;:68::i;:::-;972:269;;;1061:12;;1093:52;1115:7;-1:-1:-1;;;;;;1093:21:153;:52::i;:::-;1060:85;;;;1166:7;:21;;;;-1:-1:-1;1177:10:153;;1159:28;-1:-1:-1;;;719:528:153:o;4504:238::-;4606:4;4623:12;4637:14;4655:43;4677:7;4686:11;4655:21;:43::i;:::-;4622:76;;;;4715:7;:20;;;;-1:-1:-1;4726:9:153;4708:27;-1:-1:-1;;;;4504:238:153:o;5198:628::-;-1:-1:-1;;;5310:12:153;5452:22;;;5494:4;5487:25;;;5310:12;;;5581:4;5310:12;5569:4;5310:12;5554:7;5547:5;5536:50;5525:61;;5740:4;5734:11;5727:19;5720:27;5654:4;5636:16;5633:26;5612:198;5599:211;;5438:382;5198:628;;;;;:::o;14:286:231:-;72:6;125:2;113:9;104:7;100:23;96:32;93:52;;;141:1;138;131:12;93:52;167:23;;-1:-1:-1;;;;;;219:32:231;;209:43;;199:71;;266:1;263;256:12;679:226;738:6;791:2;779:9;770:7;766:23;762:32;759:52;;;807:1;804;797:12;759:52;-1:-1:-1;852:23:231;;679:226;-1:-1:-1;679:226:231:o;910:131::-;-1:-1:-1;;;;;985:31:231;;975:42;;965:70;;1031:1;1028;1021:12;1046:367;1114:6;1122;1175:2;1163:9;1154:7;1150:23;1146:32;1143:52;;;1191:1;1188;1181:12;1143:52;1236:23;;;-1:-1:-1;1335:2:231;1320:18;;1307:32;1348:33;1307:32;1348:33;:::i;:::-;1400:7;1390:17;;;1046:367;;;;;:::o;1418:650::-;1504:6;1512;1520;1528;1581:3;1569:9;1560:7;1556:23;1552:33;1549:53;;;1598:1;1595;1588:12;1549:53;1637:9;1624:23;1656:31;1681:5;1656:31;:::i;:::-;1706:5;-1:-1:-1;1763:2:231;1748:18;;1735:32;1776:33;1735:32;1776:33;:::i;:::-;1828:7;-1:-1:-1;1887:2:231;1872:18;;1859:32;1900:33;1859:32;1900:33;:::i;:::-;1418:650;;;;-1:-1:-1;1952:7:231;;2032:2;2017:18;2004:32;;-1:-1:-1;;1418:650:231:o;2073:247::-;2132:6;2185:2;2173:9;2164:7;2160:23;2156:32;2153:52;;;2201:1;2198;2191:12;2153:52;2240:9;2227:23;2259:31;2284:5;2259:31;:::i;2325:637::-;2515:2;2527:21;;;2597:13;;2500:18;;;2619:22;;;2467:4;;2698:15;;;2672:2;2657:18;;;2467:4;2741:195;2755:6;2752:1;2749:13;2741:195;;;2820:13;;-1:-1:-1;;;;;2816:39:231;2804:52;;2885:2;2911:15;;;;2876:12;;;;2852:1;2770:9;2741:195;;;-1:-1:-1;2953:3:231;;2325:637;-1:-1:-1;;;;;2325:637:231:o;3234:418::-;3383:2;3372:9;3365:21;3346:4;3415:6;3409:13;3458:6;3453:2;3442:9;3438:18;3431:34;3517:6;3512:2;3504:6;3500:15;3495:2;3484:9;3480:18;3474:50;3573:1;3568:2;3559:6;3548:9;3544:22;3540:31;3533:42;3643:2;3636;3632:7;3627:2;3619:6;3615:15;3611:29;3600:9;3596:45;3592:54;3584:62;;;3234:418;;;;:::o;3657:367::-;3725:6;3733;3786:2;3774:9;3765:7;3761:23;3757:32;3754:52;;;3802:1;3799;3792:12;3754:52;3841:9;3828:23;3860:31;3885:5;3860:31;:::i;:::-;3910:5;3988:2;3973:18;;;;3960:32;;-1:-1:-1;;;3657:367:231:o;4237:114::-;4321:4;4314:5;4310:16;4303:5;4300:27;4290:55;;4341:1;4338;4331:12;4356:243;4413:6;4466:2;4454:9;4445:7;4441:23;4437:32;4434:52;;;4482:1;4479;4472:12;4434:52;4521:9;4508:23;4540:29;4563:5;4540:29;:::i;4604:508::-;4681:6;4689;4697;4750:2;4738:9;4729:7;4725:23;4721:32;4718:52;;;4766:1;4763;4756:12;4718:52;4805:9;4792:23;4824:31;4849:5;4824:31;:::i;:::-;4874:5;-1:-1:-1;4931:2:231;4916:18;;4903:32;4944:33;4903:32;4944:33;:::i;:::-;4604:508;;4996:7;;-1:-1:-1;;;5076:2:231;5061:18;;;;5048:32;;4604:508::o;5117:346::-;5185:6;5193;5246:2;5234:9;5225:7;5221:23;5217:32;5214:52;;;5262:1;5259;5252:12;5214:52;-1:-1:-1;;5307:23:231;;;5427:2;5412:18;;;5399:32;;-1:-1:-1;5117:346:231:o;5468:625::-;5569:6;5577;5630:2;5618:9;5609:7;5605:23;5601:32;5598:52;;;5646:1;5643;5636:12;5598:52;5686:9;5673:23;5719:18;5711:6;5708:30;5705:50;;;5751:1;5748;5741:12;5705:50;5774:22;;5827:4;5819:13;;5815:27;-1:-1:-1;5805:55:231;;5856:1;5853;5846:12;5805:55;5896:2;5883:16;5922:18;5914:6;5911:30;5908:50;;;5954:1;5951;5944:12;5908:50;6007:7;6002:2;5992:6;5989:1;5985:14;5981:2;5977:23;5973:32;5970:45;5967:65;;;6028:1;6025;6018:12;5967:65;6059:2;6051:11;;;;;6081:6;;-1:-1:-1;5468:625:231;-1:-1:-1;;;5468:625:231:o;6832:127::-;6893:10;6888:3;6884:20;6881:1;6874:31;6924:4;6921:1;6914:15;6948:4;6945:1;6938:15;7814:277;7881:6;7934:2;7922:9;7913:7;7909:23;7905:32;7902:52;;;7950:1;7947;7940:12;7902:52;7982:9;7976:16;8035:5;8028:13;8021:21;8014:5;8011:32;8001:60;;8057:1;8054;8047:12;8096:127;8157:10;8152:3;8148:20;8145:1;8138:31;8188:4;8185:1;8178:15;8212:4;8209:1;8202:15;8228:935;8308:6;8361:2;8349:9;8340:7;8336:23;8332:32;8329:52;;;8377:1;8374;8367:12;8329:52;8410:9;8404:16;8443:18;8435:6;8432:30;8429:50;;;8475:1;8472;8465:12;8429:50;8498:22;;8551:4;8543:13;;8539:27;-1:-1:-1;8529:55:231;;8580:1;8577;8570:12;8529:55;8613:2;8607:9;8639:18;8631:6;8628:30;8625:56;;;8661:18;;:::i;:::-;8710:2;8704:9;8802:2;8764:17;;-1:-1:-1;;8760:31:231;;;8793:2;8756:40;8752:54;8740:67;;8837:18;8822:34;;8858:22;;;8819:62;8816:88;;;8884:18;;:::i;:::-;8920:2;8913:22;8944;;;8985:15;;;9002:2;8981:24;8978:37;-1:-1:-1;8975:57:231;;;9028:1;9025;9018:12;8975:57;9077:6;9072:2;9068;9064:11;9059:2;9051:6;9047:15;9041:43;9130:1;9104:19;;;9125:2;9100:28;9093:39;;;;9108:6;8228:935;-1:-1:-1;;;;8228:935:231:o;9168:247::-;9236:6;9289:2;9277:9;9268:7;9264:23;9260:32;9257:52;;;9305:1;9302;9295:12;9257:52;9337:9;9331:16;9356:29;9379:5;9356:29;:::i;9699:331::-;9804:9;9815;9857:8;9845:10;9842:24;9839:44;;;9879:1;9876;9869:12;9839:44;9908:6;9898:8;9895:20;9892:40;;;9928:1;9925;9918:12;9892:40;-1:-1:-1;;9954:23:231;;;9999:25;;;;;-1:-1:-1;9699:331:231:o;10035:374::-;10156:19;;-1:-1:-1;;10193:40:231;;;10253:2;10245:11;;10242:161;;;-1:-1:-1;;10315:2:231;10311:12;;;;10308:1;10304:20;10300:58;;;10292:67;10288:105;;;;10035:374;-1:-1:-1;;10035:374:231:o;10414:225::-;10481:9;;;10502:11;;;10499:134;;;10555:10;10550:3;10546:20;10543:1;10536:31;10590:4;10587:1;10580:15;10618:4;10615:1;10608:15;10644:127;10705:10;10700:3;10696:20;10693:1;10686:31;10736:4;10733:1;10726:15;10760:4;10757:1;10750:15","linkReferences":{},"immutableReferences":{"55852":[{"start":868,"length":32},{"start":988,"length":32},{"start":4934,"length":32}]}},"methodIdentifiers":{"COMPLIANCE_MANAGER_ROLE()":"03c26bcd","DEFAULT_ADMIN_ROLE()":"a217fddf","RULES_MANAGEMENT_ROLE()":"9b11c115","addRule(address)":"e3c4602c","bindToken(address)":"3ff5aa02","canTransfer(address,address,uint256)":"e46638e6","canTransferFrom(address,address,address,uint256)":"7157797f","clearRules()":"b043572e","containsRule(address)":"54e4b945","created(address,uint256)":"5f8dead3","destroyed(address,uint256)":"8d2ea772","detectTransferRestriction(address,address,uint256)":"d4ce1415","detectTransferRestrictionFrom(address,address,address,uint256)":"d32c7bb5","getRoleAdmin(bytes32)":"248a9ca3","getRoleMember(bytes32,uint256)":"9010d07c","getRoleMemberCount(bytes32)":"ca15c873","getRoleMembers(bytes32)":"a3246ad3","getTokenBound()":"6a3edf28","getTokenBounds()":"e54621d2","grantRole(bytes32,address)":"2f2ff15d","hasRole(bytes32,address)":"91d14854","isTokenBound(address)":"993e8b95","isTrustedForwarder(address)":"572b6c05","messageForTransferRestriction(uint8)":"7f4ab1dd","removeRule(address)":"df21950f","renounceRole(bytes32,address)":"36568abe","revokeRole(bytes32,address)":"d547741f","rule(uint256)":"db18af6c","rules()":"52f6747a","rulesCount()":"bc13eacc","setRules(address[])":"b27aef3a","supportsInterface(bytes4)":"01ffc9a7","transferred(address,address,address,uint256)":"3e5af4ca","transferred(address,address,uint256)":"8baf29b4","trustedForwarder()":"7da0a877","unbindToken(address)":"40db3b50","version()":"54fd4d50"},"rawMetadata":"{\"compiler\":{\"version\":\"0.8.34+commit.80d5c536\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"forwarderIrrevocable\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenContract\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"AccessControlBadConfirmation\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"neededRole\",\"type\":\"bytes32\"}],\"name\":\"AccessControlUnauthorizedAccount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_AdminWithAddressZeroNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_ERC3643Compliance_InvalidTokenAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_ERC3643Compliance_OperationNotSuccessful\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_ERC3643Compliance_TokenAlreadyBound\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_ERC3643Compliance_TokenNotBound\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_ERC3643Compliance_UnauthorizedCaller\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_RuleInvalidInterface\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_RulesManagementModule_ArrayIsEmpty\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_RulesManagementModule_OperationNotSuccessful\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_RulesManagementModule_RuleAddressZeroNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_RulesManagementModule_RuleAlreadyExists\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_RulesManagementModule_RuleDoNotMatch\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract IRule\",\"name\":\"rule\",\"type\":\"address\"}],\"name\":\"AddRule\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"ClearRules\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract IRule\",\"name\":\"rule\",\"type\":\"address\"}],\"name\":\"RemoveRule\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"previousAdminRole\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"newAdminRole\",\"type\":\"bytes32\"}],\"name\":\"RoleAdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleRevoked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"TokenBound\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"TokenUnbound\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"COMPLIANCE_MANAGER_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"DEFAULT_ADMIN_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"RULES_MANAGEMENT_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IRule\",\"name\":\"rule_\",\"type\":\"address\"}],\"name\":\"addRule\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"bindToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"canTransfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"canTransferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"clearRules\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IRule\",\"name\":\"rule_\",\"type\":\"address\"}],\"name\":\"containsRule\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"created\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"destroyed\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"detectTransferRestriction\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"detectTransferRestrictionFrom\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleAdmin\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"getRoleMember\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleMemberCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleMembers\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTokenBound\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTokenBounds\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRole\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"isTokenBound\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"}],\"name\":\"isTrustedForwarder\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"restrictionCode\",\"type\":\"uint8\"}],\"name\":\"messageForTransferRestriction\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IRule\",\"name\":\"rule_\",\"type\":\"address\"}],\"name\":\"removeRule\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"callerConfirmation\",\"type\":\"address\"}],\"name\":\"renounceRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"ruleId\",\"type\":\"uint256\"}],\"name\":\"rule\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"rules\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"rulesCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IRule[]\",\"name\":\"rules_\",\"type\":\"address[]\"}],\"name\":\"setRules\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"transferred\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"transferred\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"trustedForwarder\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"unbindToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"version_\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"AccessControlBadConfirmation()\":[{\"details\":\"The caller of a function is not the expected one. NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\"}],\"AccessControlUnauthorizedAccount(address,bytes32)\":[{\"details\":\"The `account` is missing a role.\"}]},\"events\":{\"AddRule(address)\":{\"params\":{\"rule\":\"The address of the rule contract that was added.\"}},\"RemoveRule(address)\":{\"params\":{\"rule\":\"The address of the rule contract that was removed.\"}},\"RoleAdminChanged(bytes32,bytes32,bytes32)\":{\"details\":\"Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite {RoleAdminChanged} not being emitted to signal this.\"},\"RoleGranted(bytes32,address,address)\":{\"details\":\"Emitted when `account` is granted `role`. `sender` is the account that originated the contract call. This account bears the admin role (for the granted role). Expected in cases where the role was granted using the internal {AccessControl-_grantRole}.\"},\"RoleRevoked(bytes32,address,address)\":{\"details\":\"Emitted when `account` is revoked `role`. `sender` is the account that originated the contract call: - if using `revokeRole`, it is the admin role bearer - if using `renounceRole`, it is the role bearer (i.e. `account`)\"},\"TokenBound(address)\":{\"params\":{\"token\":\"The address of the token that was bound.\"}},\"TokenUnbound(address)\":{\"params\":{\"token\":\"The address of the token that was unbound.\"}}},\"kind\":\"dev\",\"methods\":{\"addRule(address)\":{\"details\":\"No on-chain maximum number of rules is enforced. Adding too many rules can increase transfer-time gas usage because rule checks are linear in rule count. Security convention: do not grant {RULES_MANAGEMENT_ROLE} to rule contracts.\",\"params\":{\"rule_\":\"The IRule contract to add.\"}},\"bindToken(address)\":{\"details\":\"Operator warning: \\\"multi-tenant\\\" means one RuleEngine is shared by multiple token contracts. In that setup, bind only tokens that are equally trusted and governed together.\",\"params\":{\"token\":\"The address of the token to bind.\"}},\"canTransfer(address,address,uint256)\":{\"details\":\"Don't check the balance and the user's right (access control)\"},\"canTransferFrom(address,address,address,uint256)\":{\"details\":\"Does not check balances or access rights (Access Control).\",\"params\":{\"from\":\"The source address.\",\"spender\":\"The address performing the transfer.\",\"to\":\"The destination address.\",\"value\":\"The number of tokens to transfer.\"},\"returns\":{\"_0\":\"isCompliant True if the transfer complies with policy.\"}},\"clearRules()\":{\"details\":\"After calling this function, no rules will remain set. Developers should keep in mind that this function has an unbounded cost and using it may render the function uncallable if the set grows to the point where clearing it consumes too much gas to fit in a block.\"},\"constructor\":{\"params\":{\"admin\":\"Address of the contract (Access Control)\",\"forwarderIrrevocable\":\"Address of the forwarder, required for the gasless support\"}},\"containsRule(address)\":{\"details\":\"Complexity: O(1).\",\"params\":{\"rule_\":\"The IRule contract to check for membership.\"},\"returns\":{\"_0\":\"True if the rule is present, false otherwise.\"}},\"created(address,uint256)\":{\"details\":\"Called by the token contract when new tokens are issued to an account. Reverts if the minting does not comply with the rules.\",\"params\":{\"to\":\"The address receiving the minted tokens.\",\"value\":\"The number of tokens created.\"}},\"destroyed(address,uint256)\":{\"details\":\"Called by the token contract when tokens are redeemed or burned. Reverts if the burning does not comply with the rules.\",\"params\":{\"from\":\"The address whose tokens are being destroyed.\",\"value\":\"The number of tokens destroyed.\"}},\"detectTransferRestriction(address,address,uint256)\":{\"params\":{\"from\":\"the origin address\",\"to\":\"the destination address\",\"value\":\"to transfer\"},\"returns\":{\"_0\":\"The restricion code or REJECTED_CODE_BASE.TRANSFER_OK (0) if the transfer is valid\"}},\"detectTransferRestrictionFrom(address,address,address,uint256)\":{\"details\":\" See {ERC-1404} Add an additionnal argument `spender` This function is where an issuer enforces the restriction logic of their token transfers. Some examples of this might include: - checking if the token recipient is whitelisted, - checking if a sender's tokens are frozen in a lock-up period, etc.\",\"returns\":{\"_0\":\"uint8 restricted code, 0 means the transfer is authorized\"}},\"getRoleAdmin(bytes32)\":{\"details\":\"Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}.\"},\"getRoleMember(bytes32,uint256)\":{\"details\":\"Returns one of the accounts that have `role`. `index` must be a value between 0 and {getRoleMemberCount}, non-inclusive. Role bearers are not sorted in any particular way, and their ordering may change at any point. WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure you perform all queries on the same block. See the following https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] for more information.\"},\"getRoleMemberCount(bytes32)\":{\"details\":\"Returns the number of accounts that have `role`. Can be used together with {getRoleMember} to enumerate all bearers of a role.\"},\"getRoleMembers(bytes32)\":{\"details\":\"Return all accounts that have `role` WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that this function has an unbounded cost, and using it as part of a state-changing function may render the function uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\"},\"getTokenBound()\":{\"details\":\"If multiple tokens are supported, consider using getTokenBounds().\",\"returns\":{\"_0\":\"The address of the currently bound token.\"}},\"getTokenBounds()\":{\"details\":\"This is a view-only function and does not modify state. This function is not part of the original ERC-3643 specification This operation will copy the entire storage to memory, which can be quite expensive. This is designed to mostly be used by view accessors that are queried without any gas fees.\",\"returns\":{\"_0\":\"An array of addresses of bound token contracts.\"}},\"grantRole(bytes32,address)\":{\"details\":\"Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleGranted} event.\"},\"hasRole(bytes32,address)\":{\"details\":\"The Default Admin has all roles\"},\"isTokenBound(address)\":{\"details\":\"Complexity: O(1). Note that there are no guarantees on the ordering of values inside the array, and it may change when more values are added or removed.\",\"params\":{\"token\":\"The token address to verify.\"},\"returns\":{\"_0\":\"True if the token is bound, false otherwise.\"}},\"isTrustedForwarder(address)\":{\"details\":\"Indicates whether any particular address is the trusted forwarder.\"},\"messageForTransferRestriction(uint8)\":{\"details\":\"See {ERC-1404} This function is effectively an accessor for the \\\"message\\\", a human-readable explanation as to why a transaction is restricted. \"},\"removeRule(address)\":{\"details\":\"Reverts if the provided rule is not found or does not match the stored rule at its index. Complexity: O(1).\",\"params\":{\"rule_\":\"The IRule contract to remove.\"}},\"renounceRole(bytes32,address)\":{\"details\":\"Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been revoked `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `callerConfirmation`. May emit a {RoleRevoked} event.\"},\"revokeRole(bytes32,address)\":{\"details\":\"Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleRevoked} event.\"},\"rule(uint256)\":{\"details\":\"Reverts if `ruleId` is out of bounds. Complexity: O(1). Note that there are no guarantees on the ordering of values inside the array, and it may change when more values are added or removed.\",\"params\":{\"ruleId\":\"The index of the desired rule in the array.\"},\"returns\":{\"_0\":\"The address of the corresponding IRule contract, return the `zero address` is out of bounds.\"}},\"rules()\":{\"details\":\"This is a view-only function that does not modify state. This operation will copy the entire storage to memory, which can be quite expensive. This is designed to mostly be used by view accessors that are queried without any gas fees.\",\"returns\":{\"_0\":\"An array of all active rule contract addresses.\"}},\"rulesCount()\":{\"details\":\"Equivalent to the length of the internal rules array. Complexity: O(1)\",\"returns\":{\"_0\":\"The number of active rules.\"}},\"setRules(address[])\":{\"details\":\"Replaces the entire rule set atomically. Reverts if `rules_` is empty. Use {clearRules} to remove all rules explicitly. To transition from one non-empty set to another without an enforcement gap, call this function directly with the new set. No on-chain maximum number of rules is enforced. Operators are responsible for keeping the rule set size compatible with the target chain gas limits. Security convention: rule contracts should be treated as trusted business logic, but should not also be granted {RULES_MANAGEMENT_ROLE}.\",\"params\":{\"rules_\":\"The array of addresses representing the new rules to be set.\"}},\"transferred(address,address,address,uint256)\":{\"details\":\" Must revert if the transfer is invalid Same name as ERC-3643 but with one supplementary argument `spender` This function can be used to update state variables of the RuleEngine contract This function can be called ONLY by the token contract bound to the RuleEngine\",\"params\":{\"from\":\"token holder address\",\"spender\":\"spender address (sender)\",\"to\":\"receiver address\",\"value\":\"value of tokens involved in the transfer\"}},\"transferred(address,address,uint256)\":{\"details\":\" This function can be used to update state variables of the compliance contract This function can be called ONLY by the token contract bound to the compliance\",\"params\":{\"from\":\"The address of the sender\",\"to\":\"The address of the receiver\",\"value\":\"value of tokens involved in the transfer\"}},\"trustedForwarder()\":{\"details\":\"Returns the address of the trusted forwarder.\"},\"unbindToken(address)\":{\"details\":\"Operator warning: unbinding is an administrative operation and does not erase any state already stored by external rule contracts in a previously shared (\\\"multi-tenant\\\") setup.\",\"params\":{\"token\":\"The address of the token to unbind.\"}},\"version()\":{\"details\":\"This value is useful to know which smart contract version has been used\",\"returns\":{\"version_\":\"A string representing the version of the token implementation (e.g., \\\"1.0.0\\\").\"}}},\"title\":\"Implementation of a ruleEngine as defined by the CMTAT\",\"version\":1},\"userdoc\":{\"events\":{\"AddRule(address)\":{\"notice\":\"Emitted when a new rule is added to the rule set.\"},\"ClearRules()\":{\"notice\":\"Emitted when all rules are cleared from the rule set.\"},\"RemoveRule(address)\":{\"notice\":\"Emitted when a rule is removed from the rule set.\"},\"TokenBound(address)\":{\"notice\":\"Emitted when a token is successfully bound to the compliance contract.\"},\"TokenUnbound(address)\":{\"notice\":\"Emitted when a token is successfully unbound from the compliance contract.\"}},\"kind\":\"user\",\"methods\":{\"RULES_MANAGEMENT_ROLE()\":{\"notice\":\"Role to manage the ruleEngine\"},\"addRule(address)\":{\"notice\":\"Adds a new rule to the current rule set.\"},\"bindToken(address)\":{\"notice\":\"Associates a token contract with this compliance contract.\"},\"canTransfer(address,address,uint256)\":{\"notice\":\"Returns true if the transfer is valid, and false otherwise.\"},\"canTransferFrom(address,address,address,uint256)\":{\"notice\":\"Checks if `spender` can transfer `value` tokens from `from` to `to` under compliance rules.\"},\"clearRules()\":{\"notice\":\"Removes all configured rules.\"},\"containsRule(address)\":{\"notice\":\"Checks whether a specific rule is currently configured.\"},\"created(address,uint256)\":{\"notice\":\"Updates the compliance contract state when tokens are created (minted).\"},\"destroyed(address,uint256)\":{\"notice\":\"Updates the compliance contract state when tokens are destroyed (burned).\"},\"detectTransferRestriction(address,address,uint256)\":{\"notice\":\"Go through all the rule to know if a restriction exists on the transfer\"},\"detectTransferRestrictionFrom(address,address,address,uint256)\":{\"notice\":\"Returns a uint8 code to indicate if a transfer is restricted or not\"},\"getTokenBound()\":{\"notice\":\"Returns the single token currently bound to this compliance contract.\"},\"getTokenBounds()\":{\"notice\":\"Returns all tokens currently bound to this compliance contract.\"},\"hasRole(bytes32,address)\":{\"notice\":\"Returns `true` if `account` has been granted `role`.\"},\"isTokenBound(address)\":{\"notice\":\"Checks whether a token is currently bound to this compliance contract.\"},\"removeRule(address)\":{\"notice\":\"Removes a specific rule from the current rule set.\"},\"rule(uint256)\":{\"notice\":\"Retrieves the rule address at a specific index.\"},\"rules()\":{\"notice\":\"Returns the full list of currently configured rules.\"},\"rulesCount()\":{\"notice\":\"Returns the total number of currently configured rules.\"},\"setRules(address[])\":{\"notice\":\"Defines the rules for the rule engine.\"},\"transferred(address,address,address,uint256)\":{\"notice\":\"Function called whenever tokens are transferred from one wallet to another\"},\"transferred(address,address,uint256)\":{\"notice\":\"Function called whenever tokens are transferred from one wallet to another\"},\"unbindToken(address)\":{\"notice\":\"Removes the association of a token contract from this compliance contract.\"},\"version()\":{\"notice\":\"Returns the current version of the token contract.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/deployment/RuleEngine.sol\":\"RuleEngine\"},\"evmVersion\":\"prague\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[\":@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\":@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\":CMTAT/=lib/CMTAT/contracts/\",\":CMTATv3.0.0/=lib/CMTATv3.0.0/contracts/\",\":erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/\",\":forge-std/=lib/forge-std/src/\",\":halmos-cheatcodes/=lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/\",\":openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\":openzeppelin-contracts/=lib/openzeppelin-contracts/\"]},\"sources\":{\"lib/CMTAT/contracts/interfaces/engine/IRuleEngine.sol\":{\"keccak256\":\"0x524a2cf2214a82fb96e97a18a94956fee68a419ecd6b2dc841aa1105f336c3f1\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://9c4728d80b6678101586515c0308c63bcba2a78b0a3c12d37b522d59f3175a01\",\"dweb:/ipfs/QmYP9SPbe2hB69jKkSg43qkz1HVxBayKrG14i9f6hx7hh8\"]},\"lib/CMTAT/contracts/interfaces/technical/IERC5679.sol\":{\"keccak256\":\"0xcc6f2e79d1d9eabcf4c7ffcbd85c0de31bb2b3cdf17eb847dffb7c2d2a8c4695\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://d618bc2be7c6bc167037fe57ca648523c671c61791f3f0c65965ab7139d6dc33\",\"dweb:/ipfs/QmSrCKWFjpg1SQ7v2k3vRyWpcU9dB6Pbk167R4oAzUc2Te\"]},\"lib/CMTAT/contracts/interfaces/tokenization/IERC3643Partial.sol\":{\"keccak256\":\"0x1707381177447b1a398c443c7e753942df0c5d4633e80d2864db472e89e43dc0\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://c4281d98847629b67222332bea67f336623937758be908ee9ca1aa40b3abe19d\",\"dweb:/ipfs/QmZQBruKJH3sStjBmCb28rxRkUkZ4EFsDCi8WZ7Y85spxS\"]},\"lib/CMTAT/contracts/interfaces/tokenization/draft-IERC1404.sol\":{\"keccak256\":\"0x17fb1f64b546fd882331dffbd8c7f4e53c51738b9e2621a0dcfcf30e64d8b66e\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://c35fe277d5d99a0943293b5da5622947095e6b719af35fda9ef2c714a7879a4b\",\"dweb:/ipfs/QmRV5q3XvjJE8sxJJBpEkwk1qyz3r4McH2BdX1v2ZxZGZh\"]},\"lib/CMTAT/contracts/interfaces/tokenization/draft-IERC7551.sol\":{\"keccak256\":\"0x709074d96bd5d7aa07d2ba3a1c9a99ae0fd4361f7322b528b42f3b83c5dcb984\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://ca67a06011b746b55bf2465988dc10a4e6371e40b5108c54531f03e938bda865\",\"dweb:/ipfs/QmbjFyDAJsUXywqzU2s96pFqFpC5DLKdfa8WjMBtQPhKGE\"]},\"lib/CMTAT/contracts/interfaces/tokenization/draft-IERC7943.sol\":{\"keccak256\":\"0x1a341fc7ee7d9b8b00b6168b35a6a844d90431749d8ca694174c52c41e11763f\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://4fb6b13953539b99262cb299961fb8ff8a020de79b12f76c63decf33ff9d5103\",\"dweb:/ipfs/QmQ3bnkQJgD2s6xpapThCPTSMbDREokVEiM7extwQgfrv7\"]},\"lib/CMTAT/contracts/library/ERC1404ExtendInterfaceId.sol\":{\"keccak256\":\"0xe5f6f08d319d27f20989936460d3947eed5fdcb470f80e920f4fb09ccc7e1e87\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://cb654fe37c2bc6c765c67c5f94a769580312d1d4109c50262677ac406362f91e\",\"dweb:/ipfs/Qmc8ZFVANCmULNozM2wFUSGKXBgUHR5bpDC3ZVjV4XoEv7\"]},\"lib/CMTAT/contracts/library/RuleEngineInterfaceId.sol\":{\"keccak256\":\"0x759990208069b5a0862a255eff790d52d1d64bbb6c334705fc12414936825692\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://0bce1c17cbbddac4bf123f602dc980246e5bec724f5ed3107e148548b930e124\",\"dweb:/ipfs/QmRZUxmRN9ji9UYueD6knhnz2nSsDRZgRTX74uenGczVjA\"]},\"lib/openzeppelin-contracts/contracts/access/AccessControl.sol\":{\"keccak256\":\"0x4686ec784d75f95beaf2bf5b5f26e5f946d4c864aaee9c3c62bdc18381f5e017\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://26710ca191913f3c9df542079c4a6dcff02968e92d4f7357daefef9fbe72a19c\",\"dweb:/ipfs/QmanHbeWuBbVEqXySHa1zhm2rExjYpChDBubBaJNTCa2JB\"]},\"lib/openzeppelin-contracts/contracts/access/IAccessControl.sol\":{\"keccak256\":\"0xbff9f59c84e5337689161ce7641c0ef8e872d6a7536fbc1f5133f128887aba3c\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://b308f882e796f7b79c9502deacb0a62983035c6f6f4e962b319ba6a1f4a77d3d\",\"dweb:/ipfs/QmaWCW7ahEQqFjwhSUhV7Ae7WhfNvzSpE7DQ58hvEooqPL\"]},\"lib/openzeppelin-contracts/contracts/access/extensions/AccessControlEnumerable.sol\":{\"keccak256\":\"0xbae499c224def4d252ee766288a178769529a16ab26670a2761fd405b98c2ba0\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://7bc24842026d827fa4a9091b4464846c280f86162521a7c16e6388ce11fced8d\",\"dweb:/ipfs/QmRtwbSbzb66Wt8Y37ocVLqckdxuSkZGNF5bHwhj9AAS5L\"]},\"lib/openzeppelin-contracts/contracts/access/extensions/IAccessControlEnumerable.sol\":{\"keccak256\":\"0xbc97d8c0d67d4d7eba1e662f0a8671712ace9e060ab03af547c4bb321aec1d8c\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://890d156f50630d52c7be57d7e0499132d6fd92b2e1365b81531f4463b3304377\",\"dweb:/ipfs/QmUHe9uL1ciePH2pQg7wdrgTAFRZWjcpBEAg8V1UNtXutd\"]},\"lib/openzeppelin-contracts/contracts/interfaces/IERC165.sol\":{\"keccak256\":\"0x0afcb7e740d1537b252cb2676f600465ce6938398569f09ba1b9ca240dde2dfc\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://1c299900ac4ec268d4570ecef0d697a3013cd11a6eb74e295ee3fbc945056037\",\"dweb:/ipfs/Qmab9owJoxcA7vJT5XNayCMaUR1qxqj1NDzzisduwaJMcZ\"]},\"lib/openzeppelin-contracts/contracts/metatx/ERC2771Context.sol\":{\"keccak256\":\"0x9695d220b99dcf62910533bdf5d40d4cf6a4e04d5b106b6803a80586486dc7f7\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://83b7aecd65882d8953643dce144efe91367082cc01830c9c4ed3c8a4837fb558\",\"dweb:/ipfs/QmQ5HxGavcCKjuhd8buv177qjG6A4kvxx4pZviceKdspdM\"]},\"lib/openzeppelin-contracts/contracts/utils/Arrays.sol\":{\"keccak256\":\"0xb3b81029526a4c3acf39e57cc446407141ebce338cc99585942af1340e1a69e0\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://3857ce97e8f7a51ad78ea5419b3386e18fcc8af73b65803eedd8193ab7abc9df\",\"dweb:/ipfs/QmSQi6x2cYsUy76mfMNwuq151bVmh4kAND141kjume51Aq\"]},\"lib/openzeppelin-contracts/contracts/utils/Comparators.sol\":{\"keccak256\":\"0x302eecd8cf323b4690e3494a7d960b3cbce077032ab8ef655b323cdd136cec58\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://49ba706f1bc476d68fe6c1fad75517acea4e9e275be0989b548e292eb3a3eacd\",\"dweb:/ipfs/QmeBpvcdGWzWMKTQESUCEhHgnEQYYATVwPxLMxa6vMT7jC\"]},\"lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"keccak256\":\"0x493033a8d1b176a037b2cc6a04dad01a5c157722049bbecf632ca876224dd4b2\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6a708e8a5bdb1011c2c381c9a5cfd8a9a956d7d0a9dc1bd8bcdaf52f76ef2f12\",\"dweb:/ipfs/Qmax9WHBnVsZP46ZxEMNRQpLQnrdE4dK8LehML1Py8FowF\"]},\"lib/openzeppelin-contracts/contracts/utils/Panic.sol\":{\"keccak256\":\"0xf7fe324703a64fc51702311dc51562d5cb1497734f074e4f483bfb6717572d7a\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c6a5ff4f9fd8649b7ee20800b7fa387d3465bd77cf20c2d1068cd5c98e1ed57a\",\"dweb:/ipfs/QmVSaVJf9FXFhdYEYeCEfjMVHrxDh5qL4CGkxdMWpQCrqG\"]},\"lib/openzeppelin-contracts/contracts/utils/SlotDerivation.sol\":{\"keccak256\":\"0x94045fd4f268edf2b2d01ef119268548c320366d6f5294ad30c1b8f9d4f5225f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://edfda81f426f8948b3834115c21e83c48180e6db0d2a8cd2debb2185ed349337\",\"dweb:/ipfs/QmdYZneFyDAux1BuWQxLAdqtABrGS2k9WYCa7C9dvpKkWv\"]},\"lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol\":{\"keccak256\":\"0xcf74f855663ce2ae00ed8352666b7935f6cddea2932fdf2c3ecd30a9b1cd0e97\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://9f660b1f351b757dfe01438e59888f31f33ded3afcf5cb5b0d9bf9aa6f320a8b\",\"dweb:/ipfs/QmarDJ5hZEgBtCmmrVzEZWjub9769eD686jmzb2XpSU1cM\"]},\"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\":{\"keccak256\":\"0x2d9dc2fe26180f74c11c13663647d38e259e45f95eb88f57b61d2160b0109d3e\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://81233d1f98060113d9922180bb0f14f8335856fe9f339134b09335e9f678c377\",\"dweb:/ipfs/QmWh6R35SarhAn4z2wH8SU456jJSYL2FgucfTFgbHJJN4E\"]},\"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165Checker.sol\":{\"keccak256\":\"0x7c7ad70641a7f8cd44def0857ec97b0e40bfd073b2d6037a5f57ce9527ee9bc5\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://e05c6572dfe769f7aea6f3a8002951cc12d143d980dad29f6c5feedf9408bc14\",\"dweb:/ipfs/QmXM7C8YEptxisZiEefXUrwdXt3zMaCobmkCchxTtDg1oK\"]},\"lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"keccak256\":\"0x8891738ffe910f0cf2da09566928589bf5d63f4524dd734fd9cedbac3274dd5c\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://971f954442df5c2ef5b5ebf1eb245d7105d9fbacc7386ee5c796df1d45b21617\",\"dweb:/ipfs/QmadRjHbkicwqwwh61raUEapaVEtaLMcYbQZWs9gUkgj3u\"]},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"keccak256\":\"0x59973a93b1f983f94e10529f46ca46544a9fec2b5f56fb1390bbe9e0dc79f857\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c55ef8f0b9719790c2ae6f81d80a59ffb89f2f0abe6bc065585bd79edce058c5\",\"dweb:/ipfs/QmNNmCbX9NjPXKqHJN8R1WC2rNeZSQrPZLd6FF6AKLyH5Y\"]},\"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\":{\"keccak256\":\"0xc8cae21c9ae4a46e5162ff9bf5b351d6fa6a6eba72d515f3bc1bdfeda7fdf083\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://ce830ebcf28e31643caba318996db3763c36d52cd0f23798ba83c135355d45e9\",\"dweb:/ipfs/QmdGPcvptHN7UBCbUYBbRX3hiRVRFLRwno8b4uga6uFNif\"]},\"lib/openzeppelin-contracts/contracts/utils/structs/EnumerableSet.sol\":{\"keccak256\":\"0x5c298e834696707e274a71a224969d36faecd928a8076603210d67d091adb4ae\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://a93fe967b4d55b31157164cbb7e3e1ebaf3535fc1d3f8d0156da7abb9b565d90\",\"dweb:/ipfs/QmXH7nyxwEUeMPFDDmkdUwqxLEcezaSmVyunyMAuck1WqR\"]},\"src/RuleEngineBase.sol\":{\"keccak256\":\"0x9edae8ce7df18638cf56b571be18251d4ac4c435844c8cd77d1f7f651623c568\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://9758c7256a994b371c00d9e0098be5d76d9896f2a556208dfb83768d4d4e916b\",\"dweb:/ipfs/QmdZwwiB29tzheoaoRWiJdbbGMH2nM46ojLp7WFjm9D19h\"]},\"src/deployment/RuleEngine.sol\":{\"keccak256\":\"0xa1aa57ac7e2af018dbb8a24b07028f3f6fe0bf7641574f9a579bd3c102654a41\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://a18b877f001ccdd8ca27636b5ce868185f8ce83ef14b5277aedee27a389182e4\",\"dweb:/ipfs/QmYY2dU7dSkvHb5rFgHEqtNxpSaELzgnRCmkdzxWAWwJem\"]},\"src/interfaces/IERC3643Compliance.sol\":{\"keccak256\":\"0xf86e78e8f737795c3762b402b121b0f1822d6b27414aeca08ea6f036cccea07b\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://c795d1b89a1393b2225f6e58c0310d345d78ff534ab028353413c4a5aaf9ecf7\",\"dweb:/ipfs/QmNcJsJzLWzSAV77whMzu7je2Mj2pWoTYYn1z76kqB5mKH\"]},\"src/interfaces/IRule.sol\":{\"keccak256\":\"0x315fd1d0147d40d3cc1ee35f6ddb8c9e25e6e4f96034a285e6f342c59c3cc222\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://5b0ecca410bf89169e5c6393bc4d8fce97a5b3dcf8a2bba02317da85c98f4d0c\",\"dweb:/ipfs/QmeGS5vbFwkmEvJh7s27Q9xW4xGXuUohh2zGPVbgxgjfnu\"]},\"src/interfaces/IRulesManagementModule.sol\":{\"keccak256\":\"0x1be8087ef526f664cf8ba5dd35d4d12fc1880f905e3ba2e553ee02cb7d6506c1\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://545cafd73f2fe9b2b89b37e905057637f58ae2c1da7f3dc33493b515c87a720f\",\"dweb:/ipfs/QmXiTEhLSpN6sj1fiwFT9V6bGD1VCXTqQJiNnXcLrYmW7N\"]},\"src/modules/ERC2771ModuleStandalone.sol\":{\"keccak256\":\"0xecc9aec20ff41c46404f6fcb9bfb0fd5588781fbb4f2fbec351f603a31c178b0\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://48674e77afe59b6c6e6aa8b0d5e370ca58c9a354b5dc294bb3c9f10fbd12a3f3\",\"dweb:/ipfs/QmY3HhbBDqsBvrGBXoRwgVpfSNtiK2XmhaxVpS1F3dSPx9\"]},\"src/modules/ERC3643ComplianceModule.sol\":{\"keccak256\":\"0xdb472471270ea23d4694ca2d2eb107ce668affc9dbe18b5a6eda312ab4800a33\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://6200e990afca50a32fb0a0ad76ffe955447a67cab6e93f64281fc9f14208aab1\",\"dweb:/ipfs/QmXXhRsBq3eGDgBqQwWL5w4Sn6pdTeeXRvpC4jZBDVb6nQ\"]},\"src/modules/RulesManagementModule.sol\":{\"keccak256\":\"0xc9c58e027874658577285de9c9bf9069cd773573a615df7c9644c6c96c69dbc3\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://a6c9ca74cc247b42b9852b35cb4eeadc919d383d7bbd4f4df0739ee6a8bce2c3\",\"dweb:/ipfs/QmfJCvSQjqQrQXYt9JEHiJRZATy1s7q53DKxZC1QsSYMHZ\"]},\"src/modules/VersionModule.sol\":{\"keccak256\":\"0x077070dca24da125a764111d336c0a8fb3445b82d93692ff76b22384b0f4f39f\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://be8df88e667fb2de39d095f0c396d23ed263fdc51a4095fedc89a326540a03ee\",\"dweb:/ipfs/QmYfhhEvNee1XYwCYZCVAKpUUWBd5FP5qvTMYGr6ogC8kA\"]},\"src/modules/library/ComplianceInterfaceId.sol\":{\"keccak256\":\"0xa0f15ca7f9e0fa8ccb854ea2bd812f220c68c280682b56e8d1a437ddba4b6d1f\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://1e01a79b4a2110a401c3d2fbead97844f7428d6dc6603dccf795d42dbc142786\",\"dweb:/ipfs/QmV88ZcDHTU33oXNLFTshUBZ7otgcZRN1HXwywda7Fgz9a\"]},\"src/modules/library/RuleEngineInvariantStorage.sol\":{\"keccak256\":\"0x15005e56f8fbf8f9b8a41c4bfed6c842e37be49fa52b0dbb2edc6b08b9e50c2f\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://06c90dd748d060cb1b05de978cb42fd79d9b49a2beb3a479b4e49f8edaba1195\",\"dweb:/ipfs/QmYXEQWrwJkuzWBdi5hjSaM6pWhrNUf2kH2pHX8jRu9dZS\"]},\"src/modules/library/RuleInterfaceId.sol\":{\"keccak256\":\"0x3c57987589d6205e2546d4ce332e944d1667dddfe897087028a95ed804c50882\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://0e1718e500d4cb5cf4441131c57d23da788f2835e9a014e7d1f62dfb6161647a\",\"dweb:/ipfs/QmXY5cjc9Dzrp7ML7DfvDB9zg7t4cene3g4K9AAuDmLLfC\"]},\"src/modules/library/RulesManagementModuleInvariantStorage.sol\":{\"keccak256\":\"0xa6f9109698f169be74c309a1efadd48edffcb0e9585523258477bf07942c8ae6\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://4c28513636b660111b60a7028c9600b30dcfda291a831343d9e27e253b80856a\",\"dweb:/ipfs/QmQVSZ9N6vjPxNnJDTqEuGSWqNdoxHKhzTzP2cvgZpBSzj\"]}},\"version\":1}","metadata":{"compiler":{"version":"0.8.34+commit.80d5c536"},"language":"Solidity","output":{"abi":[{"inputs":[{"internalType":"address","name":"admin","type":"address"},{"internalType":"address","name":"forwarderIrrevocable","type":"address"},{"internalType":"address","name":"tokenContract","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"type":"error","name":"AccessControlBadConfirmation"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"neededRole","type":"bytes32"}],"type":"error","name":"AccessControlUnauthorizedAccount"},{"inputs":[],"type":"error","name":"RuleEngine_AdminWithAddressZeroNotAllowed"},{"inputs":[],"type":"error","name":"RuleEngine_ERC3643Compliance_InvalidTokenAddress"},{"inputs":[],"type":"error","name":"RuleEngine_ERC3643Compliance_OperationNotSuccessful"},{"inputs":[],"type":"error","name":"RuleEngine_ERC3643Compliance_TokenAlreadyBound"},{"inputs":[],"type":"error","name":"RuleEngine_ERC3643Compliance_TokenNotBound"},{"inputs":[],"type":"error","name":"RuleEngine_ERC3643Compliance_UnauthorizedCaller"},{"inputs":[],"type":"error","name":"RuleEngine_RuleInvalidInterface"},{"inputs":[],"type":"error","name":"RuleEngine_RulesManagementModule_ArrayIsEmpty"},{"inputs":[],"type":"error","name":"RuleEngine_RulesManagementModule_OperationNotSuccessful"},{"inputs":[],"type":"error","name":"RuleEngine_RulesManagementModule_RuleAddressZeroNotAllowed"},{"inputs":[],"type":"error","name":"RuleEngine_RulesManagementModule_RuleAlreadyExists"},{"inputs":[],"type":"error","name":"RuleEngine_RulesManagementModule_RuleDoNotMatch"},{"inputs":[{"internalType":"contract IRule","name":"rule","type":"address","indexed":true}],"type":"event","name":"AddRule","anonymous":false},{"inputs":[],"type":"event","name":"ClearRules","anonymous":false},{"inputs":[{"internalType":"contract IRule","name":"rule","type":"address","indexed":true}],"type":"event","name":"RemoveRule","anonymous":false},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32","indexed":true},{"internalType":"bytes32","name":"previousAdminRole","type":"bytes32","indexed":true},{"internalType":"bytes32","name":"newAdminRole","type":"bytes32","indexed":true}],"type":"event","name":"RoleAdminChanged","anonymous":false},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32","indexed":true},{"internalType":"address","name":"account","type":"address","indexed":true},{"internalType":"address","name":"sender","type":"address","indexed":true}],"type":"event","name":"RoleGranted","anonymous":false},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32","indexed":true},{"internalType":"address","name":"account","type":"address","indexed":true},{"internalType":"address","name":"sender","type":"address","indexed":true}],"type":"event","name":"RoleRevoked","anonymous":false},{"inputs":[{"internalType":"address","name":"token","type":"address","indexed":false}],"type":"event","name":"TokenBound","anonymous":false},{"inputs":[{"internalType":"address","name":"token","type":"address","indexed":false}],"type":"event","name":"TokenUnbound","anonymous":false},{"inputs":[],"stateMutability":"view","type":"function","name":"COMPLIANCE_MANAGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"RULES_MANAGEMENT_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}]},{"inputs":[{"internalType":"contract IRule","name":"rule_","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"addRule"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"bindToken"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"view","type":"function","name":"canTransfer","outputs":[{"internalType":"bool","name":"","type":"bool"}]},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"view","type":"function","name":"canTransferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}]},{"inputs":[],"stateMutability":"nonpayable","type":"function","name":"clearRules"},{"inputs":[{"internalType":"contract IRule","name":"rule_","type":"address"}],"stateMutability":"view","type":"function","name":"containsRule","outputs":[{"internalType":"bool","name":"","type":"bool"}]},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"nonpayable","type":"function","name":"created"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"nonpayable","type":"function","name":"destroyed"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"view","type":"function","name":"detectTransferRestriction","outputs":[{"internalType":"uint8","name":"","type":"uint8"}]},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"view","type":"function","name":"detectTransferRestrictionFrom","outputs":[{"internalType":"uint8","name":"","type":"uint8"}]},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"stateMutability":"view","type":"function","name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}]},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"stateMutability":"view","type":"function","name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}]},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"stateMutability":"view","type":"function","name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}]},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"stateMutability":"view","type":"function","name":"getRoleMembers","outputs":[{"internalType":"address[]","name":"","type":"address[]"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"getTokenBound","outputs":[{"internalType":"address","name":"","type":"address"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"getTokenBounds","outputs":[{"internalType":"address[]","name":"","type":"address[]"}]},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"grantRole"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"stateMutability":"view","type":"function","name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}]},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"stateMutability":"view","type":"function","name":"isTokenBound","outputs":[{"internalType":"bool","name":"","type":"bool"}]},{"inputs":[{"internalType":"address","name":"forwarder","type":"address"}],"stateMutability":"view","type":"function","name":"isTrustedForwarder","outputs":[{"internalType":"bool","name":"","type":"bool"}]},{"inputs":[{"internalType":"uint8","name":"restrictionCode","type":"uint8"}],"stateMutability":"view","type":"function","name":"messageForTransferRestriction","outputs":[{"internalType":"string","name":"","type":"string"}]},{"inputs":[{"internalType":"contract IRule","name":"rule_","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"removeRule"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"callerConfirmation","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"renounceRole"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"revokeRole"},{"inputs":[{"internalType":"uint256","name":"ruleId","type":"uint256"}],"stateMutability":"view","type":"function","name":"rule","outputs":[{"internalType":"address","name":"","type":"address"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"rules","outputs":[{"internalType":"address[]","name":"","type":"address[]"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"rulesCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}]},{"inputs":[{"internalType":"contract IRule[]","name":"rules_","type":"address[]"}],"stateMutability":"nonpayable","type":"function","name":"setRules"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"stateMutability":"view","type":"function","name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}]},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"nonpayable","type":"function","name":"transferred"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"nonpayable","type":"function","name":"transferred"},{"inputs":[],"stateMutability":"view","type":"function","name":"trustedForwarder","outputs":[{"internalType":"address","name":"","type":"address"}]},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"unbindToken"},{"inputs":[],"stateMutability":"view","type":"function","name":"version","outputs":[{"internalType":"string","name":"version_","type":"string"}]}],"devdoc":{"kind":"dev","methods":{"addRule(address)":{"details":"No on-chain maximum number of rules is enforced. Adding too many rules can increase transfer-time gas usage because rule checks are linear in rule count. Security convention: do not grant {RULES_MANAGEMENT_ROLE} to rule contracts.","params":{"rule_":"The IRule contract to add."}},"bindToken(address)":{"details":"Operator warning: \"multi-tenant\" means one RuleEngine is shared by multiple token contracts. In that setup, bind only tokens that are equally trusted and governed together.","params":{"token":"The address of the token to bind."}},"canTransfer(address,address,uint256)":{"details":"Don't check the balance and the user's right (access control)"},"canTransferFrom(address,address,address,uint256)":{"details":"Does not check balances or access rights (Access Control).","params":{"from":"The source address.","spender":"The address performing the transfer.","to":"The destination address.","value":"The number of tokens to transfer."},"returns":{"_0":"isCompliant True if the transfer complies with policy."}},"clearRules()":{"details":"After calling this function, no rules will remain set. Developers should keep in mind that this function has an unbounded cost and using it may render the function uncallable if the set grows to the point where clearing it consumes too much gas to fit in a block."},"constructor":{"params":{"admin":"Address of the contract (Access Control)","forwarderIrrevocable":"Address of the forwarder, required for the gasless support"}},"containsRule(address)":{"details":"Complexity: O(1).","params":{"rule_":"The IRule contract to check for membership."},"returns":{"_0":"True if the rule is present, false otherwise."}},"created(address,uint256)":{"details":"Called by the token contract when new tokens are issued to an account. Reverts if the minting does not comply with the rules.","params":{"to":"The address receiving the minted tokens.","value":"The number of tokens created."}},"destroyed(address,uint256)":{"details":"Called by the token contract when tokens are redeemed or burned. Reverts if the burning does not comply with the rules.","params":{"from":"The address whose tokens are being destroyed.","value":"The number of tokens destroyed."}},"detectTransferRestriction(address,address,uint256)":{"params":{"from":"the origin address","to":"the destination address","value":"to transfer"},"returns":{"_0":"The restricion code or REJECTED_CODE_BASE.TRANSFER_OK (0) if the transfer is valid"}},"detectTransferRestrictionFrom(address,address,address,uint256)":{"details":" See {ERC-1404} Add an additionnal argument `spender` This function is where an issuer enforces the restriction logic of their token transfers. Some examples of this might include: - checking if the token recipient is whitelisted, - checking if a sender's tokens are frozen in a lock-up period, etc.","returns":{"_0":"uint8 restricted code, 0 means the transfer is authorized"}},"getRoleAdmin(bytes32)":{"details":"Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}."},"getRoleMember(bytes32,uint256)":{"details":"Returns one of the accounts that have `role`. `index` must be a value between 0 and {getRoleMemberCount}, non-inclusive. Role bearers are not sorted in any particular way, and their ordering may change at any point. WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure you perform all queries on the same block. See the following https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] for more information."},"getRoleMemberCount(bytes32)":{"details":"Returns the number of accounts that have `role`. Can be used together with {getRoleMember} to enumerate all bearers of a role."},"getRoleMembers(bytes32)":{"details":"Return all accounts that have `role` WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that this function has an unbounded cost, and using it as part of a state-changing function may render the function uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block."},"getTokenBound()":{"details":"If multiple tokens are supported, consider using getTokenBounds().","returns":{"_0":"The address of the currently bound token."}},"getTokenBounds()":{"details":"This is a view-only function and does not modify state. This function is not part of the original ERC-3643 specification This operation will copy the entire storage to memory, which can be quite expensive. This is designed to mostly be used by view accessors that are queried without any gas fees.","returns":{"_0":"An array of addresses of bound token contracts."}},"grantRole(bytes32,address)":{"details":"Grants `role` to `account`. If `account` had not been already granted `role`, emits a {RoleGranted} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleGranted} event."},"hasRole(bytes32,address)":{"details":"The Default Admin has all roles"},"isTokenBound(address)":{"details":"Complexity: O(1). Note that there are no guarantees on the ordering of values inside the array, and it may change when more values are added or removed.","params":{"token":"The token address to verify."},"returns":{"_0":"True if the token is bound, false otherwise."}},"isTrustedForwarder(address)":{"details":"Indicates whether any particular address is the trusted forwarder."},"messageForTransferRestriction(uint8)":{"details":"See {ERC-1404} This function is effectively an accessor for the \"message\", a human-readable explanation as to why a transaction is restricted. "},"removeRule(address)":{"details":"Reverts if the provided rule is not found or does not match the stored rule at its index. Complexity: O(1).","params":{"rule_":"The IRule contract to remove."}},"renounceRole(bytes32,address)":{"details":"Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). If the calling account had been revoked `role`, emits a {RoleRevoked} event. Requirements: - the caller must be `callerConfirmation`. May emit a {RoleRevoked} event."},"revokeRole(bytes32,address)":{"details":"Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleRevoked} event."},"rule(uint256)":{"details":"Reverts if `ruleId` is out of bounds. Complexity: O(1). Note that there are no guarantees on the ordering of values inside the array, and it may change when more values are added or removed.","params":{"ruleId":"The index of the desired rule in the array."},"returns":{"_0":"The address of the corresponding IRule contract, return the `zero address` is out of bounds."}},"rules()":{"details":"This is a view-only function that does not modify state. This operation will copy the entire storage to memory, which can be quite expensive. This is designed to mostly be used by view accessors that are queried without any gas fees.","returns":{"_0":"An array of all active rule contract addresses."}},"rulesCount()":{"details":"Equivalent to the length of the internal rules array. Complexity: O(1)","returns":{"_0":"The number of active rules."}},"setRules(address[])":{"details":"Replaces the entire rule set atomically. Reverts if `rules_` is empty. Use {clearRules} to remove all rules explicitly. To transition from one non-empty set to another without an enforcement gap, call this function directly with the new set. No on-chain maximum number of rules is enforced. Operators are responsible for keeping the rule set size compatible with the target chain gas limits. Security convention: rule contracts should be treated as trusted business logic, but should not also be granted {RULES_MANAGEMENT_ROLE}.","params":{"rules_":"The array of addresses representing the new rules to be set."}},"transferred(address,address,address,uint256)":{"details":" Must revert if the transfer is invalid Same name as ERC-3643 but with one supplementary argument `spender` This function can be used to update state variables of the RuleEngine contract This function can be called ONLY by the token contract bound to the RuleEngine","params":{"from":"token holder address","spender":"spender address (sender)","to":"receiver address","value":"value of tokens involved in the transfer"}},"transferred(address,address,uint256)":{"details":" This function can be used to update state variables of the compliance contract This function can be called ONLY by the token contract bound to the compliance","params":{"from":"The address of the sender","to":"The address of the receiver","value":"value of tokens involved in the transfer"}},"trustedForwarder()":{"details":"Returns the address of the trusted forwarder."},"unbindToken(address)":{"details":"Operator warning: unbinding is an administrative operation and does not erase any state already stored by external rule contracts in a previously shared (\"multi-tenant\") setup.","params":{"token":"The address of the token to unbind."}},"version()":{"details":"This value is useful to know which smart contract version has been used","returns":{"version_":"A string representing the version of the token implementation (e.g., \"1.0.0\")."}}},"version":1},"userdoc":{"kind":"user","methods":{"RULES_MANAGEMENT_ROLE()":{"notice":"Role to manage the ruleEngine"},"addRule(address)":{"notice":"Adds a new rule to the current rule set."},"bindToken(address)":{"notice":"Associates a token contract with this compliance contract."},"canTransfer(address,address,uint256)":{"notice":"Returns true if the transfer is valid, and false otherwise."},"canTransferFrom(address,address,address,uint256)":{"notice":"Checks if `spender` can transfer `value` tokens from `from` to `to` under compliance rules."},"clearRules()":{"notice":"Removes all configured rules."},"containsRule(address)":{"notice":"Checks whether a specific rule is currently configured."},"created(address,uint256)":{"notice":"Updates the compliance contract state when tokens are created (minted)."},"destroyed(address,uint256)":{"notice":"Updates the compliance contract state when tokens are destroyed (burned)."},"detectTransferRestriction(address,address,uint256)":{"notice":"Go through all the rule to know if a restriction exists on the transfer"},"detectTransferRestrictionFrom(address,address,address,uint256)":{"notice":"Returns a uint8 code to indicate if a transfer is restricted or not"},"getTokenBound()":{"notice":"Returns the single token currently bound to this compliance contract."},"getTokenBounds()":{"notice":"Returns all tokens currently bound to this compliance contract."},"hasRole(bytes32,address)":{"notice":"Returns `true` if `account` has been granted `role`."},"isTokenBound(address)":{"notice":"Checks whether a token is currently bound to this compliance contract."},"removeRule(address)":{"notice":"Removes a specific rule from the current rule set."},"rule(uint256)":{"notice":"Retrieves the rule address at a specific index."},"rules()":{"notice":"Returns the full list of currently configured rules."},"rulesCount()":{"notice":"Returns the total number of currently configured rules."},"setRules(address[])":{"notice":"Defines the rules for the rule engine."},"transferred(address,address,address,uint256)":{"notice":"Function called whenever tokens are transferred from one wallet to another"},"transferred(address,address,uint256)":{"notice":"Function called whenever tokens are transferred from one wallet to another"},"unbindToken(address)":{"notice":"Removes the association of a token contract from this compliance contract."},"version()":{"notice":"Returns the current version of the token contract."}},"version":1}},"settings":{"remappings":["@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/","@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/","CMTAT/=lib/CMTAT/contracts/","CMTATv3.0.0/=lib/CMTATv3.0.0/contracts/","erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/","forge-std/=lib/forge-std/src/","halmos-cheatcodes/=lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/","openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/","openzeppelin-contracts/=lib/openzeppelin-contracts/"],"optimizer":{"enabled":true,"runs":200},"metadata":{"bytecodeHash":"ipfs"},"compilationTarget":{"src/deployment/RuleEngine.sol":"RuleEngine"},"evmVersion":"prague","libraries":{}},"sources":{"lib/CMTAT/contracts/interfaces/engine/IRuleEngine.sol":{"keccak256":"0x524a2cf2214a82fb96e97a18a94956fee68a419ecd6b2dc841aa1105f336c3f1","urls":["bzz-raw://9c4728d80b6678101586515c0308c63bcba2a78b0a3c12d37b522d59f3175a01","dweb:/ipfs/QmYP9SPbe2hB69jKkSg43qkz1HVxBayKrG14i9f6hx7hh8"],"license":"MPL-2.0"},"lib/CMTAT/contracts/interfaces/technical/IERC5679.sol":{"keccak256":"0xcc6f2e79d1d9eabcf4c7ffcbd85c0de31bb2b3cdf17eb847dffb7c2d2a8c4695","urls":["bzz-raw://d618bc2be7c6bc167037fe57ca648523c671c61791f3f0c65965ab7139d6dc33","dweb:/ipfs/QmSrCKWFjpg1SQ7v2k3vRyWpcU9dB6Pbk167R4oAzUc2Te"],"license":"MPL-2.0"},"lib/CMTAT/contracts/interfaces/tokenization/IERC3643Partial.sol":{"keccak256":"0x1707381177447b1a398c443c7e753942df0c5d4633e80d2864db472e89e43dc0","urls":["bzz-raw://c4281d98847629b67222332bea67f336623937758be908ee9ca1aa40b3abe19d","dweb:/ipfs/QmZQBruKJH3sStjBmCb28rxRkUkZ4EFsDCi8WZ7Y85spxS"],"license":"MPL-2.0"},"lib/CMTAT/contracts/interfaces/tokenization/draft-IERC1404.sol":{"keccak256":"0x17fb1f64b546fd882331dffbd8c7f4e53c51738b9e2621a0dcfcf30e64d8b66e","urls":["bzz-raw://c35fe277d5d99a0943293b5da5622947095e6b719af35fda9ef2c714a7879a4b","dweb:/ipfs/QmRV5q3XvjJE8sxJJBpEkwk1qyz3r4McH2BdX1v2ZxZGZh"],"license":"MPL-2.0"},"lib/CMTAT/contracts/interfaces/tokenization/draft-IERC7551.sol":{"keccak256":"0x709074d96bd5d7aa07d2ba3a1c9a99ae0fd4361f7322b528b42f3b83c5dcb984","urls":["bzz-raw://ca67a06011b746b55bf2465988dc10a4e6371e40b5108c54531f03e938bda865","dweb:/ipfs/QmbjFyDAJsUXywqzU2s96pFqFpC5DLKdfa8WjMBtQPhKGE"],"license":"MPL-2.0"},"lib/CMTAT/contracts/interfaces/tokenization/draft-IERC7943.sol":{"keccak256":"0x1a341fc7ee7d9b8b00b6168b35a6a844d90431749d8ca694174c52c41e11763f","urls":["bzz-raw://4fb6b13953539b99262cb299961fb8ff8a020de79b12f76c63decf33ff9d5103","dweb:/ipfs/QmQ3bnkQJgD2s6xpapThCPTSMbDREokVEiM7extwQgfrv7"],"license":"MPL-2.0"},"lib/CMTAT/contracts/library/ERC1404ExtendInterfaceId.sol":{"keccak256":"0xe5f6f08d319d27f20989936460d3947eed5fdcb470f80e920f4fb09ccc7e1e87","urls":["bzz-raw://cb654fe37c2bc6c765c67c5f94a769580312d1d4109c50262677ac406362f91e","dweb:/ipfs/Qmc8ZFVANCmULNozM2wFUSGKXBgUHR5bpDC3ZVjV4XoEv7"],"license":"MPL-2.0"},"lib/CMTAT/contracts/library/RuleEngineInterfaceId.sol":{"keccak256":"0x759990208069b5a0862a255eff790d52d1d64bbb6c334705fc12414936825692","urls":["bzz-raw://0bce1c17cbbddac4bf123f602dc980246e5bec724f5ed3107e148548b930e124","dweb:/ipfs/QmRZUxmRN9ji9UYueD6knhnz2nSsDRZgRTX74uenGczVjA"],"license":"MPL-2.0"},"lib/openzeppelin-contracts/contracts/access/AccessControl.sol":{"keccak256":"0x4686ec784d75f95beaf2bf5b5f26e5f946d4c864aaee9c3c62bdc18381f5e017","urls":["bzz-raw://26710ca191913f3c9df542079c4a6dcff02968e92d4f7357daefef9fbe72a19c","dweb:/ipfs/QmanHbeWuBbVEqXySHa1zhm2rExjYpChDBubBaJNTCa2JB"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/access/IAccessControl.sol":{"keccak256":"0xbff9f59c84e5337689161ce7641c0ef8e872d6a7536fbc1f5133f128887aba3c","urls":["bzz-raw://b308f882e796f7b79c9502deacb0a62983035c6f6f4e962b319ba6a1f4a77d3d","dweb:/ipfs/QmaWCW7ahEQqFjwhSUhV7Ae7WhfNvzSpE7DQ58hvEooqPL"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/access/extensions/AccessControlEnumerable.sol":{"keccak256":"0xbae499c224def4d252ee766288a178769529a16ab26670a2761fd405b98c2ba0","urls":["bzz-raw://7bc24842026d827fa4a9091b4464846c280f86162521a7c16e6388ce11fced8d","dweb:/ipfs/QmRtwbSbzb66Wt8Y37ocVLqckdxuSkZGNF5bHwhj9AAS5L"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/access/extensions/IAccessControlEnumerable.sol":{"keccak256":"0xbc97d8c0d67d4d7eba1e662f0a8671712ace9e060ab03af547c4bb321aec1d8c","urls":["bzz-raw://890d156f50630d52c7be57d7e0499132d6fd92b2e1365b81531f4463b3304377","dweb:/ipfs/QmUHe9uL1ciePH2pQg7wdrgTAFRZWjcpBEAg8V1UNtXutd"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/interfaces/IERC165.sol":{"keccak256":"0x0afcb7e740d1537b252cb2676f600465ce6938398569f09ba1b9ca240dde2dfc","urls":["bzz-raw://1c299900ac4ec268d4570ecef0d697a3013cd11a6eb74e295ee3fbc945056037","dweb:/ipfs/Qmab9owJoxcA7vJT5XNayCMaUR1qxqj1NDzzisduwaJMcZ"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/metatx/ERC2771Context.sol":{"keccak256":"0x9695d220b99dcf62910533bdf5d40d4cf6a4e04d5b106b6803a80586486dc7f7","urls":["bzz-raw://83b7aecd65882d8953643dce144efe91367082cc01830c9c4ed3c8a4837fb558","dweb:/ipfs/QmQ5HxGavcCKjuhd8buv177qjG6A4kvxx4pZviceKdspdM"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/Arrays.sol":{"keccak256":"0xb3b81029526a4c3acf39e57cc446407141ebce338cc99585942af1340e1a69e0","urls":["bzz-raw://3857ce97e8f7a51ad78ea5419b3386e18fcc8af73b65803eedd8193ab7abc9df","dweb:/ipfs/QmSQi6x2cYsUy76mfMNwuq151bVmh4kAND141kjume51Aq"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/Comparators.sol":{"keccak256":"0x302eecd8cf323b4690e3494a7d960b3cbce077032ab8ef655b323cdd136cec58","urls":["bzz-raw://49ba706f1bc476d68fe6c1fad75517acea4e9e275be0989b548e292eb3a3eacd","dweb:/ipfs/QmeBpvcdGWzWMKTQESUCEhHgnEQYYATVwPxLMxa6vMT7jC"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/Context.sol":{"keccak256":"0x493033a8d1b176a037b2cc6a04dad01a5c157722049bbecf632ca876224dd4b2","urls":["bzz-raw://6a708e8a5bdb1011c2c381c9a5cfd8a9a956d7d0a9dc1bd8bcdaf52f76ef2f12","dweb:/ipfs/Qmax9WHBnVsZP46ZxEMNRQpLQnrdE4dK8LehML1Py8FowF"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/Panic.sol":{"keccak256":"0xf7fe324703a64fc51702311dc51562d5cb1497734f074e4f483bfb6717572d7a","urls":["bzz-raw://c6a5ff4f9fd8649b7ee20800b7fa387d3465bd77cf20c2d1068cd5c98e1ed57a","dweb:/ipfs/QmVSaVJf9FXFhdYEYeCEfjMVHrxDh5qL4CGkxdMWpQCrqG"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/SlotDerivation.sol":{"keccak256":"0x94045fd4f268edf2b2d01ef119268548c320366d6f5294ad30c1b8f9d4f5225f","urls":["bzz-raw://edfda81f426f8948b3834115c21e83c48180e6db0d2a8cd2debb2185ed349337","dweb:/ipfs/QmdYZneFyDAux1BuWQxLAdqtABrGS2k9WYCa7C9dvpKkWv"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol":{"keccak256":"0xcf74f855663ce2ae00ed8352666b7935f6cddea2932fdf2c3ecd30a9b1cd0e97","urls":["bzz-raw://9f660b1f351b757dfe01438e59888f31f33ded3afcf5cb5b0d9bf9aa6f320a8b","dweb:/ipfs/QmarDJ5hZEgBtCmmrVzEZWjub9769eD686jmzb2XpSU1cM"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol":{"keccak256":"0x2d9dc2fe26180f74c11c13663647d38e259e45f95eb88f57b61d2160b0109d3e","urls":["bzz-raw://81233d1f98060113d9922180bb0f14f8335856fe9f339134b09335e9f678c377","dweb:/ipfs/QmWh6R35SarhAn4z2wH8SU456jJSYL2FgucfTFgbHJJN4E"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165Checker.sol":{"keccak256":"0x7c7ad70641a7f8cd44def0857ec97b0e40bfd073b2d6037a5f57ce9527ee9bc5","urls":["bzz-raw://e05c6572dfe769f7aea6f3a8002951cc12d143d980dad29f6c5feedf9408bc14","dweb:/ipfs/QmXM7C8YEptxisZiEefXUrwdXt3zMaCobmkCchxTtDg1oK"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol":{"keccak256":"0x8891738ffe910f0cf2da09566928589bf5d63f4524dd734fd9cedbac3274dd5c","urls":["bzz-raw://971f954442df5c2ef5b5ebf1eb245d7105d9fbacc7386ee5c796df1d45b21617","dweb:/ipfs/QmadRjHbkicwqwwh61raUEapaVEtaLMcYbQZWs9gUkgj3u"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/math/Math.sol":{"keccak256":"0x59973a93b1f983f94e10529f46ca46544a9fec2b5f56fb1390bbe9e0dc79f857","urls":["bzz-raw://c55ef8f0b9719790c2ae6f81d80a59ffb89f2f0abe6bc065585bd79edce058c5","dweb:/ipfs/QmNNmCbX9NjPXKqHJN8R1WC2rNeZSQrPZLd6FF6AKLyH5Y"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol":{"keccak256":"0xc8cae21c9ae4a46e5162ff9bf5b351d6fa6a6eba72d515f3bc1bdfeda7fdf083","urls":["bzz-raw://ce830ebcf28e31643caba318996db3763c36d52cd0f23798ba83c135355d45e9","dweb:/ipfs/QmdGPcvptHN7UBCbUYBbRX3hiRVRFLRwno8b4uga6uFNif"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/structs/EnumerableSet.sol":{"keccak256":"0x5c298e834696707e274a71a224969d36faecd928a8076603210d67d091adb4ae","urls":["bzz-raw://a93fe967b4d55b31157164cbb7e3e1ebaf3535fc1d3f8d0156da7abb9b565d90","dweb:/ipfs/QmXH7nyxwEUeMPFDDmkdUwqxLEcezaSmVyunyMAuck1WqR"],"license":"MIT"},"src/RuleEngineBase.sol":{"keccak256":"0x9edae8ce7df18638cf56b571be18251d4ac4c435844c8cd77d1f7f651623c568","urls":["bzz-raw://9758c7256a994b371c00d9e0098be5d76d9896f2a556208dfb83768d4d4e916b","dweb:/ipfs/QmdZwwiB29tzheoaoRWiJdbbGMH2nM46ojLp7WFjm9D19h"],"license":"MPL-2.0"},"src/deployment/RuleEngine.sol":{"keccak256":"0xa1aa57ac7e2af018dbb8a24b07028f3f6fe0bf7641574f9a579bd3c102654a41","urls":["bzz-raw://a18b877f001ccdd8ca27636b5ce868185f8ce83ef14b5277aedee27a389182e4","dweb:/ipfs/QmYY2dU7dSkvHb5rFgHEqtNxpSaELzgnRCmkdzxWAWwJem"],"license":"MPL-2.0"},"src/interfaces/IERC3643Compliance.sol":{"keccak256":"0xf86e78e8f737795c3762b402b121b0f1822d6b27414aeca08ea6f036cccea07b","urls":["bzz-raw://c795d1b89a1393b2225f6e58c0310d345d78ff534ab028353413c4a5aaf9ecf7","dweb:/ipfs/QmNcJsJzLWzSAV77whMzu7je2Mj2pWoTYYn1z76kqB5mKH"],"license":"MPL-2.0"},"src/interfaces/IRule.sol":{"keccak256":"0x315fd1d0147d40d3cc1ee35f6ddb8c9e25e6e4f96034a285e6f342c59c3cc222","urls":["bzz-raw://5b0ecca410bf89169e5c6393bc4d8fce97a5b3dcf8a2bba02317da85c98f4d0c","dweb:/ipfs/QmeGS5vbFwkmEvJh7s27Q9xW4xGXuUohh2zGPVbgxgjfnu"],"license":"MPL-2.0"},"src/interfaces/IRulesManagementModule.sol":{"keccak256":"0x1be8087ef526f664cf8ba5dd35d4d12fc1880f905e3ba2e553ee02cb7d6506c1","urls":["bzz-raw://545cafd73f2fe9b2b89b37e905057637f58ae2c1da7f3dc33493b515c87a720f","dweb:/ipfs/QmXiTEhLSpN6sj1fiwFT9V6bGD1VCXTqQJiNnXcLrYmW7N"],"license":"MPL-2.0"},"src/modules/ERC2771ModuleStandalone.sol":{"keccak256":"0xecc9aec20ff41c46404f6fcb9bfb0fd5588781fbb4f2fbec351f603a31c178b0","urls":["bzz-raw://48674e77afe59b6c6e6aa8b0d5e370ca58c9a354b5dc294bb3c9f10fbd12a3f3","dweb:/ipfs/QmY3HhbBDqsBvrGBXoRwgVpfSNtiK2XmhaxVpS1F3dSPx9"],"license":"MPL-2.0"},"src/modules/ERC3643ComplianceModule.sol":{"keccak256":"0xdb472471270ea23d4694ca2d2eb107ce668affc9dbe18b5a6eda312ab4800a33","urls":["bzz-raw://6200e990afca50a32fb0a0ad76ffe955447a67cab6e93f64281fc9f14208aab1","dweb:/ipfs/QmXXhRsBq3eGDgBqQwWL5w4Sn6pdTeeXRvpC4jZBDVb6nQ"],"license":"MPL-2.0"},"src/modules/RulesManagementModule.sol":{"keccak256":"0xc9c58e027874658577285de9c9bf9069cd773573a615df7c9644c6c96c69dbc3","urls":["bzz-raw://a6c9ca74cc247b42b9852b35cb4eeadc919d383d7bbd4f4df0739ee6a8bce2c3","dweb:/ipfs/QmfJCvSQjqQrQXYt9JEHiJRZATy1s7q53DKxZC1QsSYMHZ"],"license":"MPL-2.0"},"src/modules/VersionModule.sol":{"keccak256":"0x077070dca24da125a764111d336c0a8fb3445b82d93692ff76b22384b0f4f39f","urls":["bzz-raw://be8df88e667fb2de39d095f0c396d23ed263fdc51a4095fedc89a326540a03ee","dweb:/ipfs/QmYfhhEvNee1XYwCYZCVAKpUUWBd5FP5qvTMYGr6ogC8kA"],"license":"MPL-2.0"},"src/modules/library/ComplianceInterfaceId.sol":{"keccak256":"0xa0f15ca7f9e0fa8ccb854ea2bd812f220c68c280682b56e8d1a437ddba4b6d1f","urls":["bzz-raw://1e01a79b4a2110a401c3d2fbead97844f7428d6dc6603dccf795d42dbc142786","dweb:/ipfs/QmV88ZcDHTU33oXNLFTshUBZ7otgcZRN1HXwywda7Fgz9a"],"license":"MPL-2.0"},"src/modules/library/RuleEngineInvariantStorage.sol":{"keccak256":"0x15005e56f8fbf8f9b8a41c4bfed6c842e37be49fa52b0dbb2edc6b08b9e50c2f","urls":["bzz-raw://06c90dd748d060cb1b05de978cb42fd79d9b49a2beb3a479b4e49f8edaba1195","dweb:/ipfs/QmYXEQWrwJkuzWBdi5hjSaM6pWhrNUf2kH2pHX8jRu9dZS"],"license":"MPL-2.0"},"src/modules/library/RuleInterfaceId.sol":{"keccak256":"0x3c57987589d6205e2546d4ce332e944d1667dddfe897087028a95ed804c50882","urls":["bzz-raw://0e1718e500d4cb5cf4441131c57d23da788f2835e9a014e7d1f62dfb6161647a","dweb:/ipfs/QmXY5cjc9Dzrp7ML7DfvDB9zg7t4cene3g4K9AAuDmLLfC"],"license":"MPL-2.0"},"src/modules/library/RulesManagementModuleInvariantStorage.sol":{"keccak256":"0xa6f9109698f169be74c309a1efadd48edffcb0e9585523258477bf07942c8ae6","urls":["bzz-raw://4c28513636b660111b60a7028c9600b30dcfda291a831343d9e27e253b80856a","dweb:/ipfs/QmQVSZ9N6vjPxNnJDTqEuGSWqNdoxHKhzTzP2cvgZpBSzj"],"license":"MPL-2.0"}},"version":1},"id":163} \ No newline at end of file diff --git a/doc/compilation/v3.0.0-rc2/foundry/RuleEngineOwnable.sol/RuleEngineOwnable.json b/doc/compilation/v3.0.0-rc2/foundry/RuleEngineOwnable.sol/RuleEngineOwnable.json deleted file mode 100644 index d2e8c2f3..00000000 --- a/doc/compilation/v3.0.0-rc2/foundry/RuleEngineOwnable.sol/RuleEngineOwnable.json +++ /dev/null @@ -1 +0,0 @@ -{"abi":[{"type":"constructor","inputs":[{"name":"owner_","type":"address","internalType":"address"},{"name":"forwarderIrrevocable","type":"address","internalType":"address"},{"name":"tokenContract","type":"address","internalType":"address"}],"stateMutability":"nonpayable"},{"type":"function","name":"COMPLIANCE_MANAGER_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"RULES_MANAGEMENT_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"addRule","inputs":[{"name":"rule_","type":"address","internalType":"contract IRule"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"bindToken","inputs":[{"name":"token","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"canTransfer","inputs":[{"name":"from","type":"address","internalType":"address"},{"name":"to","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"canTransferFrom","inputs":[{"name":"spender","type":"address","internalType":"address"},{"name":"from","type":"address","internalType":"address"},{"name":"to","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"clearRules","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"containsRule","inputs":[{"name":"rule_","type":"address","internalType":"contract IRule"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"created","inputs":[{"name":"to","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"destroyed","inputs":[{"name":"from","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"detectTransferRestriction","inputs":[{"name":"from","type":"address","internalType":"address"},{"name":"to","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint8","internalType":"uint8"}],"stateMutability":"view"},{"type":"function","name":"detectTransferRestrictionFrom","inputs":[{"name":"spender","type":"address","internalType":"address"},{"name":"from","type":"address","internalType":"address"},{"name":"to","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint8","internalType":"uint8"}],"stateMutability":"view"},{"type":"function","name":"getTokenBound","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"getTokenBounds","inputs":[],"outputs":[{"name":"","type":"address[]","internalType":"address[]"}],"stateMutability":"view"},{"type":"function","name":"isTokenBound","inputs":[{"name":"token","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"isTrustedForwarder","inputs":[{"name":"forwarder","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"messageForTransferRestriction","inputs":[{"name":"restrictionCode","type":"uint8","internalType":"uint8"}],"outputs":[{"name":"","type":"string","internalType":"string"}],"stateMutability":"view"},{"type":"function","name":"owner","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"removeRule","inputs":[{"name":"rule_","type":"address","internalType":"contract IRule"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"renounceOwnership","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"rule","inputs":[{"name":"ruleId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"rules","inputs":[],"outputs":[{"name":"","type":"address[]","internalType":"address[]"}],"stateMutability":"view"},{"type":"function","name":"rulesCount","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"setRules","inputs":[{"name":"rules_","type":"address[]","internalType":"contract IRule[]"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"supportsInterface","inputs":[{"name":"interfaceId","type":"bytes4","internalType":"bytes4"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"transferOwnership","inputs":[{"name":"newOwner","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"transferred","inputs":[{"name":"spender","type":"address","internalType":"address"},{"name":"from","type":"address","internalType":"address"},{"name":"to","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"transferred","inputs":[{"name":"from","type":"address","internalType":"address"},{"name":"to","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"trustedForwarder","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"unbindToken","inputs":[{"name":"token","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"version","inputs":[],"outputs":[{"name":"version_","type":"string","internalType":"string"}],"stateMutability":"view"},{"type":"event","name":"AddRule","inputs":[{"name":"rule","type":"address","indexed":true,"internalType":"contract IRule"}],"anonymous":false},{"type":"event","name":"ClearRules","inputs":[],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"name":"previousOwner","type":"address","indexed":true,"internalType":"address"},{"name":"newOwner","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"RemoveRule","inputs":[{"name":"rule","type":"address","indexed":true,"internalType":"contract IRule"}],"anonymous":false},{"type":"event","name":"TokenBound","inputs":[{"name":"token","type":"address","indexed":false,"internalType":"address"}],"anonymous":false},{"type":"event","name":"TokenUnbound","inputs":[{"name":"token","type":"address","indexed":false,"internalType":"address"}],"anonymous":false},{"type":"error","name":"OwnableInvalidOwner","inputs":[{"name":"owner","type":"address","internalType":"address"}]},{"type":"error","name":"OwnableUnauthorizedAccount","inputs":[{"name":"account","type":"address","internalType":"address"}]},{"type":"error","name":"RuleEngine_AdminWithAddressZeroNotAllowed","inputs":[]},{"type":"error","name":"RuleEngine_ERC3643Compliance_InvalidTokenAddress","inputs":[]},{"type":"error","name":"RuleEngine_ERC3643Compliance_OperationNotSuccessful","inputs":[]},{"type":"error","name":"RuleEngine_ERC3643Compliance_TokenAlreadyBound","inputs":[]},{"type":"error","name":"RuleEngine_ERC3643Compliance_TokenNotBound","inputs":[]},{"type":"error","name":"RuleEngine_ERC3643Compliance_UnauthorizedCaller","inputs":[]},{"type":"error","name":"RuleEngine_RuleInvalidInterface","inputs":[]},{"type":"error","name":"RuleEngine_RulesManagementModule_ArrayIsEmpty","inputs":[]},{"type":"error","name":"RuleEngine_RulesManagementModule_OperationNotSuccessful","inputs":[]},{"type":"error","name":"RuleEngine_RulesManagementModule_RuleAddressZeroNotAllowed","inputs":[]},{"type":"error","name":"RuleEngine_RulesManagementModule_RuleAlreadyExists","inputs":[]},{"type":"error","name":"RuleEngine_RulesManagementModule_RuleDoNotMatch","inputs":[]}],"bytecode":{"object":"0x60a060405234801561000f575f5ffd5b50604051611ad2380380611ad283398101604081905261002e91610237565b6001600160a01b038083166080528390839083908116156100525761005281610093565b50506001600160a01b03811661008157604051631e4fbdf760e01b81525f600482015260240160405180910390fd5b61008a8161014a565b50505050610277565b6001600160a01b0381166100ba576040516301b8831760e71b815260040160405180910390fd5b6100c560028261019b565b156100e35760405163f423354760e01b815260040160405180910390fd5b6100ee6002826101c1565b61010b57604051631b4ddcf360e11b815260040160405180910390fd5b6040516001600160a01b03821681527f2de35142b19ed5a07796cf30791959c592018f70b1d2d7c460eef8ffe713692b9060200160405180910390a150565b600480546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b6001600160a01b0381165f90815260018301602052604081205415155b90505b92915050565b5f6101b8836001600160a01b0384165f81815260018301602052604081205461021557508154600181810184555f8481526020808220909301849055845484825282860190935260409020919091556101bb565b505f6101bb565b80516001600160a01b0381168114610232575f5ffd5b919050565b5f5f5f60608486031215610249575f5ffd5b6102528461021c565b92506102606020850161021c565b915061026e6040850161021c565b90509250925092565b60805161183561029d5f395f81816102da0152818161035a015261138601526118355ff3fe608060405234801561000f575f5ffd5b50600436106101dc575f3560e01c80638baf29b411610109578063d32c7bb51161009e578063e3c4602c1161006e578063e3c4602c14610483578063e46638e614610496578063e54621d2146104a9578063f2fde38b146104b1575f5ffd5b8063d32c7bb514610425578063d4ce14151461044a578063db18af6c1461045d578063df21950f14610470575f5ffd5b80639b11c115116100d95780639b11c115146103db578063b043572e14610402578063b27aef3a1461040a578063bc13eacc1461041d575f5ffd5b80638baf29b4146103915780638d2ea772146103a45780638da5cb5b146103b7578063993e8b95146103c8575f5ffd5b806354fd4d501161017f578063715018a61161014f578063715018a61461033d5780637157797f146103455780637da0a877146103585780637f4ab1dd1461037e575f5ffd5b806354fd4d50146102a0578063572b6c05146102ca5780635f8dead31461030a5780636a3edf281461031d575f5ffd5b80633ff5aa02116101ba5780633ff5aa021461025257806340db3b501461026557806352f6747a1461027857806354e4b9451461028d575f5ffd5b806301ffc9a7146101e057806303c26bcd146102085780633e5af4ca1461023d575b5f5ffd5b6101f36101ee366004611413565b6104c4565b60405190151581526020015b60405180910390f35b61022f7fe5c50d0927e06141e032cb9a67e1d7092dc85c0b0825191f7e1cede60002856881565b6040519081526020016101ff565b61025061024b36600461144e565b61050a565b005b61025061026036600461149c565b610524565b61025061027336600461149c565b610538565b610280610549565b6040516101ff91906114b7565b6101f361029b36600461149c565b610559565b6040805180820190915260058152640332e302e360dc1b60208201525b6040516101ff9190611502565b6101f36102d836600461149c565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0390811691161490565b610250610318366004611537565b610564565b61032561057b565b6040516001600160a01b0390911681526020016101ff565b61025061059d565b6101f361035336600461144e565b6105b0565b7f0000000000000000000000000000000000000000000000000000000000000000610325565b6102bd61038c36600461156f565b6105cd565b61025061039f36600461158a565b6105d8565b6102506103b2366004611537565b6105f0565b6004546001600160a01b0316610325565b6101f36103d636600461149c565b610603565b61022f7fea5f4eb72290e50c32abd6c23e45de3d8300b3286e1cbc2e293114b92e034e5e81565b61025061060f565b6102506104183660046115c8565b61061f565b61022f61074b565b61043861043336600461144e565b610755565b60405160ff90911681526020016101ff565b61043861045836600461158a565b61076b565b61032561046b366004611639565b610781565b61025061047e36600461149c565b6107a3565b61025061049136600461149c565b6107db565b6101f36104a436600461158a565b610849565b610280610862565b6102506104bf36600461149c565b61086e565b5f6104ce826108ad565b806104e957506001600160e01b031982166307f5828d60e41b145b8061050457506001600160e01b031982166301ffc9a760e01b145b92915050565b610512610918565b61051e84848484610948565b50505050565b61052c6109ea565b610535816109f2565b50565b6105406109ea565b61053581610aaa565b60606105545f610b33565b905090565b5f6105048183610b3f565b61056c610918565b6105775f8383610b5f565b5050565b5f5f6105876002610bf8565b11156105985761055460025f610c01565b505f90565b6105a5610c0c565b6105ae5f610c6a565b565b5f806105be86868686610755565b60ff161490505b949350505050565b606061050482610cbb565b6105e0610918565b6105eb838383610b5f565b505050565b6105f8610918565b610577825f83610b5f565b5f610504600283610b3f565b6106176109ea565b6105ae610e05565b6106276109ea565b5f819003610648576040516359203cb960e01b815260040160405180910390fd5b5f6106525f610bf8565b111561066057610660610e05565b5f5b818110156105eb5761069983838381811061067f5761067f611650565b9050602002016020810190610694919061149c565b610e36565b6106ca8383838181106106ae576106ae611650565b90506020020160208101906106c3919061149c565b5f90610e6d565b6106e75760405163f280d16160e01b815260040160405180910390fd5b8282828181106106f9576106f9611650565b905060200201602081019061070e919061149c565b6001600160a01b03167f60305ce6c9104acd0969d358f926bf391174340660aaf5e6215261fd6847bf4660405160405180910390a2600101610662565b5f6105545f610bf8565b5f61076285858585610e81565b95945050505050565b5f610777848484610f4c565b90505b9392505050565b5f61078b5f610bf8565b82101561079c576105045f83610c01565b505f919050565b6107ab6109ea565b6107b55f82610b3f565b6107d257604051632cdc3a4160e21b815260040160405180910390fd5b6105358161100e565b6107e36109ea565b6107ec81610e36565b6107f65f82610e6d565b6108135760405163f280d16160e01b815260040160405180910390fd5b6040516001600160a01b038216907f60305ce6c9104acd0969d358f926bf391174340660aaf5e6215261fd6847bf46905f90a250565b5f8061085685858561076b565b60ff1614949350505050565b60606105546002610b33565b610876610c0c565b6001600160a01b0381166108a457604051631e4fbdf760e01b81525f60048201526024015b60405180910390fd5b61053581610c6a565b5f6001600160e01b031982166320c49ce760e01b14806108dd57506001600160e01b031982166378a8de7d60e01b145b806108f857506001600160e01b03198216630c51264760e21b145b8061050457506001600160e01b03198216637157797f60e01b1492915050565b61092b61092361106b565b600290610b3f565b6105ae5760405163e39b3c8f60e01b815260040160405180910390fd5b5f6109525f610bf8565b90505f5b818110156109e2576109685f82610c01565b604051631f2d7a6560e11b81526001600160a01b03888116600483015287811660248301528681166044830152606482018690529190911690633e5af4ca906084015f604051808303815f87803b1580156109c1575f5ffd5b505af11580156109d3573d5f5f3e3d5ffd5b50505050806001019050610956565b505050505050565b6105ae610c0c565b6001600160a01b038116610a19576040516301b8831760e71b815260040160405180910390fd5b610a24600282610b3f565b15610a425760405163f423354760e01b815260040160405180910390fd5b610a4d600282610e6d565b610a6a57604051631b4ddcf360e11b815260040160405180910390fd5b6040516001600160a01b03821681527f2de35142b19ed5a07796cf30791959c592018f70b1d2d7c460eef8ffe713692b906020015b60405180910390a150565b610ab5600282610b3f565b610ad257604051636a2b488360e11b815260040160405180910390fd5b610add600282611074565b610afa57604051631b4ddcf360e11b815260040160405180910390fd5b6040516001600160a01b03821681527f28a4ca7134a3b3f9aff286e79ad3daadb4a06d1b43d037a3a98bdc074edd9b7a90602001610a9f565b60605f61077a83611088565b6001600160a01b03165f9081526001919091016020526040902054151590565b5f610b695f610bf8565b90505f5b81811015610bf157610b7f5f82610c01565b6040516322ebca6d60e21b81526001600160a01b0387811660048301528681166024830152604482018690529190911690638baf29b4906064015f604051808303815f87803b158015610bd0575f5ffd5b505af1158015610be2573d5f5f3e3d5ffd5b50505050806001019050610b6d565b5050505050565b5f610504825490565b5f61077a83836110e1565b610c1461106b565b6001600160a01b0316610c2f6004546001600160a01b031690565b6001600160a01b0316146105ae57610c4561106b565b60405163118cdaa760e01b81526001600160a01b03909116600482015260240161089b565b600480546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b60605f610cc661074b565b90505f5b81811015610dc957610cdb81610781565b604051633e822efb60e11b815260ff861660048201526001600160a01b039190911690637d045df690602401602060405180830381865afa158015610d22573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d469190611664565b15610dc157610d5481610781565b604051637f4ab1dd60e01b815260ff861660048201526001600160a01b039190911690637f4ab1dd906024015f60405180830381865afa158015610d9a573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526105c59190810190611697565b600101610cca565b505060408051808201909152601881527f556e6b6e6f776e207265737472696374696f6e20636f64650000000000000000602082015292915050565b6040517fdbf61473843cd9be1c9791ce51ef66d0da6c9026d62ba80c1ca433b13fb729b2905f90a16105ae5f611107565b610e3f81611110565b610e5081632497d6cb60e01b61115f565b61053557604051639952e34360e01b815260040160405180910390fd5b5f61077a836001600160a01b03841661117a565b5f5f610e8b61074b565b90505f5b81811015610f40575f610ea182610781565b60405163d32c7bb560e01b81526001600160a01b038a811660048301528981166024830152888116604483015260648201889052919091169063d32c7bb590608401602060405180830381865afa158015610efe573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f22919061174a565b905060ff811615610f375792506105c5915050565b50600101610e8f565b505f9695505050505050565b5f5f610f5661074b565b90505f5b81811015611003575f610f6c82610781565b60405163d4ce141560e01b81526001600160a01b038981166004830152888116602483015260448201889052919091169063d4ce141590606401602060405180830381865afa158015610fc1573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610fe5919061174a565b905060ff811615610ffa57925061077a915050565b50600101610f5a565b505f95945050505050565b6110185f82611074565b6110355760405163f280d16160e01b815260040160405180910390fd5b6040516001600160a01b038216907f6d83315c9718799346b67584ec64301b1457e989c8e35a8e2982a7776c04bfc4905f90a250565b5f6105546111c6565b5f61077a836001600160a01b0384166111d4565b6060815f018054806020026020016040519081016040528092919081815260200182805480156110d557602002820191905f5260205f20905b8154815260200190600101908083116110c1575b50505050509050919050565b5f825f0182815481106110f6576110f6611650565b905f5260205f200154905092915050565b610535816112be565b6001600160a01b0381166111375760405163f9d152fb60e01b815260040160405180910390fd5b6111415f82610b3f565b156105355760405163cc790a4b60e01b815260040160405180910390fd5b5f61116983611317565b801561077a575061077a8383611356565b5f8181526001830160205260408120546111bf57508154600181810184555f848152602080822090930184905584548482528286019093526040902091909155610504565b505f610504565b5f6105545f36816014611377565b5f81815260018301602052604081205480156112ae575f6111f6600183611765565b85549091505f9061120990600190611765565b9050808214611268575f865f01828154811061122757611227611650565b905f5260205f200154905080875f01848154811061124757611247611650565b5f918252602080832090910192909255918252600188019052604090208390555b855486908061127957611279611784565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f905560019350505050610504565b5f915050610504565b5092915050565b5f6112c7825490565b90505f5b8181101561131057826001015f845f0183815481106112ec576112ec611650565b905f5260205f20015481526020019081526020015f205f90558060010190506112cb565b50505f9055565b5f611329826301ffc9a760e01b611356565b1561079c575f80611342846001600160e01b03196113df565b915091508180156105c55750159392505050565b5f5f5f61136385856113df565b915091508180156107625750949350505050565b90508082101580156113b157507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031633145b156113d7576113c436828403815f611798565b6113cd916117bf565b60601c9250505090565b339250505090565b6301ffc9a760e01b5f818152600483905290819060208260248188617530fa92505f511515601f3d11169150509250929050565b5f60208284031215611423575f5ffd5b81356001600160e01b03198116811461077a575f5ffd5b6001600160a01b0381168114610535575f5ffd5b5f5f5f5f60808587031215611461575f5ffd5b843561146c8161143a565b9350602085013561147c8161143a565b9250604085013561148c8161143a565b9396929550929360600135925050565b5f602082840312156114ac575f5ffd5b813561077a8161143a565b602080825282518282018190525f918401906040840190835b818110156114f75783516001600160a01b03168352602093840193909201916001016114d0565b509095945050505050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b5f5f60408385031215611548575f5ffd5b82356115538161143a565b946020939093013593505050565b60ff81168114610535575f5ffd5b5f6020828403121561157f575f5ffd5b813561077a81611561565b5f5f5f6060848603121561159c575f5ffd5b83356115a78161143a565b925060208401356115b78161143a565b929592945050506040919091013590565b5f5f602083850312156115d9575f5ffd5b823567ffffffffffffffff8111156115ef575f5ffd5b8301601f810185136115ff575f5ffd5b803567ffffffffffffffff811115611615575f5ffd5b8560208260051b8401011115611629575f5ffd5b6020919091019590945092505050565b5f60208284031215611649575f5ffd5b5035919050565b634e487b7160e01b5f52603260045260245ffd5b5f60208284031215611674575f5ffd5b8151801515811461077a575f5ffd5b634e487b7160e01b5f52604160045260245ffd5b5f602082840312156116a7575f5ffd5b815167ffffffffffffffff8111156116bd575f5ffd5b8201601f810184136116cd575f5ffd5b805167ffffffffffffffff8111156116e7576116e7611683565b604051601f8201601f19908116603f0116810167ffffffffffffffff8111828210171561171657611716611683565b60405281815282820160200186101561172d575f5ffd5b8160208401602083015e5f91810160200191909152949350505050565b5f6020828403121561175a575f5ffd5b815161077a81611561565b8181038181111561050457634e487b7160e01b5f52601160045260245ffd5b634e487b7160e01b5f52603160045260245ffd5b5f5f858511156117a6575f5ffd5b838611156117b2575f5ffd5b5050820193919092039150565b80356bffffffffffffffffffffffff1981169060148410156112b7576bffffffffffffffffffffffff1960149490940360031b84901b169092169291505056fea26469706673582212205a996d82474883c2a78dc00fe976f819f1cf115270e41b1abc3e59e3917604d364736f6c63430008220033","sourceMap":"356:1683:164:-:0;;;684:180;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;1542:37:135;;;;;850:6:164;;797:20;;819:13;;956:27:162;::::1;::::0;952:83:::1;;999:25;1010:13:::0;999:10:::1;:25::i;:::-;-1:-1:-1::0;;;;;;;1273:26:128;;1269:95;;1322:31;;-1:-1:-1;;;1322:31:128;;1350:1;1322:31;;;725:51:231;698:18;;1322:31:128;;;;;;;1269:95;1373:32;1392:12;1373:18;:32::i;:::-;1225:187;684:180:164;;;356:1683;;3688:459:186;-1:-1:-1;;;;;3750:19:186;;3742:80;;;;-1:-1:-1;;;3742:80:186;;;;;;;;;;;;3841:28;:12;3863:5;3841:21;:28::i;:::-;3840:29;3832:88;;;;-1:-1:-1;;;3832:88:186;;;;;;;;;;;;4029:23;:12;4046:5;4029:16;:23::i;:::-;4021:87;;;;-1:-1:-1;;;4021:87:186;;;;;;;;;;;;4123:17;;-1:-1:-1;;;;;743:32:231;;725:51;;4123:17:186;;713:2:231;698:18;4123:17:186;;;;;;;3688:459;:::o;2912:187:128:-;3004:6;;;-1:-1:-1;;;;;3020:17:128;;;-1:-1:-1;;;;;;3020:17:128;;;;;;;3052:40;;3004:6;;;3020:17;3004:6;;3052:40;;2985:16;;3052:40;2975:124;2912:187;:::o;16041:165:158:-;-1:-1:-1;;;;;16174:23:158;;16121:4;5238:21;;;:14;;;:21;;;;;;:26;;16144:55;16137:62;;16041:165;;;;;:::o;15089:150::-;15159:4;15182:50;15187:3;-1:-1:-1;;;;;15207:23:158;;2601:4;5238:21;;;:14;;;:21;;;;;;2617:321;;-1:-1:-1;2659:23:158;;;;;;;;:11;:23;;;;;;;;;;;;;2841:18;;2817:21;;;:14;;;:21;;;;;;:42;;;;2873:11;;2617:321;-1:-1:-1;2922:5:158;2915:12;;14:177:231;93:13;;-1:-1:-1;;;;;135:31:231;;125:42;;115:70;;181:1;178;171:12;115:70;14:177;;;:::o;196:378::-;284:6;292;300;353:2;341:9;332:7;328:23;324:32;321:52;;;369:1;366;359:12;321:52;392:40;422:9;392:40;:::i;:::-;382:50;;451:49;496:2;485:9;481:18;451:49;:::i;:::-;441:59;;519:49;564:2;553:9;549:18;519:49;:::i;:::-;509:59;;196:378;;;;;:::o;579:203::-;356:1683:164;;;;;;;;;;;;;;;;;;;;;;","linkReferences":{}},"deployedBytecode":{"object":"0x608060405234801561000f575f5ffd5b50600436106101dc575f3560e01c80638baf29b411610109578063d32c7bb51161009e578063e3c4602c1161006e578063e3c4602c14610483578063e46638e614610496578063e54621d2146104a9578063f2fde38b146104b1575f5ffd5b8063d32c7bb514610425578063d4ce14151461044a578063db18af6c1461045d578063df21950f14610470575f5ffd5b80639b11c115116100d95780639b11c115146103db578063b043572e14610402578063b27aef3a1461040a578063bc13eacc1461041d575f5ffd5b80638baf29b4146103915780638d2ea772146103a45780638da5cb5b146103b7578063993e8b95146103c8575f5ffd5b806354fd4d501161017f578063715018a61161014f578063715018a61461033d5780637157797f146103455780637da0a877146103585780637f4ab1dd1461037e575f5ffd5b806354fd4d50146102a0578063572b6c05146102ca5780635f8dead31461030a5780636a3edf281461031d575f5ffd5b80633ff5aa02116101ba5780633ff5aa021461025257806340db3b501461026557806352f6747a1461027857806354e4b9451461028d575f5ffd5b806301ffc9a7146101e057806303c26bcd146102085780633e5af4ca1461023d575b5f5ffd5b6101f36101ee366004611413565b6104c4565b60405190151581526020015b60405180910390f35b61022f7fe5c50d0927e06141e032cb9a67e1d7092dc85c0b0825191f7e1cede60002856881565b6040519081526020016101ff565b61025061024b36600461144e565b61050a565b005b61025061026036600461149c565b610524565b61025061027336600461149c565b610538565b610280610549565b6040516101ff91906114b7565b6101f361029b36600461149c565b610559565b6040805180820190915260058152640332e302e360dc1b60208201525b6040516101ff9190611502565b6101f36102d836600461149c565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0390811691161490565b610250610318366004611537565b610564565b61032561057b565b6040516001600160a01b0390911681526020016101ff565b61025061059d565b6101f361035336600461144e565b6105b0565b7f0000000000000000000000000000000000000000000000000000000000000000610325565b6102bd61038c36600461156f565b6105cd565b61025061039f36600461158a565b6105d8565b6102506103b2366004611537565b6105f0565b6004546001600160a01b0316610325565b6101f36103d636600461149c565b610603565b61022f7fea5f4eb72290e50c32abd6c23e45de3d8300b3286e1cbc2e293114b92e034e5e81565b61025061060f565b6102506104183660046115c8565b61061f565b61022f61074b565b61043861043336600461144e565b610755565b60405160ff90911681526020016101ff565b61043861045836600461158a565b61076b565b61032561046b366004611639565b610781565b61025061047e36600461149c565b6107a3565b61025061049136600461149c565b6107db565b6101f36104a436600461158a565b610849565b610280610862565b6102506104bf36600461149c565b61086e565b5f6104ce826108ad565b806104e957506001600160e01b031982166307f5828d60e41b145b8061050457506001600160e01b031982166301ffc9a760e01b145b92915050565b610512610918565b61051e84848484610948565b50505050565b61052c6109ea565b610535816109f2565b50565b6105406109ea565b61053581610aaa565b60606105545f610b33565b905090565b5f6105048183610b3f565b61056c610918565b6105775f8383610b5f565b5050565b5f5f6105876002610bf8565b11156105985761055460025f610c01565b505f90565b6105a5610c0c565b6105ae5f610c6a565b565b5f806105be86868686610755565b60ff161490505b949350505050565b606061050482610cbb565b6105e0610918565b6105eb838383610b5f565b505050565b6105f8610918565b610577825f83610b5f565b5f610504600283610b3f565b6106176109ea565b6105ae610e05565b6106276109ea565b5f819003610648576040516359203cb960e01b815260040160405180910390fd5b5f6106525f610bf8565b111561066057610660610e05565b5f5b818110156105eb5761069983838381811061067f5761067f611650565b9050602002016020810190610694919061149c565b610e36565b6106ca8383838181106106ae576106ae611650565b90506020020160208101906106c3919061149c565b5f90610e6d565b6106e75760405163f280d16160e01b815260040160405180910390fd5b8282828181106106f9576106f9611650565b905060200201602081019061070e919061149c565b6001600160a01b03167f60305ce6c9104acd0969d358f926bf391174340660aaf5e6215261fd6847bf4660405160405180910390a2600101610662565b5f6105545f610bf8565b5f61076285858585610e81565b95945050505050565b5f610777848484610f4c565b90505b9392505050565b5f61078b5f610bf8565b82101561079c576105045f83610c01565b505f919050565b6107ab6109ea565b6107b55f82610b3f565b6107d257604051632cdc3a4160e21b815260040160405180910390fd5b6105358161100e565b6107e36109ea565b6107ec81610e36565b6107f65f82610e6d565b6108135760405163f280d16160e01b815260040160405180910390fd5b6040516001600160a01b038216907f60305ce6c9104acd0969d358f926bf391174340660aaf5e6215261fd6847bf46905f90a250565b5f8061085685858561076b565b60ff1614949350505050565b60606105546002610b33565b610876610c0c565b6001600160a01b0381166108a457604051631e4fbdf760e01b81525f60048201526024015b60405180910390fd5b61053581610c6a565b5f6001600160e01b031982166320c49ce760e01b14806108dd57506001600160e01b031982166378a8de7d60e01b145b806108f857506001600160e01b03198216630c51264760e21b145b8061050457506001600160e01b03198216637157797f60e01b1492915050565b61092b61092361106b565b600290610b3f565b6105ae5760405163e39b3c8f60e01b815260040160405180910390fd5b5f6109525f610bf8565b90505f5b818110156109e2576109685f82610c01565b604051631f2d7a6560e11b81526001600160a01b03888116600483015287811660248301528681166044830152606482018690529190911690633e5af4ca906084015f604051808303815f87803b1580156109c1575f5ffd5b505af11580156109d3573d5f5f3e3d5ffd5b50505050806001019050610956565b505050505050565b6105ae610c0c565b6001600160a01b038116610a19576040516301b8831760e71b815260040160405180910390fd5b610a24600282610b3f565b15610a425760405163f423354760e01b815260040160405180910390fd5b610a4d600282610e6d565b610a6a57604051631b4ddcf360e11b815260040160405180910390fd5b6040516001600160a01b03821681527f2de35142b19ed5a07796cf30791959c592018f70b1d2d7c460eef8ffe713692b906020015b60405180910390a150565b610ab5600282610b3f565b610ad257604051636a2b488360e11b815260040160405180910390fd5b610add600282611074565b610afa57604051631b4ddcf360e11b815260040160405180910390fd5b6040516001600160a01b03821681527f28a4ca7134a3b3f9aff286e79ad3daadb4a06d1b43d037a3a98bdc074edd9b7a90602001610a9f565b60605f61077a83611088565b6001600160a01b03165f9081526001919091016020526040902054151590565b5f610b695f610bf8565b90505f5b81811015610bf157610b7f5f82610c01565b6040516322ebca6d60e21b81526001600160a01b0387811660048301528681166024830152604482018690529190911690638baf29b4906064015f604051808303815f87803b158015610bd0575f5ffd5b505af1158015610be2573d5f5f3e3d5ffd5b50505050806001019050610b6d565b5050505050565b5f610504825490565b5f61077a83836110e1565b610c1461106b565b6001600160a01b0316610c2f6004546001600160a01b031690565b6001600160a01b0316146105ae57610c4561106b565b60405163118cdaa760e01b81526001600160a01b03909116600482015260240161089b565b600480546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b60605f610cc661074b565b90505f5b81811015610dc957610cdb81610781565b604051633e822efb60e11b815260ff861660048201526001600160a01b039190911690637d045df690602401602060405180830381865afa158015610d22573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d469190611664565b15610dc157610d5481610781565b604051637f4ab1dd60e01b815260ff861660048201526001600160a01b039190911690637f4ab1dd906024015f60405180830381865afa158015610d9a573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526105c59190810190611697565b600101610cca565b505060408051808201909152601881527f556e6b6e6f776e207265737472696374696f6e20636f64650000000000000000602082015292915050565b6040517fdbf61473843cd9be1c9791ce51ef66d0da6c9026d62ba80c1ca433b13fb729b2905f90a16105ae5f611107565b610e3f81611110565b610e5081632497d6cb60e01b61115f565b61053557604051639952e34360e01b815260040160405180910390fd5b5f61077a836001600160a01b03841661117a565b5f5f610e8b61074b565b90505f5b81811015610f40575f610ea182610781565b60405163d32c7bb560e01b81526001600160a01b038a811660048301528981166024830152888116604483015260648201889052919091169063d32c7bb590608401602060405180830381865afa158015610efe573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f22919061174a565b905060ff811615610f375792506105c5915050565b50600101610e8f565b505f9695505050505050565b5f5f610f5661074b565b90505f5b81811015611003575f610f6c82610781565b60405163d4ce141560e01b81526001600160a01b038981166004830152888116602483015260448201889052919091169063d4ce141590606401602060405180830381865afa158015610fc1573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610fe5919061174a565b905060ff811615610ffa57925061077a915050565b50600101610f5a565b505f95945050505050565b6110185f82611074565b6110355760405163f280d16160e01b815260040160405180910390fd5b6040516001600160a01b038216907f6d83315c9718799346b67584ec64301b1457e989c8e35a8e2982a7776c04bfc4905f90a250565b5f6105546111c6565b5f61077a836001600160a01b0384166111d4565b6060815f018054806020026020016040519081016040528092919081815260200182805480156110d557602002820191905f5260205f20905b8154815260200190600101908083116110c1575b50505050509050919050565b5f825f0182815481106110f6576110f6611650565b905f5260205f200154905092915050565b610535816112be565b6001600160a01b0381166111375760405163f9d152fb60e01b815260040160405180910390fd5b6111415f82610b3f565b156105355760405163cc790a4b60e01b815260040160405180910390fd5b5f61116983611317565b801561077a575061077a8383611356565b5f8181526001830160205260408120546111bf57508154600181810184555f848152602080822090930184905584548482528286019093526040902091909155610504565b505f610504565b5f6105545f36816014611377565b5f81815260018301602052604081205480156112ae575f6111f6600183611765565b85549091505f9061120990600190611765565b9050808214611268575f865f01828154811061122757611227611650565b905f5260205f200154905080875f01848154811061124757611247611650565b5f918252602080832090910192909255918252600188019052604090208390555b855486908061127957611279611784565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f905560019350505050610504565b5f915050610504565b5092915050565b5f6112c7825490565b90505f5b8181101561131057826001015f845f0183815481106112ec576112ec611650565b905f5260205f20015481526020019081526020015f205f90558060010190506112cb565b50505f9055565b5f611329826301ffc9a760e01b611356565b1561079c575f80611342846001600160e01b03196113df565b915091508180156105c55750159392505050565b5f5f5f61136385856113df565b915091508180156107625750949350505050565b90508082101580156113b157507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031633145b156113d7576113c436828403815f611798565b6113cd916117bf565b60601c9250505090565b339250505090565b6301ffc9a760e01b5f818152600483905290819060208260248188617530fa92505f511515601f3d11169150509250929050565b5f60208284031215611423575f5ffd5b81356001600160e01b03198116811461077a575f5ffd5b6001600160a01b0381168114610535575f5ffd5b5f5f5f5f60808587031215611461575f5ffd5b843561146c8161143a565b9350602085013561147c8161143a565b9250604085013561148c8161143a565b9396929550929360600135925050565b5f602082840312156114ac575f5ffd5b813561077a8161143a565b602080825282518282018190525f918401906040840190835b818110156114f75783516001600160a01b03168352602093840193909201916001016114d0565b509095945050505050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b5f5f60408385031215611548575f5ffd5b82356115538161143a565b946020939093013593505050565b60ff81168114610535575f5ffd5b5f6020828403121561157f575f5ffd5b813561077a81611561565b5f5f5f6060848603121561159c575f5ffd5b83356115a78161143a565b925060208401356115b78161143a565b929592945050506040919091013590565b5f5f602083850312156115d9575f5ffd5b823567ffffffffffffffff8111156115ef575f5ffd5b8301601f810185136115ff575f5ffd5b803567ffffffffffffffff811115611615575f5ffd5b8560208260051b8401011115611629575f5ffd5b6020919091019590945092505050565b5f60208284031215611649575f5ffd5b5035919050565b634e487b7160e01b5f52603260045260245ffd5b5f60208284031215611674575f5ffd5b8151801515811461077a575f5ffd5b634e487b7160e01b5f52604160045260245ffd5b5f602082840312156116a7575f5ffd5b815167ffffffffffffffff8111156116bd575f5ffd5b8201601f810184136116cd575f5ffd5b805167ffffffffffffffff8111156116e7576116e7611683565b604051601f8201601f19908116603f0116810167ffffffffffffffff8111828210171561171657611716611683565b60405281815282820160200186101561172d575f5ffd5b8160208401602083015e5f91810160200191909152949350505050565b5f6020828403121561175a575f5ffd5b815161077a81611561565b8181038181111561050457634e487b7160e01b5f52601160045260245ffd5b634e487b7160e01b5f52603160045260245ffd5b5f5f858511156117a6575f5ffd5b838611156117b2575f5ffd5b5050820193919092039150565b80356bffffffffffffffffffffffff1981169060148410156112b7576bffffffffffffffffffffffff1960149490940360031b84901b169092169291505056fea26469706673582212205a996d82474883c2a78dc00fe976f819f1cf115270e41b1abc3e59e3917604d364736f6c63430008220033","sourceMap":"356:1683:164:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1091:257:162;;;;;;:::i;:::-;;:::i;:::-;;;470:14:231;;463:22;445:41;;433:2;418:18;1091:257:162;;;;;;;;729:86:186;;779:36;729:86;;;;;643:25:231;;;631:2;616:18;729:86:186;497:177:231;1726:276:161;;;;;;:::i;:::-;;:::i;:::-;;1846:114:186;;;;;;:::i;:::-;;:::i;2223:118::-;;;;;;:::i;:::-;;:::i;4499:136:187:-;;;:::i;:::-;;;;;;;:::i;3804:158::-;;;;;;:::i;:::-;;:::i;692:129:188:-;807:7;;;;;;;;;;;;-1:-1:-1;;;807:7:188;;;;692:129;;;;;;;:::i;1874:137:135:-;;;;;;:::i;:::-;1749:17;-1:-1:-1;;;;;1973:31:135;;;;;;;1874:137;2328:155:161;;;;;;:::i;:::-;;:::i;2564:382:186:-;;;:::i;:::-;;;-1:-1:-1;;;;;3590:32:231;;;3572:51;;3560:2;3545:18;2564:382:186;3426:203:231;2293:101:128;;;:::i;4340:311:161:-;;;;;;:::i;:::-;;:::i;1666:107:135:-;1749:17;1666:107;;3695:240:161;;;;;;:::i;:::-;;:::i;2071:212::-;;;;;;:::i;:::-;;:::i;2528:161::-;;;;;;:::i;:::-;;:::i;1638:85:128:-;1710:6;;-1:-1:-1;;;;;1710:6:128;1638:85;;2386:133:186;;;;;;:::i;:::-;;:::i;1199:82:192:-;;1247:34;1199:82;;2485:117:187;;;:::i;1781:640::-;;;;;;:::i;:::-;;:::i;3608:132::-;;;:::i;3363:282:161:-;;;;;;:::i;:::-;;:::i;:::-;;;5498:4:231;5486:17;;;5468:36;;5456:2;5441:18;3363:282:161;5326:184:231;3065:242:161;;;;;;:::i;:::-;;:::i;4026:409:187:-;;;;;;:::i;:::-;;:::i;3258:234::-;;;;;;:::i;:::-;;:::i;2923:271::-;;;;;;:::i;:::-;;:::i;3999:281:161:-;;;;;;:::i;:::-;;:::i;2991:119:186:-;;;:::i;2543:215:128:-;;;;;;:::i;:::-;;:::i;1091:257:162:-;1167:4;1190:45;1223:11;1190:32;:45::i;:::-;:95;;;-1:-1:-1;;;;;;;1251:34:162;;-1:-1:-1;;;1251:34:162;1190:95;:151;;;-1:-1:-1;;;;;;;1301:40:162;;-1:-1:-1;;;1301:40:162;1190:151;1183:158;1091:257;-1:-1:-1;;1091:257:162:o;1726:276:161:-;1217:18:186;:16;:18::i;:::-;1935:60:161::1;1970:7;1979:4;1985:2;1989:5;1935:34;:60::i;:::-;1726:276:::0;;;;:::o;1846:114:186:-;1302:24;:22;:24::i;:::-;1936:17:::1;1947:5;1936:10;:17::i;:::-;1846:114:::0;:::o;2223:118::-;1302:24;:22;:24::i;:::-;2315:19:::1;2328:5;2315:12;:19::i;4499:136:187:-:0;4578:16;4613:15;:6;:13;:15::i;:::-;4606:22;;4499:136;:::o;3804:158::-;3901:4;3924:31;3901:4;3948:5;3924:15;:31::i;2328:155:161:-;1217:18:186;:16;:18::i;:::-;2441:35:161::1;2462:1;2466:2;2470:5;2441:12;:35::i;:::-;2328:155:::0;;:::o;2564:382:186:-;2627:7;2674:1;2650:21;:12;:19;:21::i;:::-;:25;2646:294;;;2863:18;:12;2879:1;2863:15;:18::i;2646:294::-;-1:-1:-1;2927:1:186;;2564:382::o;2293:101:128:-;1531:13;:11;:13::i;:::-;2357:30:::1;2384:1;2357:18;:30::i;:::-;2293:101::o:0;4340:311:161:-;4521:4;;4548:55;4578:7;4587:4;4593:2;4597:5;4548:29;:55::i;:::-;:96;;;4541:103;;4340:311;;;;;;;:::o;3695:240::-;3845:13;3881:47;3912:15;3881:30;:47::i;2071:212::-;1217:18:186;:16;:18::i;:::-;2247:29:161::1;2260:4;2266:2;2270:5;2247:12;:29::i;:::-;2071:212:::0;;;:::o;2528:161::-;1217:18:186;:16;:18::i;:::-;2645:37:161::1;2658:4;2672:1;2676:5;2645:12;:37::i;2386:133:186:-:0;2461:4;2484:28;:12;2506:5;2484:21;:28::i;2485:117:187:-;643:19;:17;:19::i;:::-;2582:13:::1;:11;:13::i;1781:640::-:0;643:19;:17;:19::i;:::-;1920:1:::1;1903:18:::0;;;1899:103:::1;;1944:47;;-1:-1:-1::0;;;1944:47:187::1;;;;;;;;;;;1899:103;2033:1;2015:15;:6;:13;:15::i;:::-;:19;2011:63;;;2050:13;:11;:13::i;:::-;2088:9;2083:332;2103:17:::0;;::::1;2083:332;;;2141:30;2160:6;;2167:1;2160:9;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;2141:10;:30::i;:::-;2277;2296:6;;2303:1;2296:9;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;2277:6;::::0;:10:::1;:30::i;:::-;2269:98;;;;-1:-1:-1::0;;;2269:98:187::1;;;;;;;;;;;;2394:6;;2401:1;2394:9;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;2386:18:187::1;;;;;;;;;;;2122:3;;2083:332;;3608:132:::0;3692:7;3718:15;:6;:13;:15::i;3363:282:161:-;3554:5;3582:56;3613:7;3622:4;3628:2;3632:5;3582:30;:56::i;:::-;3575:63;3363:282;-1:-1:-1;;;;;3363:282:161:o;3065:242::-;3229:5;3257:43;3284:4;3290:2;3294:5;3257:26;:43::i;:::-;3250:50;;3065:242;;;;;;:::o;4026:409:187:-;4118:7;4150:15;:6;:13;:15::i;:::-;4141:6;:24;4137:292;;;4353:17;:6;4363;4353:9;:17::i;4137:292::-;-1:-1:-1;4416:1:187;;4026:409;-1:-1:-1;4026:409:187:o;3258:234::-;643:19;:17;:19::i;:::-;3374:31:::1;:6;3398:5:::0;3374:15:::1;:31::i;:::-;3366:91;;;;-1:-1:-1::0;;;3366:91:187::1;;;;;;;;;;;;3467:18;3479:5;3467:11;:18::i;2923:271::-:0;643:19;:17;:19::i;:::-;3028:26:::1;3047:5;3028:10;:26::i;:::-;3072;:6;3091:5:::0;3072:10:::1;:26::i;:::-;3064:94;;;;-1:-1:-1::0;;;3064:94:187::1;;;;;;;;;;;;3173:14;::::0;-1:-1:-1;;;;;3173:14:187;::::1;::::0;::::1;::::0;;;::::1;2923:271:::0;:::o;3999:281:161:-;4163:4;;4190:42;4216:4;4222:2;4226:5;4190:25;:42::i;:::-;:83;;;;3999:281;-1:-1:-1;;;;3999:281:161:o;2991:119:186:-;3047:16;3082:21;:12;:19;:21::i;2543:215:128:-;1531:13;:11;:13::i;:::-;-1:-1:-1;;;;;2627:22:128;::::1;2623:91;;2672:31;::::0;-1:-1:-1;;;2672:31:128;;2700:1:::1;2672:31;::::0;::::1;3572:51:231::0;3545:18;;2672:31:128::1;;;;;;;;2623:91;2723:28;2742:8;2723:18;:28::i;7167:427:161:-:0;7252:4;-1:-1:-1;;;;;;7275:61:161;;-1:-1:-1;;;7275:61:161;;:143;;-1:-1:-1;;;;;;;7352:66:161;;-1:-1:-1;;;7352:66:161;7275:143;:227;;;-1:-1:-1;;;;;;;7434:68:161;;-1:-1:-1;;;7434:68:161;7275:227;:312;;;-1:-1:-1;;;;;;;7518:69:161;;-1:-1:-1;;;7518:69:161;7268:319;7167:427;-1:-1:-1;;7167:427:161:o;4153:188:186:-;4217:35;4239:12;:10;:12::i;:::-;4217;;:21;:35::i;:::-;4212:123;;4275:49;;-1:-1:-1;;;4275:49:186;;;;;;;;;;;7278:284:187;7385:19;7407:15;:6;:13;:15::i;:::-;7385:37;-1:-1:-1;7437:9:187;7432:124;7456:11;7452:1;:15;7432:124;;;7494:12;:6;7504:1;7494:9;:12::i;:::-;7488:57;;-1:-1:-1;;;7488:57:187;;-1:-1:-1;;;;;6259:32:231;;;7488:57:187;;;6241:51:231;6328:32;;;6308:18;;;6301:60;6397:32;;;6377:18;;;6370:60;6446:18;;;6439:34;;;7488:31:187;;;;;;;6213:19:231;;7488:57:187;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7469:3;;;;;7432:124;;;;7375:187;7278:284;;;;:::o;1136:72:164:-;1531:13:128;:11;:13::i;3688:459:186:-;-1:-1:-1;;;;;3750:19:186;;3742:80;;;;-1:-1:-1;;;3742:80:186;;;;;;;;;;;;3841:28;:12;3863:5;3841:21;:28::i;:::-;3840:29;3832:88;;;;-1:-1:-1;;;3832:88:186;;;;;;;;;;;;4029:23;:12;4046:5;4029:16;:23::i;:::-;4021:87;;;;-1:-1:-1;;;4021:87:186;;;;;;;;;;;;4123:17;;-1:-1:-1;;;;;3590:32:231;;3572:51;;4123:17:186;;3560:2:231;3545:18;4123:17:186;;;;;;;;3688:459;:::o;3310:372::-;3374:28;:12;3396:5;3374:21;:28::i;:::-;3366:83;;;;-1:-1:-1;;;3366:83:186;;;;;;;;;;;;3558:26;:12;3578:5;3558:19;:26::i;:::-;3550:90;;;;-1:-1:-1;;;3550:90:186;;;;;;;;;;;;3656:19;;-1:-1:-1;;;;;3590:32:231;;3572:51;;3656:19:186;;3560:2:231;3545:18;3656:19:186;3426:203:231;17440:273:158;17503:16;17531:22;17556:19;17564:3;17556:7;:19::i;16041:165::-;-1:-1:-1;;;;;16174:23:158;16121:4;5238:21;;;:14;;;;;:21;;;;;;:26;;;16041:165::o;6464:258:187:-;6554:19;6576:15;:6;:13;:15::i;:::-;6554:37;-1:-1:-1;6606:9:187;6601:115;6625:11;6621:1;:15;6601:115;;;6663:12;:6;6673:1;6663:9;:12::i;:::-;6657:48;;-1:-1:-1;;;6657:48:187;;-1:-1:-1;;;;;6704:32:231;;;6657:48:187;;;6686:51:231;6773:32;;;6753:18;;;6746:60;6822:18;;;6815:34;;;6657:31:187;;;;;;;6659:18:231;;6657:48:187;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6638:3;;;;;6601:115;;;;6544:178;6464:258;;;:::o;16287:115:158:-;16350:7;16376:19;16384:3;5434:18;;5352:107;16744:156;16818:7;16868:22;16872:3;16884:5;16868:3;:22::i;1796:162:128:-;1866:12;:10;:12::i;:::-;-1:-1:-1;;;;;1855:23:128;:7;1710:6;;-1:-1:-1;;;;;1710:6:128;;1638:85;1855:7;-1:-1:-1;;;;;1855:23:128;;1851:101;;1928:12;:10;:12::i;:::-;1901:40;;-1:-1:-1;;;1901:40:128;;-1:-1:-1;;;;;3590:32:231;;;1901:40:128;;;3572:51:231;3545:18;;1901:40:128;3426:203:231;2912:187:128;3004:6;;;-1:-1:-1;;;;;3020:17:128;;;-1:-1:-1;;;;;;3020:17:128;;;;;;;3052:40;;3004:6;;;3020:17;3004:6;;3052:40;;2985:16;;3052:40;2975:124;2912:187;:::o;6166:449:161:-;6260:13;6285:19;6307:12;:10;:12::i;:::-;6285:34;-1:-1:-1;6334:9:161;6329:237;6353:11;6349:1;:15;6329:237;;;6395:7;6400:1;6395:4;:7::i;:::-;6389:64;;-1:-1:-1;;;6389:64:161;;5498:4:231;5486:17;;6389:64:161;;;5468:36:231;-1:-1:-1;;;;;6389:47:161;;;;;;;5441:18:231;;6389:64:161;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;6385:171;;;6486:7;6491:1;6486:4;:7::i;:::-;6480:61;;-1:-1:-1;;;6480:61:161;;5498:4:231;5486:17;;6480:61:161;;;5468:36:231;-1:-1:-1;;;;;6480:44:161;;;;;;;5441:18:231;;6480:61:161;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;6480:61:161;;;;;;;;;;;;:::i;6385:171::-;6366:3;;6329:237;;;-1:-1:-1;;6575:33:161;;;;;;;;;;;;;;;;;;6166:449;-1:-1:-1;;6166:449:161:o;4914:98:187:-;4969:12;;;;;;;4991:14;:6;:12;:14::i;6719:261:161:-;6795:23;6812:5;6795:16;:23::i;:::-;6833:74;6865:5;-1:-1:-1;;;6833:31:161;:74::i;:::-;6828:146;;6930:33;;-1:-1:-1;;;6930:33:161;;;;;;;;;;;15089:150:158;15159:4;15182:50;15187:3;-1:-1:-1;;;;;15207:23:158;;15182:4;:50::i;5314:528:161:-;5475:5;5496:19;5518:12;:10;:12::i;:::-;5496:34;-1:-1:-1;5545:9:161;5540:242;5564:11;5560:1;:15;5540:242;;;5596:17;5622:7;5627:1;5622:4;:7::i;:::-;5616:70;;-1:-1:-1;;;5616:70:161;;-1:-1:-1;;;;;6259:32:231;;;5616:70:161;;;6241:51:231;6328:32;;;6308:18;;;6301:60;6397:32;;;6377:18;;;6370:60;6446:18;;;6439:34;;;5616:44:161;;;;;;;6213:19:231;;5616:70:161;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;5596:90;-1:-1:-1;5704:15:161;;;;5700:72;;5746:11;-1:-1:-1;5739:18:161;;-1:-1:-1;;5739:18:161;5700:72;-1:-1:-1;5577:3:161;;5540:242;;;-1:-1:-1;5804:30:161;5791:44;5314:528;-1:-1:-1;;;;;;5314:528:161:o;4850:458::-;4958:5;4975:19;4997:12;:10;:12::i;:::-;4975:34;-1:-1:-1;5024:9:161;5019:229;5043:11;5039:1;:15;5019:229;;;5075:17;5101:7;5106:1;5101:4;:7::i;:::-;5095:57;;-1:-1:-1;;;5095:57:161;;-1:-1:-1;;;;;6704:32:231;;;5095:57:161;;;6686:51:231;6773:32;;;6753:18;;;6746:60;6822:18;;;6815:34;;;5095:40:161;;;;;;;6659:18:231;;5095:57:161;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;5075:77;-1:-1:-1;5170:15:161;;;;5166:72;;5212:11;-1:-1:-1;5205:18:161;;-1:-1:-1;;5205:18:161;5166:72;-1:-1:-1;5056:3:161;;5019:229;;;-1:-1:-1;5270:30:161;5257:44;4850:458;-1:-1:-1;;;;;4850:458:161:o;5239:277:187:-;5388:29;:6;5410:5;5388:13;:29::i;:::-;5380:97;;;;-1:-1:-1;;;5380:97:187;;;;;;;;;;;;5492:17;;-1:-1:-1;;;;;5492:17:187;;;;;;;;5239:277;:::o;1309:172:164:-;1405:14;1438:36;:34;:36::i;15407:156:158:-;15480:4;15503:53;15511:3;-1:-1:-1;;;;;15531:23:158;;15503:7;:53::i;6459:109::-;6515:16;6550:3;:11;;6543:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6459:109;;;:::o;5801:118::-;5868:7;5894:3;:11;;5906:5;5894:18;;;;;;;;:::i;:::-;;;;;;;;;5887:25;;5801:118;;;;:::o;15877:83::-;15935:18;15942:3;15935:6;:18::i;5593:313:187:-;-1:-1:-1;;;;;5664:21:187;;5660:119;;5708:60;;-1:-1:-1;;;5708:60:187;;;;;;;;;;;5660:119;5792:22;:6;5808:5;5792:15;:22::i;:::-;5788:112;;;5837:52;;-1:-1:-1;;;5837:52:187;;;;;;;;;;;1465:283:153;1552:4;1660:23;1675:7;1660:14;:23::i;:::-;:81;;;;;1687:54;1720:7;1729:11;1687:32;:54::i;2538:406:158:-;2601:4;5238:21;;;:14;;;:21;;;;;;2617:321;;-1:-1:-1;2659:23:158;;;;;;;;:11;:23;;;;;;;;;;;;;2841:18;;2817:21;;;:14;;;:21;;;;;;:42;;;;2873:11;;2617:321;-1:-1:-1;2922:5:158;2915:12;;1624:154:162;1711:14;1744:27;2310:7:135;2354:8;2310:7;3609:2;2409:22;4499:136:187;3112:1368:158;3178:4;3307:21;;;:14;;;:21;;;;;;3343:13;;3339:1135;;3710:18;3731:12;3742:1;3731:8;:12;:::i;:::-;3777:18;;3710:33;;-1:-1:-1;3757:17:158;;3777:22;;3798:1;;3777:22;:::i;:::-;3757:42;;3832:9;3818:10;:23;3814:378;;3861:17;3881:3;:11;;3893:9;3881:22;;;;;;;;:::i;:::-;;;;;;;;;3861:42;;4028:9;4002:3;:11;;4014:10;4002:23;;;;;;;;:::i;:::-;;;;;;;;;;;;:35;;;;4141:25;;;:14;;;:25;;;;;:36;;;3814:378;4270:17;;:3;;:17;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;4373:3;:14;;:21;4388:5;4373:21;;;;;;;;;;;4366:28;;;4416:4;4409:11;;;;;;;3339:1135;4458:5;4451:12;;;;;3339:1135;3184:1296;3112:1368;;;;:::o;4824:237::-;4875:11;4889:12;4897:3;5434:18;;5352:107;4889:12;4875:26;-1:-1:-1;4916:9:158;4911:96;4935:3;4931:1;:7;4911:96;;;4966:3;:14;;:30;4981:3;:11;;4993:1;4981:14;;;;;;;;:::i;:::-;;;;;;;;;4966:30;;;;;;;;;;;4959:37;;;4940:3;;;;;4911:96;;;-1:-1:-1;;5039:11:158;33920:23:140;;2328:155:161:o;719:528:153:-;783:4;976:68;1009:7;-1:-1:-1;;;976:32:153;:68::i;:::-;972:269;;;1061:12;;1093:52;1115:7;-1:-1:-1;;;;;;1093:21:153;:52::i;:::-;1060:85;;;;1166:7;:21;;;;-1:-1:-1;1177:10:153;;1159:28;-1:-1:-1;;;719:528:153:o;4504:238::-;4606:4;4623:12;4637:14;4655:43;4677:7;4686:11;4655:21;:43::i;:::-;4622:76;;;;4715:7;:20;;;;-1:-1:-1;4726:9:153;4708:27;-1:-1:-1;;;;4504:238:153:o;2409:22:135:-;2379:52;;2463:19;2445:14;:37;;:71;;;;-1:-1:-1;1749:17:135;-1:-1:-1;;;;;1973:31:135;2505:10;1973:31;2486:30;2441:272;;;2583:47;:8;2592:36;;;2583:8;;:47;:::i;:::-;2575:56;;;:::i;:::-;2567:65;;2560:72;;;;2248:471;:::o;2441:272::-;735:10:143;2677:25:135;;;;2248:471;:::o;5198:628:153:-;-1:-1:-1;;;5310:12:153;5452:22;;;5494:4;5487:25;;;5310:12;;;5581:4;5310:12;5569:4;5310:12;5554:7;5547:5;5536:50;5525:61;;5740:4;5734:11;5727:19;5720:27;5654:4;5636:16;5633:26;5612:198;5599:211;;5438:382;5198:628;;;;;:::o;14:286:231:-;72:6;125:2;113:9;104:7;100:23;96:32;93:52;;;141:1;138;131:12;93:52;167:23;;-1:-1:-1;;;;;;219:32:231;;209:43;;199:71;;266:1;263;256:12;679:131;-1:-1:-1;;;;;754:31:231;;744:42;;734:70;;800:1;797;790:12;815:650;901:6;909;917;925;978:3;966:9;957:7;953:23;949:33;946:53;;;995:1;992;985:12;946:53;1034:9;1021:23;1053:31;1078:5;1053:31;:::i;:::-;1103:5;-1:-1:-1;1160:2:231;1145:18;;1132:32;1173:33;1132:32;1173:33;:::i;:::-;1225:7;-1:-1:-1;1284:2:231;1269:18;;1256:32;1297:33;1256:32;1297:33;:::i;:::-;815:650;;;;-1:-1:-1;1349:7:231;;1429:2;1414:18;1401:32;;-1:-1:-1;;815:650:231:o;1470:247::-;1529:6;1582:2;1570:9;1561:7;1557:23;1553:32;1550:52;;;1598:1;1595;1588:12;1550:52;1637:9;1624:23;1656:31;1681:5;1656:31;:::i;1722:637::-;1912:2;1924:21;;;1994:13;;1897:18;;;2016:22;;;1864:4;;2095:15;;;2069:2;2054:18;;;1864:4;2138:195;2152:6;2149:1;2146:13;2138:195;;;2217:13;;-1:-1:-1;;;;;2213:39:231;2201:52;;2282:2;2308:15;;;;2273:12;;;;2249:1;2167:9;2138:195;;;-1:-1:-1;2350:3:231;;1722:637;-1:-1:-1;;;;;1722:637:231:o;2631:418::-;2780:2;2769:9;2762:21;2743:4;2812:6;2806:13;2855:6;2850:2;2839:9;2835:18;2828:34;2914:6;2909:2;2901:6;2897:15;2892:2;2881:9;2877:18;2871:50;2970:1;2965:2;2956:6;2945:9;2941:22;2937:31;2930:42;3040:2;3033;3029:7;3024:2;3016:6;3012:15;3008:29;2997:9;2993:45;2989:54;2981:62;;;2631:418;;;;:::o;3054:367::-;3122:6;3130;3183:2;3171:9;3162:7;3158:23;3154:32;3151:52;;;3199:1;3196;3189:12;3151:52;3238:9;3225:23;3257:31;3282:5;3257:31;:::i;:::-;3307:5;3385:2;3370:18;;;;3357:32;;-1:-1:-1;;;3054:367:231:o;3634:114::-;3718:4;3711:5;3707:16;3700:5;3697:27;3687:55;;3738:1;3735;3728:12;3753:243;3810:6;3863:2;3851:9;3842:7;3838:23;3834:32;3831:52;;;3879:1;3876;3869:12;3831:52;3918:9;3905:23;3937:29;3960:5;3937:29;:::i;4001:508::-;4078:6;4086;4094;4147:2;4135:9;4126:7;4122:23;4118:32;4115:52;;;4163:1;4160;4153:12;4115:52;4202:9;4189:23;4221:31;4246:5;4221:31;:::i;:::-;4271:5;-1:-1:-1;4328:2:231;4313:18;;4300:32;4341:33;4300:32;4341:33;:::i;:::-;4001:508;;4393:7;;-1:-1:-1;;;4473:2:231;4458:18;;;;4445:32;;4001:508::o;4514:625::-;4615:6;4623;4676:2;4664:9;4655:7;4651:23;4647:32;4644:52;;;4692:1;4689;4682:12;4644:52;4732:9;4719:23;4765:18;4757:6;4754:30;4751:50;;;4797:1;4794;4787:12;4751:50;4820:22;;4873:4;4865:13;;4861:27;-1:-1:-1;4851:55:231;;4902:1;4899;4892:12;4851:55;4942:2;4929:16;4968:18;4960:6;4957:30;4954:50;;;5000:1;4997;4990:12;4954:50;5053:7;5048:2;5038:6;5035:1;5031:14;5027:2;5023:23;5019:32;5016:45;5013:65;;;5074:1;5071;5064:12;5013:65;5105:2;5097:11;;;;;5127:6;;-1:-1:-1;4514:625:231;-1:-1:-1;;;4514:625:231:o;5515:226::-;5574:6;5627:2;5615:9;5606:7;5602:23;5598:32;5595:52;;;5643:1;5640;5633:12;5595:52;-1:-1:-1;5688:23:231;;5515:226;-1:-1:-1;5515:226:231:o;5878:127::-;5939:10;5934:3;5930:20;5927:1;5920:31;5970:4;5967:1;5960:15;5994:4;5991:1;5984:15;6860:277;6927:6;6980:2;6968:9;6959:7;6955:23;6951:32;6948:52;;;6996:1;6993;6986:12;6948:52;7028:9;7022:16;7081:5;7074:13;7067:21;7060:5;7057:32;7047:60;;7103:1;7100;7093:12;7142:127;7203:10;7198:3;7194:20;7191:1;7184:31;7234:4;7231:1;7224:15;7258:4;7255:1;7248:15;7274:935;7354:6;7407:2;7395:9;7386:7;7382:23;7378:32;7375:52;;;7423:1;7420;7413:12;7375:52;7456:9;7450:16;7489:18;7481:6;7478:30;7475:50;;;7521:1;7518;7511:12;7475:50;7544:22;;7597:4;7589:13;;7585:27;-1:-1:-1;7575:55:231;;7626:1;7623;7616:12;7575:55;7659:2;7653:9;7685:18;7677:6;7674:30;7671:56;;;7707:18;;:::i;:::-;7756:2;7750:9;7848:2;7810:17;;-1:-1:-1;;7806:31:231;;;7839:2;7802:40;7798:54;7786:67;;7883:18;7868:34;;7904:22;;;7865:62;7862:88;;;7930:18;;:::i;:::-;7966:2;7959:22;7990;;;8031:15;;;8048:2;8027:24;8024:37;-1:-1:-1;8021:57:231;;;8074:1;8071;8064:12;8021:57;8123:6;8118:2;8114;8110:11;8105:2;8097:6;8093:15;8087:43;8176:1;8150:19;;;8171:2;8146:28;8139:39;;;;8154:6;7274:935;-1:-1:-1;;;;7274:935:231:o;8214:247::-;8282:6;8335:2;8323:9;8314:7;8310:23;8306:32;8303:52;;;8351:1;8348;8341:12;8303:52;8383:9;8377:16;8402:29;8425:5;8402:29;:::i;8466:225::-;8533:9;;;8554:11;;;8551:134;;;8607:10;8602:3;8598:20;8595:1;8588:31;8642:4;8639:1;8632:15;8670:4;8667:1;8660:15;8696:127;8757:10;8752:3;8748:20;8745:1;8738:31;8788:4;8785:1;8778:15;8812:4;8809:1;8802:15;8828:331;8933:9;8944;8986:8;8974:10;8971:24;8968:44;;;9008:1;9005;8998:12;8968:44;9037:6;9027:8;9024:20;9021:40;;;9057:1;9054;9047:12;9021:40;-1:-1:-1;;9083:23:231;;;9128:25;;;;;-1:-1:-1;8828:331:231:o;9164:374::-;9285:19;;-1:-1:-1;;9322:40:231;;;9382:2;9374:11;;9371:161;;;-1:-1:-1;;9444:2:231;9440:12;;;;9437:1;9433:20;9429:58;;;9421:67;9417:105;;;;9164:374;-1:-1:-1;;9164:374:231:o","linkReferences":{},"immutableReferences":{"55852":[{"start":730,"length":32},{"start":858,"length":32},{"start":4998,"length":32}]}},"methodIdentifiers":{"COMPLIANCE_MANAGER_ROLE()":"03c26bcd","RULES_MANAGEMENT_ROLE()":"9b11c115","addRule(address)":"e3c4602c","bindToken(address)":"3ff5aa02","canTransfer(address,address,uint256)":"e46638e6","canTransferFrom(address,address,address,uint256)":"7157797f","clearRules()":"b043572e","containsRule(address)":"54e4b945","created(address,uint256)":"5f8dead3","destroyed(address,uint256)":"8d2ea772","detectTransferRestriction(address,address,uint256)":"d4ce1415","detectTransferRestrictionFrom(address,address,address,uint256)":"d32c7bb5","getTokenBound()":"6a3edf28","getTokenBounds()":"e54621d2","isTokenBound(address)":"993e8b95","isTrustedForwarder(address)":"572b6c05","messageForTransferRestriction(uint8)":"7f4ab1dd","owner()":"8da5cb5b","removeRule(address)":"df21950f","renounceOwnership()":"715018a6","rule(uint256)":"db18af6c","rules()":"52f6747a","rulesCount()":"bc13eacc","setRules(address[])":"b27aef3a","supportsInterface(bytes4)":"01ffc9a7","transferOwnership(address)":"f2fde38b","transferred(address,address,address,uint256)":"3e5af4ca","transferred(address,address,uint256)":"8baf29b4","trustedForwarder()":"7da0a877","unbindToken(address)":"40db3b50","version()":"54fd4d50"},"rawMetadata":"{\"compiler\":{\"version\":\"0.8.34+commit.80d5c536\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"forwarderIrrevocable\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenContract\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"OwnableInvalidOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"OwnableUnauthorizedAccount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_AdminWithAddressZeroNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_ERC3643Compliance_InvalidTokenAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_ERC3643Compliance_OperationNotSuccessful\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_ERC3643Compliance_TokenAlreadyBound\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_ERC3643Compliance_TokenNotBound\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_ERC3643Compliance_UnauthorizedCaller\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_RuleInvalidInterface\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_RulesManagementModule_ArrayIsEmpty\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_RulesManagementModule_OperationNotSuccessful\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_RulesManagementModule_RuleAddressZeroNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_RulesManagementModule_RuleAlreadyExists\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_RulesManagementModule_RuleDoNotMatch\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract IRule\",\"name\":\"rule\",\"type\":\"address\"}],\"name\":\"AddRule\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"ClearRules\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract IRule\",\"name\":\"rule\",\"type\":\"address\"}],\"name\":\"RemoveRule\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"TokenBound\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"TokenUnbound\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"COMPLIANCE_MANAGER_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"RULES_MANAGEMENT_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IRule\",\"name\":\"rule_\",\"type\":\"address\"}],\"name\":\"addRule\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"bindToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"canTransfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"canTransferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"clearRules\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IRule\",\"name\":\"rule_\",\"type\":\"address\"}],\"name\":\"containsRule\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"created\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"destroyed\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"detectTransferRestriction\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"detectTransferRestrictionFrom\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTokenBound\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTokenBounds\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"isTokenBound\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"}],\"name\":\"isTrustedForwarder\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"restrictionCode\",\"type\":\"uint8\"}],\"name\":\"messageForTransferRestriction\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IRule\",\"name\":\"rule_\",\"type\":\"address\"}],\"name\":\"removeRule\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"ruleId\",\"type\":\"uint256\"}],\"name\":\"rule\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"rules\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"rulesCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IRule[]\",\"name\":\"rules_\",\"type\":\"address[]\"}],\"name\":\"setRules\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"transferred\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"transferred\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"trustedForwarder\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"unbindToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"version_\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"OwnableInvalidOwner(address)\":[{\"details\":\"The owner is not a valid owner account. (eg. `address(0)`)\"}],\"OwnableUnauthorizedAccount(address)\":[{\"details\":\"The caller account is not authorized to perform an operation.\"}]},\"events\":{\"AddRule(address)\":{\"params\":{\"rule\":\"The address of the rule contract that was added.\"}},\"RemoveRule(address)\":{\"params\":{\"rule\":\"The address of the rule contract that was removed.\"}},\"TokenBound(address)\":{\"params\":{\"token\":\"The address of the token that was bound.\"}},\"TokenUnbound(address)\":{\"params\":{\"token\":\"The address of the token that was unbound.\"}}},\"kind\":\"dev\",\"methods\":{\"addRule(address)\":{\"details\":\"No on-chain maximum number of rules is enforced. Adding too many rules can increase transfer-time gas usage because rule checks are linear in rule count. Security convention: do not grant {RULES_MANAGEMENT_ROLE} to rule contracts.\",\"params\":{\"rule_\":\"The IRule contract to add.\"}},\"bindToken(address)\":{\"details\":\"Operator warning: \\\"multi-tenant\\\" means one RuleEngine is shared by multiple token contracts. In that setup, bind only tokens that are equally trusted and governed together.\",\"params\":{\"token\":\"The address of the token to bind.\"}},\"canTransfer(address,address,uint256)\":{\"details\":\"Don't check the balance and the user's right (access control)\"},\"canTransferFrom(address,address,address,uint256)\":{\"details\":\"Does not check balances or access rights (Access Control).\",\"params\":{\"from\":\"The source address.\",\"spender\":\"The address performing the transfer.\",\"to\":\"The destination address.\",\"value\":\"The number of tokens to transfer.\"},\"returns\":{\"_0\":\"isCompliant True if the transfer complies with policy.\"}},\"clearRules()\":{\"details\":\"After calling this function, no rules will remain set. Developers should keep in mind that this function has an unbounded cost and using it may render the function uncallable if the set grows to the point where clearing it consumes too much gas to fit in a block.\"},\"constructor\":{\"params\":{\"forwarderIrrevocable\":\"Address of the forwarder, required for the gasless support\",\"owner_\":\"Address of the contract owner (ERC-173)\",\"tokenContract\":\"Address of the token contract to bind (can be zero address)\"}},\"containsRule(address)\":{\"details\":\"Complexity: O(1).\",\"params\":{\"rule_\":\"The IRule contract to check for membership.\"},\"returns\":{\"_0\":\"True if the rule is present, false otherwise.\"}},\"created(address,uint256)\":{\"details\":\"Called by the token contract when new tokens are issued to an account. Reverts if the minting does not comply with the rules.\",\"params\":{\"to\":\"The address receiving the minted tokens.\",\"value\":\"The number of tokens created.\"}},\"destroyed(address,uint256)\":{\"details\":\"Called by the token contract when tokens are redeemed or burned. Reverts if the burning does not comply with the rules.\",\"params\":{\"from\":\"The address whose tokens are being destroyed.\",\"value\":\"The number of tokens destroyed.\"}},\"detectTransferRestriction(address,address,uint256)\":{\"params\":{\"from\":\"the origin address\",\"to\":\"the destination address\",\"value\":\"to transfer\"},\"returns\":{\"_0\":\"The restricion code or REJECTED_CODE_BASE.TRANSFER_OK (0) if the transfer is valid\"}},\"detectTransferRestrictionFrom(address,address,address,uint256)\":{\"details\":\" See {ERC-1404} Add an additionnal argument `spender` This function is where an issuer enforces the restriction logic of their token transfers. Some examples of this might include: - checking if the token recipient is whitelisted, - checking if a sender's tokens are frozen in a lock-up period, etc.\",\"returns\":{\"_0\":\"uint8 restricted code, 0 means the transfer is authorized\"}},\"getTokenBound()\":{\"details\":\"If multiple tokens are supported, consider using getTokenBounds().\",\"returns\":{\"_0\":\"The address of the currently bound token.\"}},\"getTokenBounds()\":{\"details\":\"This is a view-only function and does not modify state. This function is not part of the original ERC-3643 specification This operation will copy the entire storage to memory, which can be quite expensive. This is designed to mostly be used by view accessors that are queried without any gas fees.\",\"returns\":{\"_0\":\"An array of addresses of bound token contracts.\"}},\"isTokenBound(address)\":{\"details\":\"Complexity: O(1). Note that there are no guarantees on the ordering of values inside the array, and it may change when more values are added or removed.\",\"params\":{\"token\":\"The token address to verify.\"},\"returns\":{\"_0\":\"True if the token is bound, false otherwise.\"}},\"isTrustedForwarder(address)\":{\"details\":\"Indicates whether any particular address is the trusted forwarder.\"},\"messageForTransferRestriction(uint8)\":{\"details\":\"See {ERC-1404} This function is effectively an accessor for the \\\"message\\\", a human-readable explanation as to why a transaction is restricted. \"},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"removeRule(address)\":{\"details\":\"Reverts if the provided rule is not found or does not match the stored rule at its index. Complexity: O(1).\",\"params\":{\"rule_\":\"The IRule contract to remove.\"}},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.\"},\"rule(uint256)\":{\"details\":\"Reverts if `ruleId` is out of bounds. Complexity: O(1). Note that there are no guarantees on the ordering of values inside the array, and it may change when more values are added or removed.\",\"params\":{\"ruleId\":\"The index of the desired rule in the array.\"},\"returns\":{\"_0\":\"The address of the corresponding IRule contract, return the `zero address` is out of bounds.\"}},\"rules()\":{\"details\":\"This is a view-only function that does not modify state. This operation will copy the entire storage to memory, which can be quite expensive. This is designed to mostly be used by view accessors that are queried without any gas fees.\",\"returns\":{\"_0\":\"An array of all active rule contract addresses.\"}},\"rulesCount()\":{\"details\":\"Equivalent to the length of the internal rules array. Complexity: O(1)\",\"returns\":{\"_0\":\"The number of active rules.\"}},\"setRules(address[])\":{\"details\":\"Replaces the entire rule set atomically. Reverts if `rules_` is empty. Use {clearRules} to remove all rules explicitly. To transition from one non-empty set to another without an enforcement gap, call this function directly with the new set. No on-chain maximum number of rules is enforced. Operators are responsible for keeping the rule set size compatible with the target chain gas limits. Security convention: rule contracts should be treated as trusted business logic, but should not also be granted {RULES_MANAGEMENT_ROLE}.\",\"params\":{\"rules_\":\"The array of addresses representing the new rules to be set.\"}},\"supportsInterface(bytes4)\":{\"details\":\"Returns true if this contract implements the interface defined by `interfaceId`. See the corresponding https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section] to learn more about how these ids are created. This function call must use less than 30 000 gas.\"},\"transferOwnership(address)\":{\"details\":\"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner.\"},\"transferred(address,address,address,uint256)\":{\"details\":\" Must revert if the transfer is invalid Same name as ERC-3643 but with one supplementary argument `spender` This function can be used to update state variables of the RuleEngine contract This function can be called ONLY by the token contract bound to the RuleEngine\",\"params\":{\"from\":\"token holder address\",\"spender\":\"spender address (sender)\",\"to\":\"receiver address\",\"value\":\"value of tokens involved in the transfer\"}},\"transferred(address,address,uint256)\":{\"details\":\" This function can be used to update state variables of the compliance contract This function can be called ONLY by the token contract bound to the compliance\",\"params\":{\"from\":\"The address of the sender\",\"to\":\"The address of the receiver\",\"value\":\"value of tokens involved in the transfer\"}},\"trustedForwarder()\":{\"details\":\"Returns the address of the trusted forwarder.\"},\"unbindToken(address)\":{\"details\":\"Operator warning: unbinding is an administrative operation and does not erase any state already stored by external rule contracts in a previously shared (\\\"multi-tenant\\\") setup.\",\"params\":{\"token\":\"The address of the token to unbind.\"}},\"version()\":{\"details\":\"This value is useful to know which smart contract version has been used\",\"returns\":{\"version_\":\"A string representing the version of the token implementation (e.g., \\\"1.0.0\\\").\"}}},\"title\":\"Implementation of a ruleEngine with ERC-173 Ownable access control\",\"version\":1},\"userdoc\":{\"events\":{\"AddRule(address)\":{\"notice\":\"Emitted when a new rule is added to the rule set.\"},\"ClearRules()\":{\"notice\":\"Emitted when all rules are cleared from the rule set.\"},\"RemoveRule(address)\":{\"notice\":\"Emitted when a rule is removed from the rule set.\"},\"TokenBound(address)\":{\"notice\":\"Emitted when a token is successfully bound to the compliance contract.\"},\"TokenUnbound(address)\":{\"notice\":\"Emitted when a token is successfully unbound from the compliance contract.\"}},\"kind\":\"user\",\"methods\":{\"RULES_MANAGEMENT_ROLE()\":{\"notice\":\"Role to manage the ruleEngine\"},\"addRule(address)\":{\"notice\":\"Adds a new rule to the current rule set.\"},\"bindToken(address)\":{\"notice\":\"Associates a token contract with this compliance contract.\"},\"canTransfer(address,address,uint256)\":{\"notice\":\"Returns true if the transfer is valid, and false otherwise.\"},\"canTransferFrom(address,address,address,uint256)\":{\"notice\":\"Checks if `spender` can transfer `value` tokens from `from` to `to` under compliance rules.\"},\"clearRules()\":{\"notice\":\"Removes all configured rules.\"},\"containsRule(address)\":{\"notice\":\"Checks whether a specific rule is currently configured.\"},\"created(address,uint256)\":{\"notice\":\"Updates the compliance contract state when tokens are created (minted).\"},\"destroyed(address,uint256)\":{\"notice\":\"Updates the compliance contract state when tokens are destroyed (burned).\"},\"detectTransferRestriction(address,address,uint256)\":{\"notice\":\"Go through all the rule to know if a restriction exists on the transfer\"},\"detectTransferRestrictionFrom(address,address,address,uint256)\":{\"notice\":\"Returns a uint8 code to indicate if a transfer is restricted or not\"},\"getTokenBound()\":{\"notice\":\"Returns the single token currently bound to this compliance contract.\"},\"getTokenBounds()\":{\"notice\":\"Returns all tokens currently bound to this compliance contract.\"},\"isTokenBound(address)\":{\"notice\":\"Checks whether a token is currently bound to this compliance contract.\"},\"removeRule(address)\":{\"notice\":\"Removes a specific rule from the current rule set.\"},\"rule(uint256)\":{\"notice\":\"Retrieves the rule address at a specific index.\"},\"rules()\":{\"notice\":\"Returns the full list of currently configured rules.\"},\"rulesCount()\":{\"notice\":\"Returns the total number of currently configured rules.\"},\"setRules(address[])\":{\"notice\":\"Defines the rules for the rule engine.\"},\"transferred(address,address,address,uint256)\":{\"notice\":\"Function called whenever tokens are transferred from one wallet to another\"},\"transferred(address,address,uint256)\":{\"notice\":\"Function called whenever tokens are transferred from one wallet to another\"},\"unbindToken(address)\":{\"notice\":\"Removes the association of a token contract from this compliance contract.\"},\"version()\":{\"notice\":\"Returns the current version of the token contract.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/deployment/RuleEngineOwnable.sol\":\"RuleEngineOwnable\"},\"evmVersion\":\"prague\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[\":@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\":@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\":CMTAT/=lib/CMTAT/contracts/\",\":CMTATv3.0.0/=lib/CMTATv3.0.0/contracts/\",\":erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/\",\":forge-std/=lib/forge-std/src/\",\":halmos-cheatcodes/=lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/\",\":openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\":openzeppelin-contracts/=lib/openzeppelin-contracts/\"]},\"sources\":{\"lib/CMTAT/contracts/interfaces/engine/IRuleEngine.sol\":{\"keccak256\":\"0x524a2cf2214a82fb96e97a18a94956fee68a419ecd6b2dc841aa1105f336c3f1\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://9c4728d80b6678101586515c0308c63bcba2a78b0a3c12d37b522d59f3175a01\",\"dweb:/ipfs/QmYP9SPbe2hB69jKkSg43qkz1HVxBayKrG14i9f6hx7hh8\"]},\"lib/CMTAT/contracts/interfaces/technical/IERC5679.sol\":{\"keccak256\":\"0xcc6f2e79d1d9eabcf4c7ffcbd85c0de31bb2b3cdf17eb847dffb7c2d2a8c4695\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://d618bc2be7c6bc167037fe57ca648523c671c61791f3f0c65965ab7139d6dc33\",\"dweb:/ipfs/QmSrCKWFjpg1SQ7v2k3vRyWpcU9dB6Pbk167R4oAzUc2Te\"]},\"lib/CMTAT/contracts/interfaces/tokenization/IERC3643Partial.sol\":{\"keccak256\":\"0x1707381177447b1a398c443c7e753942df0c5d4633e80d2864db472e89e43dc0\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://c4281d98847629b67222332bea67f336623937758be908ee9ca1aa40b3abe19d\",\"dweb:/ipfs/QmZQBruKJH3sStjBmCb28rxRkUkZ4EFsDCi8WZ7Y85spxS\"]},\"lib/CMTAT/contracts/interfaces/tokenization/draft-IERC1404.sol\":{\"keccak256\":\"0x17fb1f64b546fd882331dffbd8c7f4e53c51738b9e2621a0dcfcf30e64d8b66e\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://c35fe277d5d99a0943293b5da5622947095e6b719af35fda9ef2c714a7879a4b\",\"dweb:/ipfs/QmRV5q3XvjJE8sxJJBpEkwk1qyz3r4McH2BdX1v2ZxZGZh\"]},\"lib/CMTAT/contracts/interfaces/tokenization/draft-IERC7551.sol\":{\"keccak256\":\"0x709074d96bd5d7aa07d2ba3a1c9a99ae0fd4361f7322b528b42f3b83c5dcb984\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://ca67a06011b746b55bf2465988dc10a4e6371e40b5108c54531f03e938bda865\",\"dweb:/ipfs/QmbjFyDAJsUXywqzU2s96pFqFpC5DLKdfa8WjMBtQPhKGE\"]},\"lib/CMTAT/contracts/interfaces/tokenization/draft-IERC7943.sol\":{\"keccak256\":\"0x1a341fc7ee7d9b8b00b6168b35a6a844d90431749d8ca694174c52c41e11763f\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://4fb6b13953539b99262cb299961fb8ff8a020de79b12f76c63decf33ff9d5103\",\"dweb:/ipfs/QmQ3bnkQJgD2s6xpapThCPTSMbDREokVEiM7extwQgfrv7\"]},\"lib/CMTAT/contracts/library/ERC1404ExtendInterfaceId.sol\":{\"keccak256\":\"0xe5f6f08d319d27f20989936460d3947eed5fdcb470f80e920f4fb09ccc7e1e87\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://cb654fe37c2bc6c765c67c5f94a769580312d1d4109c50262677ac406362f91e\",\"dweb:/ipfs/Qmc8ZFVANCmULNozM2wFUSGKXBgUHR5bpDC3ZVjV4XoEv7\"]},\"lib/CMTAT/contracts/library/RuleEngineInterfaceId.sol\":{\"keccak256\":\"0x759990208069b5a0862a255eff790d52d1d64bbb6c334705fc12414936825692\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://0bce1c17cbbddac4bf123f602dc980246e5bec724f5ed3107e148548b930e124\",\"dweb:/ipfs/QmRZUxmRN9ji9UYueD6knhnz2nSsDRZgRTX74uenGczVjA\"]},\"lib/openzeppelin-contracts/contracts/access/Ownable.sol\":{\"keccak256\":\"0xff6d0bb2e285473e5311d9d3caacb525ae3538a80758c10649a4d61029b017bb\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://8ed324d3920bb545059d66ab97d43e43ee85fd3bd52e03e401f020afb0b120f6\",\"dweb:/ipfs/QmfEckWLmZkDDcoWrkEvMWhms66xwTLff9DDhegYpvHo1a\"]},\"lib/openzeppelin-contracts/contracts/interfaces/IERC165.sol\":{\"keccak256\":\"0x0afcb7e740d1537b252cb2676f600465ce6938398569f09ba1b9ca240dde2dfc\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://1c299900ac4ec268d4570ecef0d697a3013cd11a6eb74e295ee3fbc945056037\",\"dweb:/ipfs/Qmab9owJoxcA7vJT5XNayCMaUR1qxqj1NDzzisduwaJMcZ\"]},\"lib/openzeppelin-contracts/contracts/metatx/ERC2771Context.sol\":{\"keccak256\":\"0x9695d220b99dcf62910533bdf5d40d4cf6a4e04d5b106b6803a80586486dc7f7\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://83b7aecd65882d8953643dce144efe91367082cc01830c9c4ed3c8a4837fb558\",\"dweb:/ipfs/QmQ5HxGavcCKjuhd8buv177qjG6A4kvxx4pZviceKdspdM\"]},\"lib/openzeppelin-contracts/contracts/utils/Arrays.sol\":{\"keccak256\":\"0xb3b81029526a4c3acf39e57cc446407141ebce338cc99585942af1340e1a69e0\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://3857ce97e8f7a51ad78ea5419b3386e18fcc8af73b65803eedd8193ab7abc9df\",\"dweb:/ipfs/QmSQi6x2cYsUy76mfMNwuq151bVmh4kAND141kjume51Aq\"]},\"lib/openzeppelin-contracts/contracts/utils/Comparators.sol\":{\"keccak256\":\"0x302eecd8cf323b4690e3494a7d960b3cbce077032ab8ef655b323cdd136cec58\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://49ba706f1bc476d68fe6c1fad75517acea4e9e275be0989b548e292eb3a3eacd\",\"dweb:/ipfs/QmeBpvcdGWzWMKTQESUCEhHgnEQYYATVwPxLMxa6vMT7jC\"]},\"lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"keccak256\":\"0x493033a8d1b176a037b2cc6a04dad01a5c157722049bbecf632ca876224dd4b2\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6a708e8a5bdb1011c2c381c9a5cfd8a9a956d7d0a9dc1bd8bcdaf52f76ef2f12\",\"dweb:/ipfs/Qmax9WHBnVsZP46ZxEMNRQpLQnrdE4dK8LehML1Py8FowF\"]},\"lib/openzeppelin-contracts/contracts/utils/Panic.sol\":{\"keccak256\":\"0xf7fe324703a64fc51702311dc51562d5cb1497734f074e4f483bfb6717572d7a\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c6a5ff4f9fd8649b7ee20800b7fa387d3465bd77cf20c2d1068cd5c98e1ed57a\",\"dweb:/ipfs/QmVSaVJf9FXFhdYEYeCEfjMVHrxDh5qL4CGkxdMWpQCrqG\"]},\"lib/openzeppelin-contracts/contracts/utils/SlotDerivation.sol\":{\"keccak256\":\"0x94045fd4f268edf2b2d01ef119268548c320366d6f5294ad30c1b8f9d4f5225f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://edfda81f426f8948b3834115c21e83c48180e6db0d2a8cd2debb2185ed349337\",\"dweb:/ipfs/QmdYZneFyDAux1BuWQxLAdqtABrGS2k9WYCa7C9dvpKkWv\"]},\"lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol\":{\"keccak256\":\"0xcf74f855663ce2ae00ed8352666b7935f6cddea2932fdf2c3ecd30a9b1cd0e97\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://9f660b1f351b757dfe01438e59888f31f33ded3afcf5cb5b0d9bf9aa6f320a8b\",\"dweb:/ipfs/QmarDJ5hZEgBtCmmrVzEZWjub9769eD686jmzb2XpSU1cM\"]},\"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165Checker.sol\":{\"keccak256\":\"0x7c7ad70641a7f8cd44def0857ec97b0e40bfd073b2d6037a5f57ce9527ee9bc5\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://e05c6572dfe769f7aea6f3a8002951cc12d143d980dad29f6c5feedf9408bc14\",\"dweb:/ipfs/QmXM7C8YEptxisZiEefXUrwdXt3zMaCobmkCchxTtDg1oK\"]},\"lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"keccak256\":\"0x8891738ffe910f0cf2da09566928589bf5d63f4524dd734fd9cedbac3274dd5c\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://971f954442df5c2ef5b5ebf1eb245d7105d9fbacc7386ee5c796df1d45b21617\",\"dweb:/ipfs/QmadRjHbkicwqwwh61raUEapaVEtaLMcYbQZWs9gUkgj3u\"]},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"keccak256\":\"0x59973a93b1f983f94e10529f46ca46544a9fec2b5f56fb1390bbe9e0dc79f857\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c55ef8f0b9719790c2ae6f81d80a59ffb89f2f0abe6bc065585bd79edce058c5\",\"dweb:/ipfs/QmNNmCbX9NjPXKqHJN8R1WC2rNeZSQrPZLd6FF6AKLyH5Y\"]},\"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\":{\"keccak256\":\"0xc8cae21c9ae4a46e5162ff9bf5b351d6fa6a6eba72d515f3bc1bdfeda7fdf083\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://ce830ebcf28e31643caba318996db3763c36d52cd0f23798ba83c135355d45e9\",\"dweb:/ipfs/QmdGPcvptHN7UBCbUYBbRX3hiRVRFLRwno8b4uga6uFNif\"]},\"lib/openzeppelin-contracts/contracts/utils/structs/EnumerableSet.sol\":{\"keccak256\":\"0x5c298e834696707e274a71a224969d36faecd928a8076603210d67d091adb4ae\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://a93fe967b4d55b31157164cbb7e3e1ebaf3535fc1d3f8d0156da7abb9b565d90\",\"dweb:/ipfs/QmXH7nyxwEUeMPFDDmkdUwqxLEcezaSmVyunyMAuck1WqR\"]},\"src/RuleEngineBase.sol\":{\"keccak256\":\"0x9edae8ce7df18638cf56b571be18251d4ac4c435844c8cd77d1f7f651623c568\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://9758c7256a994b371c00d9e0098be5d76d9896f2a556208dfb83768d4d4e916b\",\"dweb:/ipfs/QmdZwwiB29tzheoaoRWiJdbbGMH2nM46ojLp7WFjm9D19h\"]},\"src/RuleEngineOwnableShared.sol\":{\"keccak256\":\"0xbe119365533074f6f59227e4b74432e03407f553f13c8361c21166f1fbb67f19\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://22b0689c774191b4065d1eda22d040fc79211f83e41f018dfe4bfcae7a328a57\",\"dweb:/ipfs/QmS9EgzvD45x72bNpMW3hyMQHfPyyBJN24iJmAuR1cEjpc\"]},\"src/deployment/RuleEngineOwnable.sol\":{\"keccak256\":\"0x1b602dc94079c162e897f1dbc55284aaa1a64a8790ceb91721fa0e81b5173a7b\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://028c26566591036d52e08ad109eb0c42be42b054cb0b5b05f567a33320912b03\",\"dweb:/ipfs/QmQhFyQfsgcdewRz1WJVBVmr5r5pigmzeg7MsjaLNUP9kZ\"]},\"src/interfaces/IERC3643Compliance.sol\":{\"keccak256\":\"0xf86e78e8f737795c3762b402b121b0f1822d6b27414aeca08ea6f036cccea07b\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://c795d1b89a1393b2225f6e58c0310d345d78ff534ab028353413c4a5aaf9ecf7\",\"dweb:/ipfs/QmNcJsJzLWzSAV77whMzu7je2Mj2pWoTYYn1z76kqB5mKH\"]},\"src/interfaces/IRule.sol\":{\"keccak256\":\"0x315fd1d0147d40d3cc1ee35f6ddb8c9e25e6e4f96034a285e6f342c59c3cc222\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://5b0ecca410bf89169e5c6393bc4d8fce97a5b3dcf8a2bba02317da85c98f4d0c\",\"dweb:/ipfs/QmeGS5vbFwkmEvJh7s27Q9xW4xGXuUohh2zGPVbgxgjfnu\"]},\"src/interfaces/IRulesManagementModule.sol\":{\"keccak256\":\"0x1be8087ef526f664cf8ba5dd35d4d12fc1880f905e3ba2e553ee02cb7d6506c1\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://545cafd73f2fe9b2b89b37e905057637f58ae2c1da7f3dc33493b515c87a720f\",\"dweb:/ipfs/QmXiTEhLSpN6sj1fiwFT9V6bGD1VCXTqQJiNnXcLrYmW7N\"]},\"src/modules/ERC2771ModuleStandalone.sol\":{\"keccak256\":\"0xecc9aec20ff41c46404f6fcb9bfb0fd5588781fbb4f2fbec351f603a31c178b0\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://48674e77afe59b6c6e6aa8b0d5e370ca58c9a354b5dc294bb3c9f10fbd12a3f3\",\"dweb:/ipfs/QmY3HhbBDqsBvrGBXoRwgVpfSNtiK2XmhaxVpS1F3dSPx9\"]},\"src/modules/ERC3643ComplianceModule.sol\":{\"keccak256\":\"0xdb472471270ea23d4694ca2d2eb107ce668affc9dbe18b5a6eda312ab4800a33\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://6200e990afca50a32fb0a0ad76ffe955447a67cab6e93f64281fc9f14208aab1\",\"dweb:/ipfs/QmXXhRsBq3eGDgBqQwWL5w4Sn6pdTeeXRvpC4jZBDVb6nQ\"]},\"src/modules/RulesManagementModule.sol\":{\"keccak256\":\"0xc9c58e027874658577285de9c9bf9069cd773573a615df7c9644c6c96c69dbc3\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://a6c9ca74cc247b42b9852b35cb4eeadc919d383d7bbd4f4df0739ee6a8bce2c3\",\"dweb:/ipfs/QmfJCvSQjqQrQXYt9JEHiJRZATy1s7q53DKxZC1QsSYMHZ\"]},\"src/modules/VersionModule.sol\":{\"keccak256\":\"0x077070dca24da125a764111d336c0a8fb3445b82d93692ff76b22384b0f4f39f\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://be8df88e667fb2de39d095f0c396d23ed263fdc51a4095fedc89a326540a03ee\",\"dweb:/ipfs/QmYfhhEvNee1XYwCYZCVAKpUUWBd5FP5qvTMYGr6ogC8kA\"]},\"src/modules/library/ComplianceInterfaceId.sol\":{\"keccak256\":\"0xa0f15ca7f9e0fa8ccb854ea2bd812f220c68c280682b56e8d1a437ddba4b6d1f\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://1e01a79b4a2110a401c3d2fbead97844f7428d6dc6603dccf795d42dbc142786\",\"dweb:/ipfs/QmV88ZcDHTU33oXNLFTshUBZ7otgcZRN1HXwywda7Fgz9a\"]},\"src/modules/library/RuleEngineInvariantStorage.sol\":{\"keccak256\":\"0x15005e56f8fbf8f9b8a41c4bfed6c842e37be49fa52b0dbb2edc6b08b9e50c2f\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://06c90dd748d060cb1b05de978cb42fd79d9b49a2beb3a479b4e49f8edaba1195\",\"dweb:/ipfs/QmYXEQWrwJkuzWBdi5hjSaM6pWhrNUf2kH2pHX8jRu9dZS\"]},\"src/modules/library/RuleInterfaceId.sol\":{\"keccak256\":\"0x3c57987589d6205e2546d4ce332e944d1667dddfe897087028a95ed804c50882\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://0e1718e500d4cb5cf4441131c57d23da788f2835e9a014e7d1f62dfb6161647a\",\"dweb:/ipfs/QmXY5cjc9Dzrp7ML7DfvDB9zg7t4cene3g4K9AAuDmLLfC\"]},\"src/modules/library/RulesManagementModuleInvariantStorage.sol\":{\"keccak256\":\"0xa6f9109698f169be74c309a1efadd48edffcb0e9585523258477bf07942c8ae6\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://4c28513636b660111b60a7028c9600b30dcfda291a831343d9e27e253b80856a\",\"dweb:/ipfs/QmQVSZ9N6vjPxNnJDTqEuGSWqNdoxHKhzTzP2cvgZpBSzj\"]}},\"version\":1}","metadata":{"compiler":{"version":"0.8.34+commit.80d5c536"},"language":"Solidity","output":{"abi":[{"inputs":[{"internalType":"address","name":"owner_","type":"address"},{"internalType":"address","name":"forwarderIrrevocable","type":"address"},{"internalType":"address","name":"tokenContract","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"type":"error","name":"OwnableInvalidOwner"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"type":"error","name":"OwnableUnauthorizedAccount"},{"inputs":[],"type":"error","name":"RuleEngine_AdminWithAddressZeroNotAllowed"},{"inputs":[],"type":"error","name":"RuleEngine_ERC3643Compliance_InvalidTokenAddress"},{"inputs":[],"type":"error","name":"RuleEngine_ERC3643Compliance_OperationNotSuccessful"},{"inputs":[],"type":"error","name":"RuleEngine_ERC3643Compliance_TokenAlreadyBound"},{"inputs":[],"type":"error","name":"RuleEngine_ERC3643Compliance_TokenNotBound"},{"inputs":[],"type":"error","name":"RuleEngine_ERC3643Compliance_UnauthorizedCaller"},{"inputs":[],"type":"error","name":"RuleEngine_RuleInvalidInterface"},{"inputs":[],"type":"error","name":"RuleEngine_RulesManagementModule_ArrayIsEmpty"},{"inputs":[],"type":"error","name":"RuleEngine_RulesManagementModule_OperationNotSuccessful"},{"inputs":[],"type":"error","name":"RuleEngine_RulesManagementModule_RuleAddressZeroNotAllowed"},{"inputs":[],"type":"error","name":"RuleEngine_RulesManagementModule_RuleAlreadyExists"},{"inputs":[],"type":"error","name":"RuleEngine_RulesManagementModule_RuleDoNotMatch"},{"inputs":[{"internalType":"contract IRule","name":"rule","type":"address","indexed":true}],"type":"event","name":"AddRule","anonymous":false},{"inputs":[],"type":"event","name":"ClearRules","anonymous":false},{"inputs":[{"internalType":"address","name":"previousOwner","type":"address","indexed":true},{"internalType":"address","name":"newOwner","type":"address","indexed":true}],"type":"event","name":"OwnershipTransferred","anonymous":false},{"inputs":[{"internalType":"contract IRule","name":"rule","type":"address","indexed":true}],"type":"event","name":"RemoveRule","anonymous":false},{"inputs":[{"internalType":"address","name":"token","type":"address","indexed":false}],"type":"event","name":"TokenBound","anonymous":false},{"inputs":[{"internalType":"address","name":"token","type":"address","indexed":false}],"type":"event","name":"TokenUnbound","anonymous":false},{"inputs":[],"stateMutability":"view","type":"function","name":"COMPLIANCE_MANAGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"RULES_MANAGEMENT_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}]},{"inputs":[{"internalType":"contract IRule","name":"rule_","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"addRule"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"bindToken"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"view","type":"function","name":"canTransfer","outputs":[{"internalType":"bool","name":"","type":"bool"}]},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"view","type":"function","name":"canTransferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}]},{"inputs":[],"stateMutability":"nonpayable","type":"function","name":"clearRules"},{"inputs":[{"internalType":"contract IRule","name":"rule_","type":"address"}],"stateMutability":"view","type":"function","name":"containsRule","outputs":[{"internalType":"bool","name":"","type":"bool"}]},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"nonpayable","type":"function","name":"created"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"nonpayable","type":"function","name":"destroyed"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"view","type":"function","name":"detectTransferRestriction","outputs":[{"internalType":"uint8","name":"","type":"uint8"}]},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"view","type":"function","name":"detectTransferRestrictionFrom","outputs":[{"internalType":"uint8","name":"","type":"uint8"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"getTokenBound","outputs":[{"internalType":"address","name":"","type":"address"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"getTokenBounds","outputs":[{"internalType":"address[]","name":"","type":"address[]"}]},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"stateMutability":"view","type":"function","name":"isTokenBound","outputs":[{"internalType":"bool","name":"","type":"bool"}]},{"inputs":[{"internalType":"address","name":"forwarder","type":"address"}],"stateMutability":"view","type":"function","name":"isTrustedForwarder","outputs":[{"internalType":"bool","name":"","type":"bool"}]},{"inputs":[{"internalType":"uint8","name":"restrictionCode","type":"uint8"}],"stateMutability":"view","type":"function","name":"messageForTransferRestriction","outputs":[{"internalType":"string","name":"","type":"string"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}]},{"inputs":[{"internalType":"contract IRule","name":"rule_","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"removeRule"},{"inputs":[],"stateMutability":"nonpayable","type":"function","name":"renounceOwnership"},{"inputs":[{"internalType":"uint256","name":"ruleId","type":"uint256"}],"stateMutability":"view","type":"function","name":"rule","outputs":[{"internalType":"address","name":"","type":"address"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"rules","outputs":[{"internalType":"address[]","name":"","type":"address[]"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"rulesCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}]},{"inputs":[{"internalType":"contract IRule[]","name":"rules_","type":"address[]"}],"stateMutability":"nonpayable","type":"function","name":"setRules"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"stateMutability":"view","type":"function","name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}]},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"transferOwnership"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"nonpayable","type":"function","name":"transferred"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"nonpayable","type":"function","name":"transferred"},{"inputs":[],"stateMutability":"view","type":"function","name":"trustedForwarder","outputs":[{"internalType":"address","name":"","type":"address"}]},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"unbindToken"},{"inputs":[],"stateMutability":"view","type":"function","name":"version","outputs":[{"internalType":"string","name":"version_","type":"string"}]}],"devdoc":{"kind":"dev","methods":{"addRule(address)":{"details":"No on-chain maximum number of rules is enforced. Adding too many rules can increase transfer-time gas usage because rule checks are linear in rule count. Security convention: do not grant {RULES_MANAGEMENT_ROLE} to rule contracts.","params":{"rule_":"The IRule contract to add."}},"bindToken(address)":{"details":"Operator warning: \"multi-tenant\" means one RuleEngine is shared by multiple token contracts. In that setup, bind only tokens that are equally trusted and governed together.","params":{"token":"The address of the token to bind."}},"canTransfer(address,address,uint256)":{"details":"Don't check the balance and the user's right (access control)"},"canTransferFrom(address,address,address,uint256)":{"details":"Does not check balances or access rights (Access Control).","params":{"from":"The source address.","spender":"The address performing the transfer.","to":"The destination address.","value":"The number of tokens to transfer."},"returns":{"_0":"isCompliant True if the transfer complies with policy."}},"clearRules()":{"details":"After calling this function, no rules will remain set. Developers should keep in mind that this function has an unbounded cost and using it may render the function uncallable if the set grows to the point where clearing it consumes too much gas to fit in a block."},"constructor":{"params":{"forwarderIrrevocable":"Address of the forwarder, required for the gasless support","owner_":"Address of the contract owner (ERC-173)","tokenContract":"Address of the token contract to bind (can be zero address)"}},"containsRule(address)":{"details":"Complexity: O(1).","params":{"rule_":"The IRule contract to check for membership."},"returns":{"_0":"True if the rule is present, false otherwise."}},"created(address,uint256)":{"details":"Called by the token contract when new tokens are issued to an account. Reverts if the minting does not comply with the rules.","params":{"to":"The address receiving the minted tokens.","value":"The number of tokens created."}},"destroyed(address,uint256)":{"details":"Called by the token contract when tokens are redeemed or burned. Reverts if the burning does not comply with the rules.","params":{"from":"The address whose tokens are being destroyed.","value":"The number of tokens destroyed."}},"detectTransferRestriction(address,address,uint256)":{"params":{"from":"the origin address","to":"the destination address","value":"to transfer"},"returns":{"_0":"The restricion code or REJECTED_CODE_BASE.TRANSFER_OK (0) if the transfer is valid"}},"detectTransferRestrictionFrom(address,address,address,uint256)":{"details":" See {ERC-1404} Add an additionnal argument `spender` This function is where an issuer enforces the restriction logic of their token transfers. Some examples of this might include: - checking if the token recipient is whitelisted, - checking if a sender's tokens are frozen in a lock-up period, etc.","returns":{"_0":"uint8 restricted code, 0 means the transfer is authorized"}},"getTokenBound()":{"details":"If multiple tokens are supported, consider using getTokenBounds().","returns":{"_0":"The address of the currently bound token."}},"getTokenBounds()":{"details":"This is a view-only function and does not modify state. This function is not part of the original ERC-3643 specification This operation will copy the entire storage to memory, which can be quite expensive. This is designed to mostly be used by view accessors that are queried without any gas fees.","returns":{"_0":"An array of addresses of bound token contracts."}},"isTokenBound(address)":{"details":"Complexity: O(1). Note that there are no guarantees on the ordering of values inside the array, and it may change when more values are added or removed.","params":{"token":"The token address to verify."},"returns":{"_0":"True if the token is bound, false otherwise."}},"isTrustedForwarder(address)":{"details":"Indicates whether any particular address is the trusted forwarder."},"messageForTransferRestriction(uint8)":{"details":"See {ERC-1404} This function is effectively an accessor for the \"message\", a human-readable explanation as to why a transaction is restricted. "},"owner()":{"details":"Returns the address of the current owner."},"removeRule(address)":{"details":"Reverts if the provided rule is not found or does not match the stored rule at its index. Complexity: O(1).","params":{"rule_":"The IRule contract to remove."}},"renounceOwnership()":{"details":"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner."},"rule(uint256)":{"details":"Reverts if `ruleId` is out of bounds. Complexity: O(1). Note that there are no guarantees on the ordering of values inside the array, and it may change when more values are added or removed.","params":{"ruleId":"The index of the desired rule in the array."},"returns":{"_0":"The address of the corresponding IRule contract, return the `zero address` is out of bounds."}},"rules()":{"details":"This is a view-only function that does not modify state. This operation will copy the entire storage to memory, which can be quite expensive. This is designed to mostly be used by view accessors that are queried without any gas fees.","returns":{"_0":"An array of all active rule contract addresses."}},"rulesCount()":{"details":"Equivalent to the length of the internal rules array. Complexity: O(1)","returns":{"_0":"The number of active rules."}},"setRules(address[])":{"details":"Replaces the entire rule set atomically. Reverts if `rules_` is empty. Use {clearRules} to remove all rules explicitly. To transition from one non-empty set to another without an enforcement gap, call this function directly with the new set. No on-chain maximum number of rules is enforced. Operators are responsible for keeping the rule set size compatible with the target chain gas limits. Security convention: rule contracts should be treated as trusted business logic, but should not also be granted {RULES_MANAGEMENT_ROLE}.","params":{"rules_":"The array of addresses representing the new rules to be set."}},"supportsInterface(bytes4)":{"details":"Returns true if this contract implements the interface defined by `interfaceId`. See the corresponding https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section] to learn more about how these ids are created. This function call must use less than 30 000 gas."},"transferOwnership(address)":{"details":"Transfers ownership of the contract to a new account (`newOwner`). Can only be called by the current owner."},"transferred(address,address,address,uint256)":{"details":" Must revert if the transfer is invalid Same name as ERC-3643 but with one supplementary argument `spender` This function can be used to update state variables of the RuleEngine contract This function can be called ONLY by the token contract bound to the RuleEngine","params":{"from":"token holder address","spender":"spender address (sender)","to":"receiver address","value":"value of tokens involved in the transfer"}},"transferred(address,address,uint256)":{"details":" This function can be used to update state variables of the compliance contract This function can be called ONLY by the token contract bound to the compliance","params":{"from":"The address of the sender","to":"The address of the receiver","value":"value of tokens involved in the transfer"}},"trustedForwarder()":{"details":"Returns the address of the trusted forwarder."},"unbindToken(address)":{"details":"Operator warning: unbinding is an administrative operation and does not erase any state already stored by external rule contracts in a previously shared (\"multi-tenant\") setup.","params":{"token":"The address of the token to unbind."}},"version()":{"details":"This value is useful to know which smart contract version has been used","returns":{"version_":"A string representing the version of the token implementation (e.g., \"1.0.0\")."}}},"version":1},"userdoc":{"kind":"user","methods":{"RULES_MANAGEMENT_ROLE()":{"notice":"Role to manage the ruleEngine"},"addRule(address)":{"notice":"Adds a new rule to the current rule set."},"bindToken(address)":{"notice":"Associates a token contract with this compliance contract."},"canTransfer(address,address,uint256)":{"notice":"Returns true if the transfer is valid, and false otherwise."},"canTransferFrom(address,address,address,uint256)":{"notice":"Checks if `spender` can transfer `value` tokens from `from` to `to` under compliance rules."},"clearRules()":{"notice":"Removes all configured rules."},"containsRule(address)":{"notice":"Checks whether a specific rule is currently configured."},"created(address,uint256)":{"notice":"Updates the compliance contract state when tokens are created (minted)."},"destroyed(address,uint256)":{"notice":"Updates the compliance contract state when tokens are destroyed (burned)."},"detectTransferRestriction(address,address,uint256)":{"notice":"Go through all the rule to know if a restriction exists on the transfer"},"detectTransferRestrictionFrom(address,address,address,uint256)":{"notice":"Returns a uint8 code to indicate if a transfer is restricted or not"},"getTokenBound()":{"notice":"Returns the single token currently bound to this compliance contract."},"getTokenBounds()":{"notice":"Returns all tokens currently bound to this compliance contract."},"isTokenBound(address)":{"notice":"Checks whether a token is currently bound to this compliance contract."},"removeRule(address)":{"notice":"Removes a specific rule from the current rule set."},"rule(uint256)":{"notice":"Retrieves the rule address at a specific index."},"rules()":{"notice":"Returns the full list of currently configured rules."},"rulesCount()":{"notice":"Returns the total number of currently configured rules."},"setRules(address[])":{"notice":"Defines the rules for the rule engine."},"transferred(address,address,address,uint256)":{"notice":"Function called whenever tokens are transferred from one wallet to another"},"transferred(address,address,uint256)":{"notice":"Function called whenever tokens are transferred from one wallet to another"},"unbindToken(address)":{"notice":"Removes the association of a token contract from this compliance contract."},"version()":{"notice":"Returns the current version of the token contract."}},"version":1}},"settings":{"remappings":["@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/","@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/","CMTAT/=lib/CMTAT/contracts/","CMTATv3.0.0/=lib/CMTATv3.0.0/contracts/","erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/","forge-std/=lib/forge-std/src/","halmos-cheatcodes/=lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/","openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/","openzeppelin-contracts/=lib/openzeppelin-contracts/"],"optimizer":{"enabled":true,"runs":200},"metadata":{"bytecodeHash":"ipfs"},"compilationTarget":{"src/deployment/RuleEngineOwnable.sol":"RuleEngineOwnable"},"evmVersion":"prague","libraries":{}},"sources":{"lib/CMTAT/contracts/interfaces/engine/IRuleEngine.sol":{"keccak256":"0x524a2cf2214a82fb96e97a18a94956fee68a419ecd6b2dc841aa1105f336c3f1","urls":["bzz-raw://9c4728d80b6678101586515c0308c63bcba2a78b0a3c12d37b522d59f3175a01","dweb:/ipfs/QmYP9SPbe2hB69jKkSg43qkz1HVxBayKrG14i9f6hx7hh8"],"license":"MPL-2.0"},"lib/CMTAT/contracts/interfaces/technical/IERC5679.sol":{"keccak256":"0xcc6f2e79d1d9eabcf4c7ffcbd85c0de31bb2b3cdf17eb847dffb7c2d2a8c4695","urls":["bzz-raw://d618bc2be7c6bc167037fe57ca648523c671c61791f3f0c65965ab7139d6dc33","dweb:/ipfs/QmSrCKWFjpg1SQ7v2k3vRyWpcU9dB6Pbk167R4oAzUc2Te"],"license":"MPL-2.0"},"lib/CMTAT/contracts/interfaces/tokenization/IERC3643Partial.sol":{"keccak256":"0x1707381177447b1a398c443c7e753942df0c5d4633e80d2864db472e89e43dc0","urls":["bzz-raw://c4281d98847629b67222332bea67f336623937758be908ee9ca1aa40b3abe19d","dweb:/ipfs/QmZQBruKJH3sStjBmCb28rxRkUkZ4EFsDCi8WZ7Y85spxS"],"license":"MPL-2.0"},"lib/CMTAT/contracts/interfaces/tokenization/draft-IERC1404.sol":{"keccak256":"0x17fb1f64b546fd882331dffbd8c7f4e53c51738b9e2621a0dcfcf30e64d8b66e","urls":["bzz-raw://c35fe277d5d99a0943293b5da5622947095e6b719af35fda9ef2c714a7879a4b","dweb:/ipfs/QmRV5q3XvjJE8sxJJBpEkwk1qyz3r4McH2BdX1v2ZxZGZh"],"license":"MPL-2.0"},"lib/CMTAT/contracts/interfaces/tokenization/draft-IERC7551.sol":{"keccak256":"0x709074d96bd5d7aa07d2ba3a1c9a99ae0fd4361f7322b528b42f3b83c5dcb984","urls":["bzz-raw://ca67a06011b746b55bf2465988dc10a4e6371e40b5108c54531f03e938bda865","dweb:/ipfs/QmbjFyDAJsUXywqzU2s96pFqFpC5DLKdfa8WjMBtQPhKGE"],"license":"MPL-2.0"},"lib/CMTAT/contracts/interfaces/tokenization/draft-IERC7943.sol":{"keccak256":"0x1a341fc7ee7d9b8b00b6168b35a6a844d90431749d8ca694174c52c41e11763f","urls":["bzz-raw://4fb6b13953539b99262cb299961fb8ff8a020de79b12f76c63decf33ff9d5103","dweb:/ipfs/QmQ3bnkQJgD2s6xpapThCPTSMbDREokVEiM7extwQgfrv7"],"license":"MPL-2.0"},"lib/CMTAT/contracts/library/ERC1404ExtendInterfaceId.sol":{"keccak256":"0xe5f6f08d319d27f20989936460d3947eed5fdcb470f80e920f4fb09ccc7e1e87","urls":["bzz-raw://cb654fe37c2bc6c765c67c5f94a769580312d1d4109c50262677ac406362f91e","dweb:/ipfs/Qmc8ZFVANCmULNozM2wFUSGKXBgUHR5bpDC3ZVjV4XoEv7"],"license":"MPL-2.0"},"lib/CMTAT/contracts/library/RuleEngineInterfaceId.sol":{"keccak256":"0x759990208069b5a0862a255eff790d52d1d64bbb6c334705fc12414936825692","urls":["bzz-raw://0bce1c17cbbddac4bf123f602dc980246e5bec724f5ed3107e148548b930e124","dweb:/ipfs/QmRZUxmRN9ji9UYueD6knhnz2nSsDRZgRTX74uenGczVjA"],"license":"MPL-2.0"},"lib/openzeppelin-contracts/contracts/access/Ownable.sol":{"keccak256":"0xff6d0bb2e285473e5311d9d3caacb525ae3538a80758c10649a4d61029b017bb","urls":["bzz-raw://8ed324d3920bb545059d66ab97d43e43ee85fd3bd52e03e401f020afb0b120f6","dweb:/ipfs/QmfEckWLmZkDDcoWrkEvMWhms66xwTLff9DDhegYpvHo1a"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/interfaces/IERC165.sol":{"keccak256":"0x0afcb7e740d1537b252cb2676f600465ce6938398569f09ba1b9ca240dde2dfc","urls":["bzz-raw://1c299900ac4ec268d4570ecef0d697a3013cd11a6eb74e295ee3fbc945056037","dweb:/ipfs/Qmab9owJoxcA7vJT5XNayCMaUR1qxqj1NDzzisduwaJMcZ"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/metatx/ERC2771Context.sol":{"keccak256":"0x9695d220b99dcf62910533bdf5d40d4cf6a4e04d5b106b6803a80586486dc7f7","urls":["bzz-raw://83b7aecd65882d8953643dce144efe91367082cc01830c9c4ed3c8a4837fb558","dweb:/ipfs/QmQ5HxGavcCKjuhd8buv177qjG6A4kvxx4pZviceKdspdM"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/Arrays.sol":{"keccak256":"0xb3b81029526a4c3acf39e57cc446407141ebce338cc99585942af1340e1a69e0","urls":["bzz-raw://3857ce97e8f7a51ad78ea5419b3386e18fcc8af73b65803eedd8193ab7abc9df","dweb:/ipfs/QmSQi6x2cYsUy76mfMNwuq151bVmh4kAND141kjume51Aq"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/Comparators.sol":{"keccak256":"0x302eecd8cf323b4690e3494a7d960b3cbce077032ab8ef655b323cdd136cec58","urls":["bzz-raw://49ba706f1bc476d68fe6c1fad75517acea4e9e275be0989b548e292eb3a3eacd","dweb:/ipfs/QmeBpvcdGWzWMKTQESUCEhHgnEQYYATVwPxLMxa6vMT7jC"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/Context.sol":{"keccak256":"0x493033a8d1b176a037b2cc6a04dad01a5c157722049bbecf632ca876224dd4b2","urls":["bzz-raw://6a708e8a5bdb1011c2c381c9a5cfd8a9a956d7d0a9dc1bd8bcdaf52f76ef2f12","dweb:/ipfs/Qmax9WHBnVsZP46ZxEMNRQpLQnrdE4dK8LehML1Py8FowF"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/Panic.sol":{"keccak256":"0xf7fe324703a64fc51702311dc51562d5cb1497734f074e4f483bfb6717572d7a","urls":["bzz-raw://c6a5ff4f9fd8649b7ee20800b7fa387d3465bd77cf20c2d1068cd5c98e1ed57a","dweb:/ipfs/QmVSaVJf9FXFhdYEYeCEfjMVHrxDh5qL4CGkxdMWpQCrqG"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/SlotDerivation.sol":{"keccak256":"0x94045fd4f268edf2b2d01ef119268548c320366d6f5294ad30c1b8f9d4f5225f","urls":["bzz-raw://edfda81f426f8948b3834115c21e83c48180e6db0d2a8cd2debb2185ed349337","dweb:/ipfs/QmdYZneFyDAux1BuWQxLAdqtABrGS2k9WYCa7C9dvpKkWv"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol":{"keccak256":"0xcf74f855663ce2ae00ed8352666b7935f6cddea2932fdf2c3ecd30a9b1cd0e97","urls":["bzz-raw://9f660b1f351b757dfe01438e59888f31f33ded3afcf5cb5b0d9bf9aa6f320a8b","dweb:/ipfs/QmarDJ5hZEgBtCmmrVzEZWjub9769eD686jmzb2XpSU1cM"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165Checker.sol":{"keccak256":"0x7c7ad70641a7f8cd44def0857ec97b0e40bfd073b2d6037a5f57ce9527ee9bc5","urls":["bzz-raw://e05c6572dfe769f7aea6f3a8002951cc12d143d980dad29f6c5feedf9408bc14","dweb:/ipfs/QmXM7C8YEptxisZiEefXUrwdXt3zMaCobmkCchxTtDg1oK"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol":{"keccak256":"0x8891738ffe910f0cf2da09566928589bf5d63f4524dd734fd9cedbac3274dd5c","urls":["bzz-raw://971f954442df5c2ef5b5ebf1eb245d7105d9fbacc7386ee5c796df1d45b21617","dweb:/ipfs/QmadRjHbkicwqwwh61raUEapaVEtaLMcYbQZWs9gUkgj3u"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/math/Math.sol":{"keccak256":"0x59973a93b1f983f94e10529f46ca46544a9fec2b5f56fb1390bbe9e0dc79f857","urls":["bzz-raw://c55ef8f0b9719790c2ae6f81d80a59ffb89f2f0abe6bc065585bd79edce058c5","dweb:/ipfs/QmNNmCbX9NjPXKqHJN8R1WC2rNeZSQrPZLd6FF6AKLyH5Y"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol":{"keccak256":"0xc8cae21c9ae4a46e5162ff9bf5b351d6fa6a6eba72d515f3bc1bdfeda7fdf083","urls":["bzz-raw://ce830ebcf28e31643caba318996db3763c36d52cd0f23798ba83c135355d45e9","dweb:/ipfs/QmdGPcvptHN7UBCbUYBbRX3hiRVRFLRwno8b4uga6uFNif"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/structs/EnumerableSet.sol":{"keccak256":"0x5c298e834696707e274a71a224969d36faecd928a8076603210d67d091adb4ae","urls":["bzz-raw://a93fe967b4d55b31157164cbb7e3e1ebaf3535fc1d3f8d0156da7abb9b565d90","dweb:/ipfs/QmXH7nyxwEUeMPFDDmkdUwqxLEcezaSmVyunyMAuck1WqR"],"license":"MIT"},"src/RuleEngineBase.sol":{"keccak256":"0x9edae8ce7df18638cf56b571be18251d4ac4c435844c8cd77d1f7f651623c568","urls":["bzz-raw://9758c7256a994b371c00d9e0098be5d76d9896f2a556208dfb83768d4d4e916b","dweb:/ipfs/QmdZwwiB29tzheoaoRWiJdbbGMH2nM46ojLp7WFjm9D19h"],"license":"MPL-2.0"},"src/RuleEngineOwnableShared.sol":{"keccak256":"0xbe119365533074f6f59227e4b74432e03407f553f13c8361c21166f1fbb67f19","urls":["bzz-raw://22b0689c774191b4065d1eda22d040fc79211f83e41f018dfe4bfcae7a328a57","dweb:/ipfs/QmS9EgzvD45x72bNpMW3hyMQHfPyyBJN24iJmAuR1cEjpc"],"license":"MPL-2.0"},"src/deployment/RuleEngineOwnable.sol":{"keccak256":"0x1b602dc94079c162e897f1dbc55284aaa1a64a8790ceb91721fa0e81b5173a7b","urls":["bzz-raw://028c26566591036d52e08ad109eb0c42be42b054cb0b5b05f567a33320912b03","dweb:/ipfs/QmQhFyQfsgcdewRz1WJVBVmr5r5pigmzeg7MsjaLNUP9kZ"],"license":"MPL-2.0"},"src/interfaces/IERC3643Compliance.sol":{"keccak256":"0xf86e78e8f737795c3762b402b121b0f1822d6b27414aeca08ea6f036cccea07b","urls":["bzz-raw://c795d1b89a1393b2225f6e58c0310d345d78ff534ab028353413c4a5aaf9ecf7","dweb:/ipfs/QmNcJsJzLWzSAV77whMzu7je2Mj2pWoTYYn1z76kqB5mKH"],"license":"MPL-2.0"},"src/interfaces/IRule.sol":{"keccak256":"0x315fd1d0147d40d3cc1ee35f6ddb8c9e25e6e4f96034a285e6f342c59c3cc222","urls":["bzz-raw://5b0ecca410bf89169e5c6393bc4d8fce97a5b3dcf8a2bba02317da85c98f4d0c","dweb:/ipfs/QmeGS5vbFwkmEvJh7s27Q9xW4xGXuUohh2zGPVbgxgjfnu"],"license":"MPL-2.0"},"src/interfaces/IRulesManagementModule.sol":{"keccak256":"0x1be8087ef526f664cf8ba5dd35d4d12fc1880f905e3ba2e553ee02cb7d6506c1","urls":["bzz-raw://545cafd73f2fe9b2b89b37e905057637f58ae2c1da7f3dc33493b515c87a720f","dweb:/ipfs/QmXiTEhLSpN6sj1fiwFT9V6bGD1VCXTqQJiNnXcLrYmW7N"],"license":"MPL-2.0"},"src/modules/ERC2771ModuleStandalone.sol":{"keccak256":"0xecc9aec20ff41c46404f6fcb9bfb0fd5588781fbb4f2fbec351f603a31c178b0","urls":["bzz-raw://48674e77afe59b6c6e6aa8b0d5e370ca58c9a354b5dc294bb3c9f10fbd12a3f3","dweb:/ipfs/QmY3HhbBDqsBvrGBXoRwgVpfSNtiK2XmhaxVpS1F3dSPx9"],"license":"MPL-2.0"},"src/modules/ERC3643ComplianceModule.sol":{"keccak256":"0xdb472471270ea23d4694ca2d2eb107ce668affc9dbe18b5a6eda312ab4800a33","urls":["bzz-raw://6200e990afca50a32fb0a0ad76ffe955447a67cab6e93f64281fc9f14208aab1","dweb:/ipfs/QmXXhRsBq3eGDgBqQwWL5w4Sn6pdTeeXRvpC4jZBDVb6nQ"],"license":"MPL-2.0"},"src/modules/RulesManagementModule.sol":{"keccak256":"0xc9c58e027874658577285de9c9bf9069cd773573a615df7c9644c6c96c69dbc3","urls":["bzz-raw://a6c9ca74cc247b42b9852b35cb4eeadc919d383d7bbd4f4df0739ee6a8bce2c3","dweb:/ipfs/QmfJCvSQjqQrQXYt9JEHiJRZATy1s7q53DKxZC1QsSYMHZ"],"license":"MPL-2.0"},"src/modules/VersionModule.sol":{"keccak256":"0x077070dca24da125a764111d336c0a8fb3445b82d93692ff76b22384b0f4f39f","urls":["bzz-raw://be8df88e667fb2de39d095f0c396d23ed263fdc51a4095fedc89a326540a03ee","dweb:/ipfs/QmYfhhEvNee1XYwCYZCVAKpUUWBd5FP5qvTMYGr6ogC8kA"],"license":"MPL-2.0"},"src/modules/library/ComplianceInterfaceId.sol":{"keccak256":"0xa0f15ca7f9e0fa8ccb854ea2bd812f220c68c280682b56e8d1a437ddba4b6d1f","urls":["bzz-raw://1e01a79b4a2110a401c3d2fbead97844f7428d6dc6603dccf795d42dbc142786","dweb:/ipfs/QmV88ZcDHTU33oXNLFTshUBZ7otgcZRN1HXwywda7Fgz9a"],"license":"MPL-2.0"},"src/modules/library/RuleEngineInvariantStorage.sol":{"keccak256":"0x15005e56f8fbf8f9b8a41c4bfed6c842e37be49fa52b0dbb2edc6b08b9e50c2f","urls":["bzz-raw://06c90dd748d060cb1b05de978cb42fd79d9b49a2beb3a479b4e49f8edaba1195","dweb:/ipfs/QmYXEQWrwJkuzWBdi5hjSaM6pWhrNUf2kH2pHX8jRu9dZS"],"license":"MPL-2.0"},"src/modules/library/RuleInterfaceId.sol":{"keccak256":"0x3c57987589d6205e2546d4ce332e944d1667dddfe897087028a95ed804c50882","urls":["bzz-raw://0e1718e500d4cb5cf4441131c57d23da788f2835e9a014e7d1f62dfb6161647a","dweb:/ipfs/QmXY5cjc9Dzrp7ML7DfvDB9zg7t4cene3g4K9AAuDmLLfC"],"license":"MPL-2.0"},"src/modules/library/RulesManagementModuleInvariantStorage.sol":{"keccak256":"0xa6f9109698f169be74c309a1efadd48edffcb0e9585523258477bf07942c8ae6","urls":["bzz-raw://4c28513636b660111b60a7028c9600b30dcfda291a831343d9e27e253b80856a","dweb:/ipfs/QmQVSZ9N6vjPxNnJDTqEuGSWqNdoxHKhzTzP2cvgZpBSzj"],"license":"MPL-2.0"}},"version":1},"id":164} \ No newline at end of file diff --git a/doc/compilation/v3.0.0-rc2/foundry/RuleEngineOwnable2Step.sol/RuleEngineOwnable2Step.json b/doc/compilation/v3.0.0-rc2/foundry/RuleEngineOwnable2Step.sol/RuleEngineOwnable2Step.json deleted file mode 100644 index 3041cecc..00000000 --- a/doc/compilation/v3.0.0-rc2/foundry/RuleEngineOwnable2Step.sol/RuleEngineOwnable2Step.json +++ /dev/null @@ -1 +0,0 @@ -{"abi":[{"type":"constructor","inputs":[{"name":"owner_","type":"address","internalType":"address"},{"name":"forwarderIrrevocable","type":"address","internalType":"address"},{"name":"tokenContract","type":"address","internalType":"address"}],"stateMutability":"nonpayable"},{"type":"function","name":"COMPLIANCE_MANAGER_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"RULES_MANAGEMENT_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"acceptOwnership","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"addRule","inputs":[{"name":"rule_","type":"address","internalType":"contract IRule"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"bindToken","inputs":[{"name":"token","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"canTransfer","inputs":[{"name":"from","type":"address","internalType":"address"},{"name":"to","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"canTransferFrom","inputs":[{"name":"spender","type":"address","internalType":"address"},{"name":"from","type":"address","internalType":"address"},{"name":"to","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"clearRules","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"containsRule","inputs":[{"name":"rule_","type":"address","internalType":"contract IRule"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"created","inputs":[{"name":"to","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"destroyed","inputs":[{"name":"from","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"detectTransferRestriction","inputs":[{"name":"from","type":"address","internalType":"address"},{"name":"to","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint8","internalType":"uint8"}],"stateMutability":"view"},{"type":"function","name":"detectTransferRestrictionFrom","inputs":[{"name":"spender","type":"address","internalType":"address"},{"name":"from","type":"address","internalType":"address"},{"name":"to","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint8","internalType":"uint8"}],"stateMutability":"view"},{"type":"function","name":"getTokenBound","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"getTokenBounds","inputs":[],"outputs":[{"name":"","type":"address[]","internalType":"address[]"}],"stateMutability":"view"},{"type":"function","name":"isTokenBound","inputs":[{"name":"token","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"isTrustedForwarder","inputs":[{"name":"forwarder","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"messageForTransferRestriction","inputs":[{"name":"restrictionCode","type":"uint8","internalType":"uint8"}],"outputs":[{"name":"","type":"string","internalType":"string"}],"stateMutability":"view"},{"type":"function","name":"owner","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"pendingOwner","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"removeRule","inputs":[{"name":"rule_","type":"address","internalType":"contract IRule"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"renounceOwnership","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"rule","inputs":[{"name":"ruleId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"rules","inputs":[],"outputs":[{"name":"","type":"address[]","internalType":"address[]"}],"stateMutability":"view"},{"type":"function","name":"rulesCount","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"setRules","inputs":[{"name":"rules_","type":"address[]","internalType":"contract IRule[]"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"supportsInterface","inputs":[{"name":"interfaceId","type":"bytes4","internalType":"bytes4"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"transferOwnership","inputs":[{"name":"newOwner","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"transferred","inputs":[{"name":"spender","type":"address","internalType":"address"},{"name":"from","type":"address","internalType":"address"},{"name":"to","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"transferred","inputs":[{"name":"from","type":"address","internalType":"address"},{"name":"to","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"trustedForwarder","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"unbindToken","inputs":[{"name":"token","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"version","inputs":[],"outputs":[{"name":"version_","type":"string","internalType":"string"}],"stateMutability":"view"},{"type":"event","name":"AddRule","inputs":[{"name":"rule","type":"address","indexed":true,"internalType":"contract IRule"}],"anonymous":false},{"type":"event","name":"ClearRules","inputs":[],"anonymous":false},{"type":"event","name":"OwnershipTransferStarted","inputs":[{"name":"previousOwner","type":"address","indexed":true,"internalType":"address"},{"name":"newOwner","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"name":"previousOwner","type":"address","indexed":true,"internalType":"address"},{"name":"newOwner","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"RemoveRule","inputs":[{"name":"rule","type":"address","indexed":true,"internalType":"contract IRule"}],"anonymous":false},{"type":"event","name":"TokenBound","inputs":[{"name":"token","type":"address","indexed":false,"internalType":"address"}],"anonymous":false},{"type":"event","name":"TokenUnbound","inputs":[{"name":"token","type":"address","indexed":false,"internalType":"address"}],"anonymous":false},{"type":"error","name":"OwnableInvalidOwner","inputs":[{"name":"owner","type":"address","internalType":"address"}]},{"type":"error","name":"OwnableUnauthorizedAccount","inputs":[{"name":"account","type":"address","internalType":"address"}]},{"type":"error","name":"RuleEngine_AdminWithAddressZeroNotAllowed","inputs":[]},{"type":"error","name":"RuleEngine_ERC3643Compliance_InvalidTokenAddress","inputs":[]},{"type":"error","name":"RuleEngine_ERC3643Compliance_OperationNotSuccessful","inputs":[]},{"type":"error","name":"RuleEngine_ERC3643Compliance_TokenAlreadyBound","inputs":[]},{"type":"error","name":"RuleEngine_ERC3643Compliance_TokenNotBound","inputs":[]},{"type":"error","name":"RuleEngine_ERC3643Compliance_UnauthorizedCaller","inputs":[]},{"type":"error","name":"RuleEngine_RuleInvalidInterface","inputs":[]},{"type":"error","name":"RuleEngine_RulesManagementModule_ArrayIsEmpty","inputs":[]},{"type":"error","name":"RuleEngine_RulesManagementModule_OperationNotSuccessful","inputs":[]},{"type":"error","name":"RuleEngine_RulesManagementModule_RuleAddressZeroNotAllowed","inputs":[]},{"type":"error","name":"RuleEngine_RulesManagementModule_RuleAlreadyExists","inputs":[]},{"type":"error","name":"RuleEngine_RulesManagementModule_RuleDoNotMatch","inputs":[]}],"bytecode":{"object":"0x60a060405234801561000f575f5ffd5b50604051611bd1380380611bd183398101604081905261002e91610258565b6001600160a01b038083166080528390839083908116156100525761005281610093565b50506001600160a01b03811661008157604051631e4fbdf760e01b81525f600482015260240160405180910390fd5b61008a8161014a565b50505050610298565b6001600160a01b0381166100ba576040516301b8831760e71b815260040160405180910390fd5b6100c5600282610166565b156100e35760405163f423354760e01b815260040160405180910390fd5b6100ee60028261018c565b61010b57604051631b4ddcf360e11b815260040160405180910390fd5b6040516001600160a01b03821681527f2de35142b19ed5a07796cf30791959c592018f70b1d2d7c460eef8ffe713692b9060200160405180910390a150565b600580546001600160a01b0319169055610163816101a0565b50565b6001600160a01b0381165f90815260018301602052604081205415155b90505b92915050565b5f610183836001600160a01b0384166101f1565b600480546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b5f81815260018301602052604081205461023657508154600181810184555f848152602080822090930184905584548482528286019093526040902091909155610186565b505f610186565b80516001600160a01b0381168114610253575f5ffd5b919050565b5f5f5f6060848603121561026a575f5ffd5b6102738461023d565b92506102816020850161023d565b915061028f6040850161023d565b90509250925092565b6080516119136102be5f395f81816102f00152818161037801526113ab01526119135ff3fe608060405234801561000f575f5ffd5b50600436106101f2575f3560e01c80638baf29b411610114578063d32c7bb5116100a9578063e30c397811610079578063e30c3978146104a1578063e3c4602c146104b2578063e46638e6146104c5578063e54621d2146104d8578063f2fde38b146104e0575f5ffd5b8063d32c7bb514610443578063d4ce141514610468578063db18af6c1461047b578063df21950f1461048e575f5ffd5b80639b11c115116100e45780639b11c115146103f9578063b043572e14610420578063b27aef3a14610428578063bc13eacc1461043b575f5ffd5b80638baf29b4146103af5780638d2ea772146103c25780638da5cb5b146103d5578063993e8b95146103e6575f5ffd5b8063572b6c051161018a5780637157797f1161015a5780637157797f1461035b57806379ba50971461036e5780637da0a877146103765780637f4ab1dd1461039c575f5ffd5b8063572b6c05146102e05780635f8dead3146103205780636a3edf2814610333578063715018a614610353575f5ffd5b806340db3b50116101c557806340db3b501461027b57806352f6747a1461028e57806354e4b945146102a357806354fd4d50146102b6575f5ffd5b806301ffc9a7146101f657806303c26bcd1461021e5780633e5af4ca146102535780633ff5aa0214610268575b5f5ffd5b6102096102043660046114f1565b6104f3565b60405190151581526020015b60405180910390f35b6102457fe5c50d0927e06141e032cb9a67e1d7092dc85c0b0825191f7e1cede60002856881565b604051908152602001610215565b61026661026136600461152c565b610539565b005b61026661027636600461157a565b610553565b61026661028936600461157a565b610567565b610296610578565b6040516102159190611595565b6102096102b136600461157a565b610588565b6040805180820190915260058152640332e302e360dc1b60208201525b60405161021591906115e0565b6102096102ee36600461157a565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0390811691161490565b61026661032e366004611615565b610593565b61033b6105aa565b6040516001600160a01b039091168152602001610215565b6102666105cc565b61020961036936600461152c565b6105df565b6102666105fc565b7f000000000000000000000000000000000000000000000000000000000000000061033b565b6102d36103aa36600461164d565b610663565b6102666103bd366004611668565b61066e565b6102666103d0366004611615565b610686565b6004546001600160a01b031661033b565b6102096103f436600461157a565b610699565b6102457fea5f4eb72290e50c32abd6c23e45de3d8300b3286e1cbc2e293114b92e034e5e81565b6102666106a5565b6102666104363660046116a6565b6106b5565b6102456107e1565b61045661045136600461152c565b6107eb565b60405160ff9091168152602001610215565b610456610476366004611668565b610801565b61033b610489366004611717565b610817565b61026661049c36600461157a565b610839565b6005546001600160a01b031661033b565b6102666104c036600461157a565b610871565b6102096104d3366004611668565b6108df565b6102966108f8565b6102666104ee36600461157a565b610904565b5f6104fd82610975565b8061051857506001600160e01b031982166307f5828d60e41b145b8061053357506001600160e01b031982166301ffc9a760e01b145b92915050565b6105416109e0565b61054d84848484610a10565b50505050565b61055b610ab2565b61056481610aba565b50565b61056f610ab2565b61056481610b72565b60606105835f610bfb565b905090565b5f6105338183610c07565b61059b6109e0565b6105a65f8383610c27565b5050565b5f5f6105b66002610cc0565b11156105c75761058360025f610cc9565b505f90565b6105d4610cd4565b6105dd5f610d32565b565b5f806105ed868686866107eb565b60ff161490505b949350505050565b5f610605610d4b565b9050806001600160a01b03166106236005546001600160a01b031690565b6001600160a01b03161461065a5760405163118cdaa760e01b81526001600160a01b03821660048201526024015b60405180910390fd5b61056481610d32565b606061053382610d54565b6106766109e0565b610681838383610c27565b505050565b61068e6109e0565b6105a6825f83610c27565b5f610533600283610c07565b6106ad610ab2565b6105dd610e9e565b6106bd610ab2565b5f8190036106de576040516359203cb960e01b815260040160405180910390fd5b5f6106e85f610cc0565b11156106f6576106f6610e9e565b5f5b818110156106815761072f8383838181106107155761071561172e565b905060200201602081019061072a919061157a565b610ecf565b6107608383838181106107445761074461172e565b9050602002016020810190610759919061157a565b5f90610f06565b61077d5760405163f280d16160e01b815260040160405180910390fd5b82828281811061078f5761078f61172e565b90506020020160208101906107a4919061157a565b6001600160a01b03167f60305ce6c9104acd0969d358f926bf391174340660aaf5e6215261fd6847bf4660405160405180910390a26001016106f8565b5f6105835f610cc0565b5f6107f885858585610f1a565b95945050505050565b5f61080d848484610fe5565b90505b9392505050565b5f6108215f610cc0565b821015610832576105335f83610cc9565b505f919050565b610841610ab2565b61084b5f82610c07565b61086857604051632cdc3a4160e21b815260040160405180910390fd5b610564816110a7565b610879610ab2565b61088281610ecf565b61088c5f82610f06565b6108a95760405163f280d16160e01b815260040160405180910390fd5b6040516001600160a01b038216907f60305ce6c9104acd0969d358f926bf391174340660aaf5e6215261fd6847bf46905f90a250565b5f806108ec858585610801565b60ff1614949350505050565b60606105836002610bfb565b61090c610cd4565b600580546001600160a01b0383166001600160a01b0319909116811790915561093d6004546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b5f6001600160e01b031982166320c49ce760e01b14806109a557506001600160e01b031982166378a8de7d60e01b145b806109c057506001600160e01b03198216630c51264760e21b145b8061053357506001600160e01b03198216637157797f60e01b1492915050565b6109f36109eb610d4b565b600290610c07565b6105dd5760405163e39b3c8f60e01b815260040160405180910390fd5b5f610a1a5f610cc0565b90505f5b81811015610aaa57610a305f82610cc9565b604051631f2d7a6560e11b81526001600160a01b03888116600483015287811660248301528681166044830152606482018690529190911690633e5af4ca906084015f604051808303815f87803b158015610a89575f5ffd5b505af1158015610a9b573d5f5f3e3d5ffd5b50505050806001019050610a1e565b505050505050565b6105dd610cd4565b6001600160a01b038116610ae1576040516301b8831760e71b815260040160405180910390fd5b610aec600282610c07565b15610b0a5760405163f423354760e01b815260040160405180910390fd5b610b15600282610f06565b610b3257604051631b4ddcf360e11b815260040160405180910390fd5b6040516001600160a01b03821681527f2de35142b19ed5a07796cf30791959c592018f70b1d2d7c460eef8ffe713692b906020015b60405180910390a150565b610b7d600282610c07565b610b9a57604051636a2b488360e11b815260040160405180910390fd5b610ba5600282611104565b610bc257604051631b4ddcf360e11b815260040160405180910390fd5b6040516001600160a01b03821681527f28a4ca7134a3b3f9aff286e79ad3daadb4a06d1b43d037a3a98bdc074edd9b7a90602001610b67565b60605f61081083611118565b6001600160a01b03165f9081526001919091016020526040902054151590565b5f610c315f610cc0565b90505f5b81811015610cb957610c475f82610cc9565b6040516322ebca6d60e21b81526001600160a01b0387811660048301528681166024830152604482018690529190911690638baf29b4906064015f604051808303815f87803b158015610c98575f5ffd5b505af1158015610caa573d5f5f3e3d5ffd5b50505050806001019050610c35565b5050505050565b5f610533825490565b5f6108108383611171565b610cdc610d4b565b6001600160a01b0316610cf76004546001600160a01b031690565b6001600160a01b0316146105dd57610d0d610d4b565b60405163118cdaa760e01b81526001600160a01b039091166004820152602401610651565b600580546001600160a01b031916905561056481611197565b5f6105836111e8565b60605f610d5f6107e1565b90505f5b81811015610e6257610d7481610817565b604051633e822efb60e11b815260ff861660048201526001600160a01b039190911690637d045df690602401602060405180830381865afa158015610dbb573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ddf9190611742565b15610e5a57610ded81610817565b604051637f4ab1dd60e01b815260ff861660048201526001600160a01b039190911690637f4ab1dd906024015f60405180830381865afa158015610e33573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526105f49190810190611775565b600101610d63565b505060408051808201909152601881527f556e6b6e6f776e207265737472696374696f6e20636f64650000000000000000602082015292915050565b6040517fdbf61473843cd9be1c9791ce51ef66d0da6c9026d62ba80c1ca433b13fb729b2905f90a16105dd5f6111f1565b610ed8816111fa565b610ee981632497d6cb60e01b611249565b61056457604051639952e34360e01b815260040160405180910390fd5b5f610810836001600160a01b038416611264565b5f5f610f246107e1565b90505f5b81811015610fd9575f610f3a82610817565b60405163d32c7bb560e01b81526001600160a01b038a811660048301528981166024830152888116604483015260648201889052919091169063d32c7bb590608401602060405180830381865afa158015610f97573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610fbb9190611828565b905060ff811615610fd05792506105f4915050565b50600101610f28565b505f9695505050505050565b5f5f610fef6107e1565b90505f5b8181101561109c575f61100582610817565b60405163d4ce141560e01b81526001600160a01b038981166004830152888116602483015260448201889052919091169063d4ce141590606401602060405180830381865afa15801561105a573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061107e9190611828565b905060ff811615611093579250610810915050565b50600101610ff3565b505f95945050505050565b6110b15f82611104565b6110ce5760405163f280d16160e01b815260040160405180910390fd5b6040516001600160a01b038216907f6d83315c9718799346b67584ec64301b1457e989c8e35a8e2982a7776c04bfc4905f90a250565b5f610810836001600160a01b0384166112b0565b6060815f0180548060200260200160405190810160405280929190818152602001828054801561116557602002820191905f5260205f20905b815481526020019060010190808311611151575b50505050509050919050565b5f825f0182815481106111865761118661172e565b905f5260205f200154905092915050565b600480546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b5f61058361139a565b61056481611404565b6001600160a01b0381166112215760405163f9d152fb60e01b815260040160405180910390fd5b61122b5f82610c07565b156105645760405163cc790a4b60e01b815260040160405180910390fd5b5f6112538361145d565b80156108105750610810838361149c565b5f8181526001830160205260408120546112a957508154600181810184555f848152602080822090930184905584548482528286019093526040902091909155610533565b505f610533565b5f818152600183016020526040812054801561138a575f6112d2600183611843565b85549091505f906112e590600190611843565b9050808214611344575f865f0182815481106113035761130361172e565b905f5260205f200154905080875f0184815481106113235761132361172e565b5f918252602080832090910192909255918252600188019052604090208390555b855486908061135557611355611862565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f905560019350505050610533565b5f915050610533565b5092915050565b5f3660148082108015906113d657507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031633145b156113fc576113e936828403815f611876565b6113f29161189d565b60601c9250505090565b339250505090565b5f61140d825490565b90505f5b8181101561145657826001015f845f0183815481106114325761143261172e565b905f5260205f20015481526020019081526020015f205f9055806001019050611411565b50505f9055565b5f61146f826301ffc9a760e01b61149c565b15610832575f80611488846001600160e01b03196114bd565b915091508180156105f45750159392505050565b5f5f5f6114a985856114bd565b915091508180156107f85750949350505050565b6301ffc9a760e01b5f818152600483905290819060208260248188617530fa92505f511515601f3d11169150509250929050565b5f60208284031215611501575f5ffd5b81356001600160e01b031981168114610810575f5ffd5b6001600160a01b0381168114610564575f5ffd5b5f5f5f5f6080858703121561153f575f5ffd5b843561154a81611518565b9350602085013561155a81611518565b9250604085013561156a81611518565b9396929550929360600135925050565b5f6020828403121561158a575f5ffd5b813561081081611518565b602080825282518282018190525f918401906040840190835b818110156115d55783516001600160a01b03168352602093840193909201916001016115ae565b509095945050505050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b5f5f60408385031215611626575f5ffd5b823561163181611518565b946020939093013593505050565b60ff81168114610564575f5ffd5b5f6020828403121561165d575f5ffd5b81356108108161163f565b5f5f5f6060848603121561167a575f5ffd5b833561168581611518565b9250602084013561169581611518565b929592945050506040919091013590565b5f5f602083850312156116b7575f5ffd5b823567ffffffffffffffff8111156116cd575f5ffd5b8301601f810185136116dd575f5ffd5b803567ffffffffffffffff8111156116f3575f5ffd5b8560208260051b8401011115611707575f5ffd5b6020919091019590945092505050565b5f60208284031215611727575f5ffd5b5035919050565b634e487b7160e01b5f52603260045260245ffd5b5f60208284031215611752575f5ffd5b81518015158114610810575f5ffd5b634e487b7160e01b5f52604160045260245ffd5b5f60208284031215611785575f5ffd5b815167ffffffffffffffff81111561179b575f5ffd5b8201601f810184136117ab575f5ffd5b805167ffffffffffffffff8111156117c5576117c5611761565b604051601f8201601f19908116603f0116810167ffffffffffffffff811182821017156117f4576117f4611761565b60405281815282820160200186101561180b575f5ffd5b8160208401602083015e5f91810160200191909152949350505050565b5f60208284031215611838575f5ffd5b81516108108161163f565b8181038181111561053357634e487b7160e01b5f52601160045260245ffd5b634e487b7160e01b5f52603160045260245ffd5b5f5f85851115611884575f5ffd5b83861115611890575f5ffd5b5050820193919092039150565b80356bffffffffffffffffffffffff198116906014841015611393576bffffffffffffffffffffffff1960149490940360031b84901b169092169291505056fea2646970667358221220112af4469313f66a43c96817f27e5105f6d280d5212be301d8cd5f7becaaa13464736f6c63430008220033","sourceMap":"467:1692:165:-:0;;;805:180;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;1542:37:135;;;;;971:6:165;;918:20;;940:13;;956:27:162;::::1;::::0;952:83:::1;;999:25;1010:13:::0;999:10:::1;:25::i;:::-;-1:-1:-1::0;;;;;;;1273:26:128;;1269:95;;1322:31;;-1:-1:-1;;;1322:31:128;;1350:1;1322:31;;;725:51:231;698:18;;1322:31:128;;;;;;;1269:95;1373:32;1392:12;1373:18;:32::i;:::-;1225:187;805:180:165;;;467:1692;;3688:459:186;-1:-1:-1;;;;;3750:19:186;;3742:80;;;;-1:-1:-1;;;3742:80:186;;;;;;;;;;;;3841:28;:12;3863:5;3841:21;:28::i;:::-;3840:29;3832:88;;;;-1:-1:-1;;;3832:88:186;;;;;;;;;;;;4029:23;:12;4046:5;4029:16;:23::i;:::-;4021:87;;;;-1:-1:-1;;;4021:87:186;;;;;;;;;;;;4123:17;;-1:-1:-1;;;;;743:32:231;;725:51;;4123:17:186;;713:2:231;698:18;4123:17:186;;;;;;;3688:459;:::o;2011:153:129:-;2100:13;2093:20;;-1:-1:-1;;;;;;2093:20:129;;;2123:34;2148:8;2123:24;:34::i;:::-;2011:153;:::o;16041:165:158:-;-1:-1:-1;;;;;16174:23:158;;16121:4;5238:21;;;:14;;;:21;;;;;;:26;;16144:55;16137:62;;16041:165;;;;;:::o;15089:150::-;15159:4;15182:50;15187:3;-1:-1:-1;;;;;15207:23:158;;15182:4;:50::i;2912:187:128:-;3004:6;;;-1:-1:-1;;;;;3020:17:128;;;-1:-1:-1;;;;;;3020:17:128;;;;;;;3052:40;;3004:6;;;3020:17;3004:6;;3052:40;;2985:16;;3052:40;2975:124;2912:187;:::o;2538:406:158:-;2601:4;5238:21;;;:14;;;:21;;;;;;2617:321;;-1:-1:-1;2659:23:158;;;;;;;;:11;:23;;;;;;;;;;;;;2841:18;;2817:21;;;:14;;;:21;;;;;;:42;;;;2873:11;;2617:321;-1:-1:-1;2922:5:158;2915:12;;14:177:231;93:13;;-1:-1:-1;;;;;135:31:231;;125:42;;115:70;;181:1;178;171:12;115:70;14:177;;;:::o;196:378::-;284:6;292;300;353:2;341:9;332:7;328:23;324:32;321:52;;;369:1;366;359:12;321:52;392:40;422:9;392:40;:::i;:::-;382:50;;451:49;496:2;485:9;481:18;451:49;:::i;:::-;441:59;;519:49;564:2;553:9;549:18;519:49;:::i;:::-;509:59;;196:378;;;;;:::o;579:203::-;467:1692:165;;;;;;;;;;;;;;;;;;;;;;","linkReferences":{}},"deployedBytecode":{"object":"0x608060405234801561000f575f5ffd5b50600436106101f2575f3560e01c80638baf29b411610114578063d32c7bb5116100a9578063e30c397811610079578063e30c3978146104a1578063e3c4602c146104b2578063e46638e6146104c5578063e54621d2146104d8578063f2fde38b146104e0575f5ffd5b8063d32c7bb514610443578063d4ce141514610468578063db18af6c1461047b578063df21950f1461048e575f5ffd5b80639b11c115116100e45780639b11c115146103f9578063b043572e14610420578063b27aef3a14610428578063bc13eacc1461043b575f5ffd5b80638baf29b4146103af5780638d2ea772146103c25780638da5cb5b146103d5578063993e8b95146103e6575f5ffd5b8063572b6c051161018a5780637157797f1161015a5780637157797f1461035b57806379ba50971461036e5780637da0a877146103765780637f4ab1dd1461039c575f5ffd5b8063572b6c05146102e05780635f8dead3146103205780636a3edf2814610333578063715018a614610353575f5ffd5b806340db3b50116101c557806340db3b501461027b57806352f6747a1461028e57806354e4b945146102a357806354fd4d50146102b6575f5ffd5b806301ffc9a7146101f657806303c26bcd1461021e5780633e5af4ca146102535780633ff5aa0214610268575b5f5ffd5b6102096102043660046114f1565b6104f3565b60405190151581526020015b60405180910390f35b6102457fe5c50d0927e06141e032cb9a67e1d7092dc85c0b0825191f7e1cede60002856881565b604051908152602001610215565b61026661026136600461152c565b610539565b005b61026661027636600461157a565b610553565b61026661028936600461157a565b610567565b610296610578565b6040516102159190611595565b6102096102b136600461157a565b610588565b6040805180820190915260058152640332e302e360dc1b60208201525b60405161021591906115e0565b6102096102ee36600461157a565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0390811691161490565b61026661032e366004611615565b610593565b61033b6105aa565b6040516001600160a01b039091168152602001610215565b6102666105cc565b61020961036936600461152c565b6105df565b6102666105fc565b7f000000000000000000000000000000000000000000000000000000000000000061033b565b6102d36103aa36600461164d565b610663565b6102666103bd366004611668565b61066e565b6102666103d0366004611615565b610686565b6004546001600160a01b031661033b565b6102096103f436600461157a565b610699565b6102457fea5f4eb72290e50c32abd6c23e45de3d8300b3286e1cbc2e293114b92e034e5e81565b6102666106a5565b6102666104363660046116a6565b6106b5565b6102456107e1565b61045661045136600461152c565b6107eb565b60405160ff9091168152602001610215565b610456610476366004611668565b610801565b61033b610489366004611717565b610817565b61026661049c36600461157a565b610839565b6005546001600160a01b031661033b565b6102666104c036600461157a565b610871565b6102096104d3366004611668565b6108df565b6102966108f8565b6102666104ee36600461157a565b610904565b5f6104fd82610975565b8061051857506001600160e01b031982166307f5828d60e41b145b8061053357506001600160e01b031982166301ffc9a760e01b145b92915050565b6105416109e0565b61054d84848484610a10565b50505050565b61055b610ab2565b61056481610aba565b50565b61056f610ab2565b61056481610b72565b60606105835f610bfb565b905090565b5f6105338183610c07565b61059b6109e0565b6105a65f8383610c27565b5050565b5f5f6105b66002610cc0565b11156105c75761058360025f610cc9565b505f90565b6105d4610cd4565b6105dd5f610d32565b565b5f806105ed868686866107eb565b60ff161490505b949350505050565b5f610605610d4b565b9050806001600160a01b03166106236005546001600160a01b031690565b6001600160a01b03161461065a5760405163118cdaa760e01b81526001600160a01b03821660048201526024015b60405180910390fd5b61056481610d32565b606061053382610d54565b6106766109e0565b610681838383610c27565b505050565b61068e6109e0565b6105a6825f83610c27565b5f610533600283610c07565b6106ad610ab2565b6105dd610e9e565b6106bd610ab2565b5f8190036106de576040516359203cb960e01b815260040160405180910390fd5b5f6106e85f610cc0565b11156106f6576106f6610e9e565b5f5b818110156106815761072f8383838181106107155761071561172e565b905060200201602081019061072a919061157a565b610ecf565b6107608383838181106107445761074461172e565b9050602002016020810190610759919061157a565b5f90610f06565b61077d5760405163f280d16160e01b815260040160405180910390fd5b82828281811061078f5761078f61172e565b90506020020160208101906107a4919061157a565b6001600160a01b03167f60305ce6c9104acd0969d358f926bf391174340660aaf5e6215261fd6847bf4660405160405180910390a26001016106f8565b5f6105835f610cc0565b5f6107f885858585610f1a565b95945050505050565b5f61080d848484610fe5565b90505b9392505050565b5f6108215f610cc0565b821015610832576105335f83610cc9565b505f919050565b610841610ab2565b61084b5f82610c07565b61086857604051632cdc3a4160e21b815260040160405180910390fd5b610564816110a7565b610879610ab2565b61088281610ecf565b61088c5f82610f06565b6108a95760405163f280d16160e01b815260040160405180910390fd5b6040516001600160a01b038216907f60305ce6c9104acd0969d358f926bf391174340660aaf5e6215261fd6847bf46905f90a250565b5f806108ec858585610801565b60ff1614949350505050565b60606105836002610bfb565b61090c610cd4565b600580546001600160a01b0383166001600160a01b0319909116811790915561093d6004546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b5f6001600160e01b031982166320c49ce760e01b14806109a557506001600160e01b031982166378a8de7d60e01b145b806109c057506001600160e01b03198216630c51264760e21b145b8061053357506001600160e01b03198216637157797f60e01b1492915050565b6109f36109eb610d4b565b600290610c07565b6105dd5760405163e39b3c8f60e01b815260040160405180910390fd5b5f610a1a5f610cc0565b90505f5b81811015610aaa57610a305f82610cc9565b604051631f2d7a6560e11b81526001600160a01b03888116600483015287811660248301528681166044830152606482018690529190911690633e5af4ca906084015f604051808303815f87803b158015610a89575f5ffd5b505af1158015610a9b573d5f5f3e3d5ffd5b50505050806001019050610a1e565b505050505050565b6105dd610cd4565b6001600160a01b038116610ae1576040516301b8831760e71b815260040160405180910390fd5b610aec600282610c07565b15610b0a5760405163f423354760e01b815260040160405180910390fd5b610b15600282610f06565b610b3257604051631b4ddcf360e11b815260040160405180910390fd5b6040516001600160a01b03821681527f2de35142b19ed5a07796cf30791959c592018f70b1d2d7c460eef8ffe713692b906020015b60405180910390a150565b610b7d600282610c07565b610b9a57604051636a2b488360e11b815260040160405180910390fd5b610ba5600282611104565b610bc257604051631b4ddcf360e11b815260040160405180910390fd5b6040516001600160a01b03821681527f28a4ca7134a3b3f9aff286e79ad3daadb4a06d1b43d037a3a98bdc074edd9b7a90602001610b67565b60605f61081083611118565b6001600160a01b03165f9081526001919091016020526040902054151590565b5f610c315f610cc0565b90505f5b81811015610cb957610c475f82610cc9565b6040516322ebca6d60e21b81526001600160a01b0387811660048301528681166024830152604482018690529190911690638baf29b4906064015f604051808303815f87803b158015610c98575f5ffd5b505af1158015610caa573d5f5f3e3d5ffd5b50505050806001019050610c35565b5050505050565b5f610533825490565b5f6108108383611171565b610cdc610d4b565b6001600160a01b0316610cf76004546001600160a01b031690565b6001600160a01b0316146105dd57610d0d610d4b565b60405163118cdaa760e01b81526001600160a01b039091166004820152602401610651565b600580546001600160a01b031916905561056481611197565b5f6105836111e8565b60605f610d5f6107e1565b90505f5b81811015610e6257610d7481610817565b604051633e822efb60e11b815260ff861660048201526001600160a01b039190911690637d045df690602401602060405180830381865afa158015610dbb573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ddf9190611742565b15610e5a57610ded81610817565b604051637f4ab1dd60e01b815260ff861660048201526001600160a01b039190911690637f4ab1dd906024015f60405180830381865afa158015610e33573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526105f49190810190611775565b600101610d63565b505060408051808201909152601881527f556e6b6e6f776e207265737472696374696f6e20636f64650000000000000000602082015292915050565b6040517fdbf61473843cd9be1c9791ce51ef66d0da6c9026d62ba80c1ca433b13fb729b2905f90a16105dd5f6111f1565b610ed8816111fa565b610ee981632497d6cb60e01b611249565b61056457604051639952e34360e01b815260040160405180910390fd5b5f610810836001600160a01b038416611264565b5f5f610f246107e1565b90505f5b81811015610fd9575f610f3a82610817565b60405163d32c7bb560e01b81526001600160a01b038a811660048301528981166024830152888116604483015260648201889052919091169063d32c7bb590608401602060405180830381865afa158015610f97573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610fbb9190611828565b905060ff811615610fd05792506105f4915050565b50600101610f28565b505f9695505050505050565b5f5f610fef6107e1565b90505f5b8181101561109c575f61100582610817565b60405163d4ce141560e01b81526001600160a01b038981166004830152888116602483015260448201889052919091169063d4ce141590606401602060405180830381865afa15801561105a573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061107e9190611828565b905060ff811615611093579250610810915050565b50600101610ff3565b505f95945050505050565b6110b15f82611104565b6110ce5760405163f280d16160e01b815260040160405180910390fd5b6040516001600160a01b038216907f6d83315c9718799346b67584ec64301b1457e989c8e35a8e2982a7776c04bfc4905f90a250565b5f610810836001600160a01b0384166112b0565b6060815f0180548060200260200160405190810160405280929190818152602001828054801561116557602002820191905f5260205f20905b815481526020019060010190808311611151575b50505050509050919050565b5f825f0182815481106111865761118661172e565b905f5260205f200154905092915050565b600480546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b5f61058361139a565b61056481611404565b6001600160a01b0381166112215760405163f9d152fb60e01b815260040160405180910390fd5b61122b5f82610c07565b156105645760405163cc790a4b60e01b815260040160405180910390fd5b5f6112538361145d565b80156108105750610810838361149c565b5f8181526001830160205260408120546112a957508154600181810184555f848152602080822090930184905584548482528286019093526040902091909155610533565b505f610533565b5f818152600183016020526040812054801561138a575f6112d2600183611843565b85549091505f906112e590600190611843565b9050808214611344575f865f0182815481106113035761130361172e565b905f5260205f200154905080875f0184815481106113235761132361172e565b5f918252602080832090910192909255918252600188019052604090208390555b855486908061135557611355611862565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f905560019350505050610533565b5f915050610533565b5092915050565b5f3660148082108015906113d657507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031633145b156113fc576113e936828403815f611876565b6113f29161189d565b60601c9250505090565b339250505090565b5f61140d825490565b90505f5b8181101561145657826001015f845f0183815481106114325761143261172e565b905f5260205f20015481526020019081526020015f205f9055806001019050611411565b50505f9055565b5f61146f826301ffc9a760e01b61149c565b15610832575f80611488846001600160e01b03196114bd565b915091508180156105f45750159392505050565b5f5f5f6114a985856114bd565b915091508180156107f85750949350505050565b6301ffc9a760e01b5f818152600483905290819060208260248188617530fa92505f511515601f3d11169150509250929050565b5f60208284031215611501575f5ffd5b81356001600160e01b031981168114610810575f5ffd5b6001600160a01b0381168114610564575f5ffd5b5f5f5f5f6080858703121561153f575f5ffd5b843561154a81611518565b9350602085013561155a81611518565b9250604085013561156a81611518565b9396929550929360600135925050565b5f6020828403121561158a575f5ffd5b813561081081611518565b602080825282518282018190525f918401906040840190835b818110156115d55783516001600160a01b03168352602093840193909201916001016115ae565b509095945050505050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b5f5f60408385031215611626575f5ffd5b823561163181611518565b946020939093013593505050565b60ff81168114610564575f5ffd5b5f6020828403121561165d575f5ffd5b81356108108161163f565b5f5f5f6060848603121561167a575f5ffd5b833561168581611518565b9250602084013561169581611518565b929592945050506040919091013590565b5f5f602083850312156116b7575f5ffd5b823567ffffffffffffffff8111156116cd575f5ffd5b8301601f810185136116dd575f5ffd5b803567ffffffffffffffff8111156116f3575f5ffd5b8560208260051b8401011115611707575f5ffd5b6020919091019590945092505050565b5f60208284031215611727575f5ffd5b5035919050565b634e487b7160e01b5f52603260045260245ffd5b5f60208284031215611752575f5ffd5b81518015158114610810575f5ffd5b634e487b7160e01b5f52604160045260245ffd5b5f60208284031215611785575f5ffd5b815167ffffffffffffffff81111561179b575f5ffd5b8201601f810184136117ab575f5ffd5b805167ffffffffffffffff8111156117c5576117c5611761565b604051601f8201601f19908116603f0116810167ffffffffffffffff811182821017156117f4576117f4611761565b60405281815282820160200186101561180b575f5ffd5b8160208401602083015e5f91810160200191909152949350505050565b5f60208284031215611838575f5ffd5b81516108108161163f565b8181038181111561053357634e487b7160e01b5f52601160045260245ffd5b634e487b7160e01b5f52603160045260245ffd5b5f5f85851115611884575f5ffd5b83861115611890575f5ffd5b5050820193919092039150565b80356bffffffffffffffffffffffff198116906014841015611393576bffffffffffffffffffffffff1960149490940360031b84901b169092169291505056fea2646970667358221220112af4469313f66a43c96817f27e5105f6d280d5212be301d8cd5f7becaaa13464736f6c63430008220033","sourceMap":"467:1692:165:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1091:257:162;;;;;;:::i;:::-;;:::i;:::-;;;470:14:231;;463:22;445:41;;433:2;418:18;1091:257:162;;;;;;;;729:86:186;;779:36;729:86;;;;;643:25:231;;;631:2;616:18;729:86:186;497:177:231;1726:276:161;;;;;;:::i;:::-;;:::i;:::-;;1846:114:186;;;;;;:::i;:::-;;:::i;2223:118::-;;;;;;:::i;:::-;;:::i;4499:136:187:-;;;:::i;:::-;;;;;;;:::i;3804:158::-;;;;;;:::i;:::-;;:::i;692:129:188:-;807:7;;;;;;;;;;;;-1:-1:-1;;;807:7:188;;;;692:129;;;;;;;:::i;1874:137:135:-;;;;;;:::i;:::-;1749:17;-1:-1:-1;;;;;1973:31:135;;;;;;;1874:137;2328:155:161;;;;;;:::i;:::-;;:::i;2564:382:186:-;;;:::i;:::-;;;-1:-1:-1;;;;;3590:32:231;;;3572:51;;3560:2;3545:18;2564:382:186;3426:203:231;2293:101:128;;;:::i;4340:311:161:-;;;;;;:::i;:::-;;:::i;2244:229:129:-;;;:::i;1666:107:135:-;1749:17;1666:107;;3695:240:161;;;;;;:::i;:::-;;:::i;2071:212::-;;;;;;:::i;:::-;;:::i;2528:161::-;;;;;;:::i;:::-;;:::i;1638:85:128:-;1710:6;;-1:-1:-1;;;;;1710:6:128;1638:85;;2386:133:186;;;;;;:::i;:::-;;:::i;1199:82:192:-;;1247:34;1199:82;;2485:117:187;;;:::i;1781:640::-;;;;;;:::i;:::-;;:::i;3608:132::-;;;:::i;3363:282:161:-;;;;;;:::i;:::-;;:::i;:::-;;;5498:4:231;5486:17;;;5468:36;;5456:2;5441:18;3363:282:161;5326:184:231;3065:242:161;;;;;;:::i;:::-;;:::i;4026:409:187:-;;;;;;:::i;:::-;;:::i;3258:234::-;;;;;;:::i;:::-;;:::i;1232:99:129:-;1311:13;;-1:-1:-1;;;;;1311:13:129;1232:99;;2923:271:187;;;;;;:::i;:::-;;:::i;3999:281:161:-;;;;;;:::i;:::-;;:::i;2991:119:186:-;;;:::i;1649:178:129:-;;;;;;:::i;:::-;;:::i;1091:257:162:-;1167:4;1190:45;1223:11;1190:32;:45::i;:::-;:95;;;-1:-1:-1;;;;;;;1251:34:162;;-1:-1:-1;;;1251:34:162;1190:95;:151;;;-1:-1:-1;;;;;;;1301:40:162;;-1:-1:-1;;;1301:40:162;1190:151;1183:158;1091:257;-1:-1:-1;;1091:257:162:o;1726:276:161:-;1217:18:186;:16;:18::i;:::-;1935:60:161::1;1970:7;1979:4;1985:2;1989:5;1935:34;:60::i;:::-;1726:276:::0;;;;:::o;1846:114:186:-;1302:24;:22;:24::i;:::-;1936:17:::1;1947:5;1936:10;:17::i;:::-;1846:114:::0;:::o;2223:118::-;1302:24;:22;:24::i;:::-;2315:19:::1;2328:5;2315:12;:19::i;4499:136:187:-:0;4578:16;4613:15;:6;:13;:15::i;:::-;4606:22;;4499:136;:::o;3804:158::-;3901:4;3924:31;3901:4;3948:5;3924:15;:31::i;2328:155:161:-;1217:18:186;:16;:18::i;:::-;2441:35:161::1;2462:1;2466:2;2470:5;2441:12;:35::i;:::-;2328:155:::0;;:::o;2564:382:186:-;2627:7;2674:1;2650:21;:12;:19;:21::i;:::-;:25;2646:294;;;2863:18;:12;2879:1;2863:15;:18::i;2646:294::-;-1:-1:-1;2927:1:186;;2564:382::o;2293:101:128:-;1531:13;:11;:13::i;:::-;2357:30:::1;2384:1;2357:18;:30::i;:::-;2293:101::o:0;4340:311:161:-;4521:4;;4548:55;4578:7;4587:4;4593:2;4597:5;4548:29;:55::i;:::-;:96;;;4541:103;;4340:311;;;;;;;:::o;2244:229:129:-;2296:14;2313:12;:10;:12::i;:::-;2296:29;;2357:6;-1:-1:-1;;;;;2339:24:129;:14;1311:13;;-1:-1:-1;;;;;1311:13:129;;1232:99;2339:14;-1:-1:-1;;;;;2339:24:129;;2335:96;;2386:34;;-1:-1:-1;;;2386:34:129;;-1:-1:-1;;;;;3590:32:231;;2386:34:129;;;3572:51:231;3545:18;;2386:34:129;;;;;;;;2335:96;2440:26;2459:6;2440:18;:26::i;3695:240:161:-;3845:13;3881:47;3912:15;3881:30;:47::i;2071:212::-;1217:18:186;:16;:18::i;:::-;2247:29:161::1;2260:4;2266:2;2270:5;2247:12;:29::i;:::-;2071:212:::0;;;:::o;2528:161::-;1217:18:186;:16;:18::i;:::-;2645:37:161::1;2658:4;2672:1;2676:5;2645:12;:37::i;2386:133:186:-:0;2461:4;2484:28;:12;2506:5;2484:21;:28::i;2485:117:187:-;643:19;:17;:19::i;:::-;2582:13:::1;:11;:13::i;1781:640::-:0;643:19;:17;:19::i;:::-;1920:1:::1;1903:18:::0;;;1899:103:::1;;1944:47;;-1:-1:-1::0;;;1944:47:187::1;;;;;;;;;;;1899:103;2033:1;2015:15;:6;:13;:15::i;:::-;:19;2011:63;;;2050:13;:11;:13::i;:::-;2088:9;2083:332;2103:17:::0;;::::1;2083:332;;;2141:30;2160:6;;2167:1;2160:9;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;2141:10;:30::i;:::-;2277;2296:6;;2303:1;2296:9;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;2277:6;::::0;:10:::1;:30::i;:::-;2269:98;;;;-1:-1:-1::0;;;2269:98:187::1;;;;;;;;;;;;2394:6;;2401:1;2394:9;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1::0;;;;;2386:18:187::1;;;;;;;;;;;2122:3;;2083:332;;3608:132:::0;3692:7;3718:15;:6;:13;:15::i;3363:282:161:-;3554:5;3582:56;3613:7;3622:4;3628:2;3632:5;3582:30;:56::i;:::-;3575:63;3363:282;-1:-1:-1;;;;;3363:282:161:o;3065:242::-;3229:5;3257:43;3284:4;3290:2;3294:5;3257:26;:43::i;:::-;3250:50;;3065:242;;;;;;:::o;4026:409:187:-;4118:7;4150:15;:6;:13;:15::i;:::-;4141:6;:24;4137:292;;;4353:17;:6;4363;4353:9;:17::i;4137:292::-;-1:-1:-1;4416:1:187;;4026:409;-1:-1:-1;4026:409:187:o;3258:234::-;643:19;:17;:19::i;:::-;3374:31:::1;:6;3398:5:::0;3374:15:::1;:31::i;:::-;3366:91;;;;-1:-1:-1::0;;;3366:91:187::1;;;;;;;;;;;;3467:18;3479:5;3467:11;:18::i;2923:271::-:0;643:19;:17;:19::i;:::-;3028:26:::1;3047:5;3028:10;:26::i;:::-;3072;:6;3091:5:::0;3072:10:::1;:26::i;:::-;3064:94;;;;-1:-1:-1::0;;;3064:94:187::1;;;;;;;;;;;;3173:14;::::0;-1:-1:-1;;;;;3173:14:187;::::1;::::0;::::1;::::0;;;::::1;2923:271:::0;:::o;3999:281:161:-;4163:4;;4190:42;4216:4;4222:2;4226:5;4190:25;:42::i;:::-;:83;;;;3999:281;-1:-1:-1;;;;3999:281:161:o;2991:119:186:-;3047:16;3082:21;:12;:19;:21::i;1649:178:129:-;1531:13:128;:11;:13::i;:::-;1738::129::1;:24:::0;;-1:-1:-1;;;;;1738:24:129;::::1;-1:-1:-1::0;;;;;;1738:24:129;;::::1;::::0;::::1;::::0;;;1802:7:::1;1710:6:128::0;;-1:-1:-1;;;;;1710:6:128;;1638:85;1802:7:129::1;-1:-1:-1::0;;;;;1777:43:129::1;;;;;;;;;;;1649:178:::0;:::o;7167:427:161:-;7252:4;-1:-1:-1;;;;;;7275:61:161;;-1:-1:-1;;;7275:61:161;;:143;;-1:-1:-1;;;;;;;7352:66:161;;-1:-1:-1;;;7352:66:161;7275:143;:227;;;-1:-1:-1;;;;;;;7434:68:161;;-1:-1:-1;;;7434:68:161;7275:227;:312;;;-1:-1:-1;;;;;;;7518:69:161;;-1:-1:-1;;;7518:69:161;7268:319;7167:427;-1:-1:-1;;7167:427:161:o;4153:188:186:-;4217:35;4239:12;:10;:12::i;:::-;4217;;:21;:35::i;:::-;4212:123;;4275:49;;-1:-1:-1;;;4275:49:186;;;;;;;;;;;7278:284:187;7385:19;7407:15;:6;:13;:15::i;:::-;7385:37;-1:-1:-1;7437:9:187;7432:124;7456:11;7452:1;:15;7432:124;;;7494:12;:6;7504:1;7494:9;:12::i;:::-;7488:57;;-1:-1:-1;;;7488:57:187;;-1:-1:-1;;;;;6259:32:231;;;7488:57:187;;;6241:51:231;6328:32;;;6308:18;;;6301:60;6397:32;;;6377:18;;;6370:60;6446:18;;;6439:34;;;7488:31:187;;;;;;;6213:19:231;;7488:57:187;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;7469:3;;;;;7432:124;;;;7375:187;7278:284;;;;:::o;1257:72:165:-;1531:13:128;:11;:13::i;3688:459:186:-;-1:-1:-1;;;;;3750:19:186;;3742:80;;;;-1:-1:-1;;;3742:80:186;;;;;;;;;;;;3841:28;:12;3863:5;3841:21;:28::i;:::-;3840:29;3832:88;;;;-1:-1:-1;;;3832:88:186;;;;;;;;;;;;4029:23;:12;4046:5;4029:16;:23::i;:::-;4021:87;;;;-1:-1:-1;;;4021:87:186;;;;;;;;;;;;4123:17;;-1:-1:-1;;;;;3590:32:231;;3572:51;;4123:17:186;;3560:2:231;3545:18;4123:17:186;;;;;;;;3688:459;:::o;3310:372::-;3374:28;:12;3396:5;3374:21;:28::i;:::-;3366:83;;;;-1:-1:-1;;;3366:83:186;;;;;;;;;;;;3558:26;:12;3578:5;3558:19;:26::i;:::-;3550:90;;;;-1:-1:-1;;;3550:90:186;;;;;;;;;;;;3656:19;;-1:-1:-1;;;;;3590:32:231;;3572:51;;3656:19:186;;3560:2:231;3545:18;3656:19:186;3426:203:231;17440:273:158;17503:16;17531:22;17556:19;17564:3;17556:7;:19::i;16041:165::-;-1:-1:-1;;;;;16174:23:158;16121:4;5238:21;;;:14;;;;;:21;;;;;;:26;;;16041:165::o;6464:258:187:-;6554:19;6576:15;:6;:13;:15::i;:::-;6554:37;-1:-1:-1;6606:9:187;6601:115;6625:11;6621:1;:15;6601:115;;;6663:12;:6;6673:1;6663:9;:12::i;:::-;6657:48;;-1:-1:-1;;;6657:48:187;;-1:-1:-1;;;;;6704:32:231;;;6657:48:187;;;6686:51:231;6773:32;;;6753:18;;;6746:60;6822:18;;;6815:34;;;6657:31:187;;;;;;;6659:18:231;;6657:48:187;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6638:3;;;;;6601:115;;;;6544:178;6464:258;;;:::o;16287:115:158:-;16350:7;16376:19;16384:3;5434:18;;5352:107;16744:156;16818:7;16868:22;16872:3;16884:5;16868:3;:22::i;1796:162:128:-;1866:12;:10;:12::i;:::-;-1:-1:-1;;;;;1855:23:128;:7;1710:6;;-1:-1:-1;;;;;1710:6:128;;1638:85;1855:7;-1:-1:-1;;;;;1855:23:128;;1851:101;;1928:12;:10;:12::i;:::-;1901:40;;-1:-1:-1;;;1901:40:128;;-1:-1:-1;;;;;3590:32:231;;;1901:40:128;;;3572:51:231;3545:18;;1901:40:128;3426:203:231;2011:153:129;2100:13;2093:20;;-1:-1:-1;;;;;;2093:20:129;;;2123:34;2148:8;2123:24;:34::i;1430:172:165:-;1526:14;1559:36;:34;:36::i;6166:449:161:-;6260:13;6285:19;6307:12;:10;:12::i;:::-;6285:34;-1:-1:-1;6334:9:161;6329:237;6353:11;6349:1;:15;6329:237;;;6395:7;6400:1;6395:4;:7::i;:::-;6389:64;;-1:-1:-1;;;6389:64:161;;5498:4:231;5486:17;;6389:64:161;;;5468:36:231;-1:-1:-1;;;;;6389:47:161;;;;;;;5441:18:231;;6389:64:161;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;6385:171;;;6486:7;6491:1;6486:4;:7::i;:::-;6480:61;;-1:-1:-1;;;6480:61:161;;5498:4:231;5486:17;;6480:61:161;;;5468:36:231;-1:-1:-1;;;;;6480:44:161;;;;;;;5441:18:231;;6480:61:161;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;6480:61:161;;;;;;;;;;;;:::i;6385:171::-;6366:3;;6329:237;;;-1:-1:-1;;6575:33:161;;;;;;;;;;;;;;;;;;6166:449;-1:-1:-1;;6166:449:161:o;4914:98:187:-;4969:12;;;;;;;4991:14;:6;:12;:14::i;6719:261:161:-;6795:23;6812:5;6795:16;:23::i;:::-;6833:74;6865:5;-1:-1:-1;;;6833:31:161;:74::i;:::-;6828:146;;6930:33;;-1:-1:-1;;;6930:33:161;;;;;;;;;;;15089:150:158;15159:4;15182:50;15187:3;-1:-1:-1;;;;;15207:23:158;;15182:4;:50::i;5314:528:161:-;5475:5;5496:19;5518:12;:10;:12::i;:::-;5496:34;-1:-1:-1;5545:9:161;5540:242;5564:11;5560:1;:15;5540:242;;;5596:17;5622:7;5627:1;5622:4;:7::i;:::-;5616:70;;-1:-1:-1;;;5616:70:161;;-1:-1:-1;;;;;6259:32:231;;;5616:70:161;;;6241:51:231;6328:32;;;6308:18;;;6301:60;6397:32;;;6377:18;;;6370:60;6446:18;;;6439:34;;;5616:44:161;;;;;;;6213:19:231;;5616:70:161;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;5596:90;-1:-1:-1;5704:15:161;;;;5700:72;;5746:11;-1:-1:-1;5739:18:161;;-1:-1:-1;;5739:18:161;5700:72;-1:-1:-1;5577:3:161;;5540:242;;;-1:-1:-1;5804:30:161;5791:44;5314:528;-1:-1:-1;;;;;;5314:528:161:o;4850:458::-;4958:5;4975:19;4997:12;:10;:12::i;:::-;4975:34;-1:-1:-1;5024:9:161;5019:229;5043:11;5039:1;:15;5019:229;;;5075:17;5101:7;5106:1;5101:4;:7::i;:::-;5095:57;;-1:-1:-1;;;5095:57:161;;-1:-1:-1;;;;;6704:32:231;;;5095:57:161;;;6686:51:231;6773:32;;;6753:18;;;6746:60;6822:18;;;6815:34;;;5095:40:161;;;;;;;6659:18:231;;5095:57:161;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;5075:77;-1:-1:-1;5170:15:161;;;;5166:72;;5212:11;-1:-1:-1;5205:18:161;;-1:-1:-1;;5205:18:161;5166:72;-1:-1:-1;5056:3:161;;5019:229;;;-1:-1:-1;5270:30:161;5257:44;4850:458;-1:-1:-1;;;;;4850:458:161:o;5239:277:187:-;5388:29;:6;5410:5;5388:13;:29::i;:::-;5380:97;;;;-1:-1:-1;;;5380:97:187;;;;;;;;;;;;5492:17;;-1:-1:-1;;;;;5492:17:187;;;;;;;;5239:277;:::o;15407:156:158:-;15480:4;15503:53;15511:3;-1:-1:-1;;;;;15531:23:158;;15503:7;:53::i;6459:109::-;6515:16;6550:3;:11;;6543:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6459:109;;;:::o;5801:118::-;5868:7;5894:3;:11;;5906:5;5894:18;;;;;;;;:::i;:::-;;;;;;;;;5887:25;;5801:118;;;;:::o;2912:187:128:-;3004:6;;;-1:-1:-1;;;;;3020:17:128;;;-1:-1:-1;;;;;;3020:17:128;;;;;;;3052:40;;3004:6;;;3020:17;3004:6;;3052:40;;2985:16;;3052:40;2975:124;2912:187;:::o;1624:154:162:-;1711:14;1744:27;:25;:27::i;15877:83:158:-;15935:18;15942:3;15935:6;:18::i;5593:313:187:-;-1:-1:-1;;;;;5664:21:187;;5660:119;;5708:60;;-1:-1:-1;;;5708:60:187;;;;;;;;;;;5660:119;5792:22;:6;5808:5;5792:15;:22::i;:::-;5788:112;;;5837:52;;-1:-1:-1;;;5837:52:187;;;;;;;;;;;1465:283:153;1552:4;1660:23;1675:7;1660:14;:23::i;:::-;:81;;;;;1687:54;1720:7;1729:11;1687:32;:54::i;2538:406:158:-;2601:4;5238:21;;;:14;;;:21;;;;;;2617:321;;-1:-1:-1;2659:23:158;;;;;;;;:11;:23;;;;;;;;;;;;;2841:18;;2817:21;;;:14;;;:21;;;;;;:42;;;;2873:11;;2617:321;-1:-1:-1;2922:5:158;2915:12;;3112:1368;3178:4;3307:21;;;:14;;;:21;;;;;;3343:13;;3339:1135;;3710:18;3731:12;3742:1;3731:8;:12;:::i;:::-;3777:18;;3710:33;;-1:-1:-1;3757:17:158;;3777:22;;3798:1;;3777:22;:::i;:::-;3757:42;;3832:9;3818:10;:23;3814:378;;3861:17;3881:3;:11;;3893:9;3881:22;;;;;;;;:::i;:::-;;;;;;;;;3861:42;;4028:9;4002:3;:11;;4014:10;4002:23;;;;;;;;:::i;:::-;;;;;;;;;;;;:35;;;;4141:25;;;:14;;;:25;;;;;:36;;;3814:378;4270:17;;:3;;:17;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;4373:3;:14;;:21;4388:5;4373:21;;;;;;;;;;;4366:28;;;4416:4;4409:11;;;;;;;3339:1135;4458:5;4451:12;;;;;3339:1135;3184:1296;3112:1368;;;;:::o;2248:471:135:-;2310:7;2354:8;3609:2;2445:37;;;;;;:71;;-1:-1:-1;1749:17:135;-1:-1:-1;;;;;1973:31:135;2505:10;1973:31;2486:30;2441:272;;;2583:47;:8;2592:36;;;2583:8;;:47;:::i;:::-;2575:56;;;:::i;:::-;2567:65;;2560:72;;;;2248:471;:::o;2441:272::-;735:10:143;2677:25:135;;;;2248:471;:::o;4824:237:158:-;4875:11;4889:12;4897:3;5434:18;;5352:107;4889:12;4875:26;-1:-1:-1;4916:9:158;4911:96;4935:3;4931:1;:7;4911:96;;;4966:3;:14;;:30;4981:3;:11;;4993:1;4981:14;;;;;;;;:::i;:::-;;;;;;;;;4966:30;;;;;;;;;;;4959:37;;;4940:3;;;;;4911:96;;;-1:-1:-1;;5039:11:158;33920:23:140;;2328:155:161:o;719:528:153:-;783:4;976:68;1009:7;-1:-1:-1;;;976:32:153;:68::i;:::-;972:269;;;1061:12;;1093:52;1115:7;-1:-1:-1;;;;;;1093:21:153;:52::i;:::-;1060:85;;;;1166:7;:21;;;;-1:-1:-1;1177:10:153;;1159:28;-1:-1:-1;;;719:528:153:o;4504:238::-;4606:4;4623:12;4637:14;4655:43;4677:7;4686:11;4655:21;:43::i;:::-;4622:76;;;;4715:7;:20;;;;-1:-1:-1;4726:9:153;4708:27;-1:-1:-1;;;;4504:238:153:o;5198:628::-;-1:-1:-1;;;5310:12:153;5452:22;;;5494:4;5487:25;;;5310:12;;;5581:4;5310:12;5569:4;5310:12;5554:7;5547:5;5536:50;5525:61;;5740:4;5734:11;5727:19;5720:27;5654:4;5636:16;5633:26;5612:198;5599:211;;5438:382;5198:628;;;;;:::o;14:286:231:-;72:6;125:2;113:9;104:7;100:23;96:32;93:52;;;141:1;138;131:12;93:52;167:23;;-1:-1:-1;;;;;;219:32:231;;209:43;;199:71;;266:1;263;256:12;679:131;-1:-1:-1;;;;;754:31:231;;744:42;;734:70;;800:1;797;790:12;815:650;901:6;909;917;925;978:3;966:9;957:7;953:23;949:33;946:53;;;995:1;992;985:12;946:53;1034:9;1021:23;1053:31;1078:5;1053:31;:::i;:::-;1103:5;-1:-1:-1;1160:2:231;1145:18;;1132:32;1173:33;1132:32;1173:33;:::i;:::-;1225:7;-1:-1:-1;1284:2:231;1269:18;;1256:32;1297:33;1256:32;1297:33;:::i;:::-;815:650;;;;-1:-1:-1;1349:7:231;;1429:2;1414:18;1401:32;;-1:-1:-1;;815:650:231:o;1470:247::-;1529:6;1582:2;1570:9;1561:7;1557:23;1553:32;1550:52;;;1598:1;1595;1588:12;1550:52;1637:9;1624:23;1656:31;1681:5;1656:31;:::i;1722:637::-;1912:2;1924:21;;;1994:13;;1897:18;;;2016:22;;;1864:4;;2095:15;;;2069:2;2054:18;;;1864:4;2138:195;2152:6;2149:1;2146:13;2138:195;;;2217:13;;-1:-1:-1;;;;;2213:39:231;2201:52;;2282:2;2308:15;;;;2273:12;;;;2249:1;2167:9;2138:195;;;-1:-1:-1;2350:3:231;;1722:637;-1:-1:-1;;;;;1722:637:231:o;2631:418::-;2780:2;2769:9;2762:21;2743:4;2812:6;2806:13;2855:6;2850:2;2839:9;2835:18;2828:34;2914:6;2909:2;2901:6;2897:15;2892:2;2881:9;2877:18;2871:50;2970:1;2965:2;2956:6;2945:9;2941:22;2937:31;2930:42;3040:2;3033;3029:7;3024:2;3016:6;3012:15;3008:29;2997:9;2993:45;2989:54;2981:62;;;2631:418;;;;:::o;3054:367::-;3122:6;3130;3183:2;3171:9;3162:7;3158:23;3154:32;3151:52;;;3199:1;3196;3189:12;3151:52;3238:9;3225:23;3257:31;3282:5;3257:31;:::i;:::-;3307:5;3385:2;3370:18;;;;3357:32;;-1:-1:-1;;;3054:367:231:o;3634:114::-;3718:4;3711:5;3707:16;3700:5;3697:27;3687:55;;3738:1;3735;3728:12;3753:243;3810:6;3863:2;3851:9;3842:7;3838:23;3834:32;3831:52;;;3879:1;3876;3869:12;3831:52;3918:9;3905:23;3937:29;3960:5;3937:29;:::i;4001:508::-;4078:6;4086;4094;4147:2;4135:9;4126:7;4122:23;4118:32;4115:52;;;4163:1;4160;4153:12;4115:52;4202:9;4189:23;4221:31;4246:5;4221:31;:::i;:::-;4271:5;-1:-1:-1;4328:2:231;4313:18;;4300:32;4341:33;4300:32;4341:33;:::i;:::-;4001:508;;4393:7;;-1:-1:-1;;;4473:2:231;4458:18;;;;4445:32;;4001:508::o;4514:625::-;4615:6;4623;4676:2;4664:9;4655:7;4651:23;4647:32;4644:52;;;4692:1;4689;4682:12;4644:52;4732:9;4719:23;4765:18;4757:6;4754:30;4751:50;;;4797:1;4794;4787:12;4751:50;4820:22;;4873:4;4865:13;;4861:27;-1:-1:-1;4851:55:231;;4902:1;4899;4892:12;4851:55;4942:2;4929:16;4968:18;4960:6;4957:30;4954:50;;;5000:1;4997;4990:12;4954:50;5053:7;5048:2;5038:6;5035:1;5031:14;5027:2;5023:23;5019:32;5016:45;5013:65;;;5074:1;5071;5064:12;5013:65;5105:2;5097:11;;;;;5127:6;;-1:-1:-1;4514:625:231;-1:-1:-1;;;4514:625:231:o;5515:226::-;5574:6;5627:2;5615:9;5606:7;5602:23;5598:32;5595:52;;;5643:1;5640;5633:12;5595:52;-1:-1:-1;5688:23:231;;5515:226;-1:-1:-1;5515:226:231:o;5878:127::-;5939:10;5934:3;5930:20;5927:1;5920:31;5970:4;5967:1;5960:15;5994:4;5991:1;5984:15;6860:277;6927:6;6980:2;6968:9;6959:7;6955:23;6951:32;6948:52;;;6996:1;6993;6986:12;6948:52;7028:9;7022:16;7081:5;7074:13;7067:21;7060:5;7057:32;7047:60;;7103:1;7100;7093:12;7142:127;7203:10;7198:3;7194:20;7191:1;7184:31;7234:4;7231:1;7224:15;7258:4;7255:1;7248:15;7274:935;7354:6;7407:2;7395:9;7386:7;7382:23;7378:32;7375:52;;;7423:1;7420;7413:12;7375:52;7456:9;7450:16;7489:18;7481:6;7478:30;7475:50;;;7521:1;7518;7511:12;7475:50;7544:22;;7597:4;7589:13;;7585:27;-1:-1:-1;7575:55:231;;7626:1;7623;7616:12;7575:55;7659:2;7653:9;7685:18;7677:6;7674:30;7671:56;;;7707:18;;:::i;:::-;7756:2;7750:9;7848:2;7810:17;;-1:-1:-1;;7806:31:231;;;7839:2;7802:40;7798:54;7786:67;;7883:18;7868:34;;7904:22;;;7865:62;7862:88;;;7930:18;;:::i;:::-;7966:2;7959:22;7990;;;8031:15;;;8048:2;8027:24;8024:37;-1:-1:-1;8021:57:231;;;8074:1;8071;8064:12;8021:57;8123:6;8118:2;8114;8110:11;8105:2;8097:6;8093:15;8087:43;8176:1;8150:19;;;8171:2;8146:28;8139:39;;;;8154:6;7274:935;-1:-1:-1;;;;7274:935:231:o;8214:247::-;8282:6;8335:2;8323:9;8314:7;8310:23;8306:32;8303:52;;;8351:1;8348;8341:12;8303:52;8383:9;8377:16;8402:29;8425:5;8402:29;:::i;8466:225::-;8533:9;;;8554:11;;;8551:134;;;8607:10;8602:3;8598:20;8595:1;8588:31;8642:4;8639:1;8632:15;8670:4;8667:1;8660:15;8696:127;8757:10;8752:3;8748:20;8745:1;8738:31;8788:4;8785:1;8778:15;8812:4;8809:1;8802:15;8828:331;8933:9;8944;8986:8;8974:10;8971:24;8968:44;;;9008:1;9005;8998:12;8968:44;9037:6;9027:8;9024:20;9021:40;;;9057:1;9054;9047:12;9021:40;-1:-1:-1;;9083:23:231;;;9128:25;;;;;-1:-1:-1;8828:331:231:o;9164:374::-;9285:19;;-1:-1:-1;;9322:40:231;;;9382:2;9374:11;;9371:161;;;-1:-1:-1;;9444:2:231;9440:12;;;;9437:1;9433:20;9429:58;;;9421:67;9417:105;;;;9164:374;-1:-1:-1;;9164:374:231:o","linkReferences":{},"immutableReferences":{"55852":[{"start":752,"length":32},{"start":888,"length":32},{"start":5035,"length":32}]}},"methodIdentifiers":{"COMPLIANCE_MANAGER_ROLE()":"03c26bcd","RULES_MANAGEMENT_ROLE()":"9b11c115","acceptOwnership()":"79ba5097","addRule(address)":"e3c4602c","bindToken(address)":"3ff5aa02","canTransfer(address,address,uint256)":"e46638e6","canTransferFrom(address,address,address,uint256)":"7157797f","clearRules()":"b043572e","containsRule(address)":"54e4b945","created(address,uint256)":"5f8dead3","destroyed(address,uint256)":"8d2ea772","detectTransferRestriction(address,address,uint256)":"d4ce1415","detectTransferRestrictionFrom(address,address,address,uint256)":"d32c7bb5","getTokenBound()":"6a3edf28","getTokenBounds()":"e54621d2","isTokenBound(address)":"993e8b95","isTrustedForwarder(address)":"572b6c05","messageForTransferRestriction(uint8)":"7f4ab1dd","owner()":"8da5cb5b","pendingOwner()":"e30c3978","removeRule(address)":"df21950f","renounceOwnership()":"715018a6","rule(uint256)":"db18af6c","rules()":"52f6747a","rulesCount()":"bc13eacc","setRules(address[])":"b27aef3a","supportsInterface(bytes4)":"01ffc9a7","transferOwnership(address)":"f2fde38b","transferred(address,address,address,uint256)":"3e5af4ca","transferred(address,address,uint256)":"8baf29b4","trustedForwarder()":"7da0a877","unbindToken(address)":"40db3b50","version()":"54fd4d50"},"rawMetadata":"{\"compiler\":{\"version\":\"0.8.34+commit.80d5c536\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"forwarderIrrevocable\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenContract\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"OwnableInvalidOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"OwnableUnauthorizedAccount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_AdminWithAddressZeroNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_ERC3643Compliance_InvalidTokenAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_ERC3643Compliance_OperationNotSuccessful\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_ERC3643Compliance_TokenAlreadyBound\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_ERC3643Compliance_TokenNotBound\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_ERC3643Compliance_UnauthorizedCaller\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_RuleInvalidInterface\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_RulesManagementModule_ArrayIsEmpty\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_RulesManagementModule_OperationNotSuccessful\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_RulesManagementModule_RuleAddressZeroNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_RulesManagementModule_RuleAlreadyExists\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_RulesManagementModule_RuleDoNotMatch\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract IRule\",\"name\":\"rule\",\"type\":\"address\"}],\"name\":\"AddRule\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"ClearRules\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferStarted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract IRule\",\"name\":\"rule\",\"type\":\"address\"}],\"name\":\"RemoveRule\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"TokenBound\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"TokenUnbound\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"COMPLIANCE_MANAGER_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"RULES_MANAGEMENT_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IRule\",\"name\":\"rule_\",\"type\":\"address\"}],\"name\":\"addRule\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"bindToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"canTransfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"canTransferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"clearRules\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IRule\",\"name\":\"rule_\",\"type\":\"address\"}],\"name\":\"containsRule\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"created\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"destroyed\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"detectTransferRestriction\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"detectTransferRestrictionFrom\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTokenBound\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTokenBounds\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"isTokenBound\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"}],\"name\":\"isTrustedForwarder\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"restrictionCode\",\"type\":\"uint8\"}],\"name\":\"messageForTransferRestriction\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingOwner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IRule\",\"name\":\"rule_\",\"type\":\"address\"}],\"name\":\"removeRule\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"ruleId\",\"type\":\"uint256\"}],\"name\":\"rule\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"rules\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"rulesCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IRule[]\",\"name\":\"rules_\",\"type\":\"address[]\"}],\"name\":\"setRules\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"transferred\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"transferred\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"trustedForwarder\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"unbindToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"version_\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"errors\":{\"OwnableInvalidOwner(address)\":[{\"details\":\"The owner is not a valid owner account. (eg. `address(0)`)\"}],\"OwnableUnauthorizedAccount(address)\":[{\"details\":\"The caller account is not authorized to perform an operation.\"}]},\"events\":{\"AddRule(address)\":{\"params\":{\"rule\":\"The address of the rule contract that was added.\"}},\"RemoveRule(address)\":{\"params\":{\"rule\":\"The address of the rule contract that was removed.\"}},\"TokenBound(address)\":{\"params\":{\"token\":\"The address of the token that was bound.\"}},\"TokenUnbound(address)\":{\"params\":{\"token\":\"The address of the token that was unbound.\"}}},\"kind\":\"dev\",\"methods\":{\"acceptOwnership()\":{\"details\":\"The new owner accepts the ownership transfer.\"},\"addRule(address)\":{\"details\":\"No on-chain maximum number of rules is enforced. Adding too many rules can increase transfer-time gas usage because rule checks are linear in rule count. Security convention: do not grant {RULES_MANAGEMENT_ROLE} to rule contracts.\",\"params\":{\"rule_\":\"The IRule contract to add.\"}},\"bindToken(address)\":{\"details\":\"Operator warning: \\\"multi-tenant\\\" means one RuleEngine is shared by multiple token contracts. In that setup, bind only tokens that are equally trusted and governed together.\",\"params\":{\"token\":\"The address of the token to bind.\"}},\"canTransfer(address,address,uint256)\":{\"details\":\"Don't check the balance and the user's right (access control)\"},\"canTransferFrom(address,address,address,uint256)\":{\"details\":\"Does not check balances or access rights (Access Control).\",\"params\":{\"from\":\"The source address.\",\"spender\":\"The address performing the transfer.\",\"to\":\"The destination address.\",\"value\":\"The number of tokens to transfer.\"},\"returns\":{\"_0\":\"isCompliant True if the transfer complies with policy.\"}},\"clearRules()\":{\"details\":\"After calling this function, no rules will remain set. Developers should keep in mind that this function has an unbounded cost and using it may render the function uncallable if the set grows to the point where clearing it consumes too much gas to fit in a block.\"},\"constructor\":{\"params\":{\"forwarderIrrevocable\":\"Address of the forwarder, required for the gasless support\",\"owner_\":\"Address of the contract owner (ERC-173)\",\"tokenContract\":\"Address of the token contract to bind (can be zero address)\"}},\"containsRule(address)\":{\"details\":\"Complexity: O(1).\",\"params\":{\"rule_\":\"The IRule contract to check for membership.\"},\"returns\":{\"_0\":\"True if the rule is present, false otherwise.\"}},\"created(address,uint256)\":{\"details\":\"Called by the token contract when new tokens are issued to an account. Reverts if the minting does not comply with the rules.\",\"params\":{\"to\":\"The address receiving the minted tokens.\",\"value\":\"The number of tokens created.\"}},\"destroyed(address,uint256)\":{\"details\":\"Called by the token contract when tokens are redeemed or burned. Reverts if the burning does not comply with the rules.\",\"params\":{\"from\":\"The address whose tokens are being destroyed.\",\"value\":\"The number of tokens destroyed.\"}},\"detectTransferRestriction(address,address,uint256)\":{\"params\":{\"from\":\"the origin address\",\"to\":\"the destination address\",\"value\":\"to transfer\"},\"returns\":{\"_0\":\"The restricion code or REJECTED_CODE_BASE.TRANSFER_OK (0) if the transfer is valid\"}},\"detectTransferRestrictionFrom(address,address,address,uint256)\":{\"details\":\" See {ERC-1404} Add an additionnal argument `spender` This function is where an issuer enforces the restriction logic of their token transfers. Some examples of this might include: - checking if the token recipient is whitelisted, - checking if a sender's tokens are frozen in a lock-up period, etc.\",\"returns\":{\"_0\":\"uint8 restricted code, 0 means the transfer is authorized\"}},\"getTokenBound()\":{\"details\":\"If multiple tokens are supported, consider using getTokenBounds().\",\"returns\":{\"_0\":\"The address of the currently bound token.\"}},\"getTokenBounds()\":{\"details\":\"This is a view-only function and does not modify state. This function is not part of the original ERC-3643 specification This operation will copy the entire storage to memory, which can be quite expensive. This is designed to mostly be used by view accessors that are queried without any gas fees.\",\"returns\":{\"_0\":\"An array of addresses of bound token contracts.\"}},\"isTokenBound(address)\":{\"details\":\"Complexity: O(1). Note that there are no guarantees on the ordering of values inside the array, and it may change when more values are added or removed.\",\"params\":{\"token\":\"The token address to verify.\"},\"returns\":{\"_0\":\"True if the token is bound, false otherwise.\"}},\"isTrustedForwarder(address)\":{\"details\":\"Indicates whether any particular address is the trusted forwarder.\"},\"messageForTransferRestriction(uint8)\":{\"details\":\"See {ERC-1404} This function is effectively an accessor for the \\\"message\\\", a human-readable explanation as to why a transaction is restricted. \"},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pendingOwner()\":{\"details\":\"Returns the address of the pending owner.\"},\"removeRule(address)\":{\"details\":\"Reverts if the provided rule is not found or does not match the stored rule at its index. Complexity: O(1).\",\"params\":{\"rule_\":\"The IRule contract to remove.\"}},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.\"},\"rule(uint256)\":{\"details\":\"Reverts if `ruleId` is out of bounds. Complexity: O(1). Note that there are no guarantees on the ordering of values inside the array, and it may change when more values are added or removed.\",\"params\":{\"ruleId\":\"The index of the desired rule in the array.\"},\"returns\":{\"_0\":\"The address of the corresponding IRule contract, return the `zero address` is out of bounds.\"}},\"rules()\":{\"details\":\"This is a view-only function that does not modify state. This operation will copy the entire storage to memory, which can be quite expensive. This is designed to mostly be used by view accessors that are queried without any gas fees.\",\"returns\":{\"_0\":\"An array of all active rule contract addresses.\"}},\"rulesCount()\":{\"details\":\"Equivalent to the length of the internal rules array. Complexity: O(1)\",\"returns\":{\"_0\":\"The number of active rules.\"}},\"setRules(address[])\":{\"details\":\"Replaces the entire rule set atomically. Reverts if `rules_` is empty. Use {clearRules} to remove all rules explicitly. To transition from one non-empty set to another without an enforcement gap, call this function directly with the new set. No on-chain maximum number of rules is enforced. Operators are responsible for keeping the rule set size compatible with the target chain gas limits. Security convention: rule contracts should be treated as trusted business logic, but should not also be granted {RULES_MANAGEMENT_ROLE}.\",\"params\":{\"rules_\":\"The array of addresses representing the new rules to be set.\"}},\"supportsInterface(bytes4)\":{\"details\":\"Returns true if this contract implements the interface defined by `interfaceId`. See the corresponding https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section] to learn more about how these ids are created. This function call must use less than 30 000 gas.\"},\"transferOwnership(address)\":{\"details\":\"Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. Can only be called by the current owner. Setting `newOwner` to the zero address is allowed; this can be used to cancel an initiated ownership transfer.\"},\"transferred(address,address,address,uint256)\":{\"details\":\" Must revert if the transfer is invalid Same name as ERC-3643 but with one supplementary argument `spender` This function can be used to update state variables of the RuleEngine contract This function can be called ONLY by the token contract bound to the RuleEngine\",\"params\":{\"from\":\"token holder address\",\"spender\":\"spender address (sender)\",\"to\":\"receiver address\",\"value\":\"value of tokens involved in the transfer\"}},\"transferred(address,address,uint256)\":{\"details\":\" This function can be used to update state variables of the compliance contract This function can be called ONLY by the token contract bound to the compliance\",\"params\":{\"from\":\"The address of the sender\",\"to\":\"The address of the receiver\",\"value\":\"value of tokens involved in the transfer\"}},\"trustedForwarder()\":{\"details\":\"Returns the address of the trusted forwarder.\"},\"unbindToken(address)\":{\"details\":\"Operator warning: unbinding is an administrative operation and does not erase any state already stored by external rule contracts in a previously shared (\\\"multi-tenant\\\") setup.\",\"params\":{\"token\":\"The address of the token to unbind.\"}},\"version()\":{\"details\":\"This value is useful to know which smart contract version has been used\",\"returns\":{\"version_\":\"A string representing the version of the token implementation (e.g., \\\"1.0.0\\\").\"}}},\"title\":\"Implementation of a ruleEngine with ERC-173 Ownable2Step access control\",\"version\":1},\"userdoc\":{\"events\":{\"AddRule(address)\":{\"notice\":\"Emitted when a new rule is added to the rule set.\"},\"ClearRules()\":{\"notice\":\"Emitted when all rules are cleared from the rule set.\"},\"RemoveRule(address)\":{\"notice\":\"Emitted when a rule is removed from the rule set.\"},\"TokenBound(address)\":{\"notice\":\"Emitted when a token is successfully bound to the compliance contract.\"},\"TokenUnbound(address)\":{\"notice\":\"Emitted when a token is successfully unbound from the compliance contract.\"}},\"kind\":\"user\",\"methods\":{\"RULES_MANAGEMENT_ROLE()\":{\"notice\":\"Role to manage the ruleEngine\"},\"addRule(address)\":{\"notice\":\"Adds a new rule to the current rule set.\"},\"bindToken(address)\":{\"notice\":\"Associates a token contract with this compliance contract.\"},\"canTransfer(address,address,uint256)\":{\"notice\":\"Returns true if the transfer is valid, and false otherwise.\"},\"canTransferFrom(address,address,address,uint256)\":{\"notice\":\"Checks if `spender` can transfer `value` tokens from `from` to `to` under compliance rules.\"},\"clearRules()\":{\"notice\":\"Removes all configured rules.\"},\"containsRule(address)\":{\"notice\":\"Checks whether a specific rule is currently configured.\"},\"created(address,uint256)\":{\"notice\":\"Updates the compliance contract state when tokens are created (minted).\"},\"destroyed(address,uint256)\":{\"notice\":\"Updates the compliance contract state when tokens are destroyed (burned).\"},\"detectTransferRestriction(address,address,uint256)\":{\"notice\":\"Go through all the rule to know if a restriction exists on the transfer\"},\"detectTransferRestrictionFrom(address,address,address,uint256)\":{\"notice\":\"Returns a uint8 code to indicate if a transfer is restricted or not\"},\"getTokenBound()\":{\"notice\":\"Returns the single token currently bound to this compliance contract.\"},\"getTokenBounds()\":{\"notice\":\"Returns all tokens currently bound to this compliance contract.\"},\"isTokenBound(address)\":{\"notice\":\"Checks whether a token is currently bound to this compliance contract.\"},\"removeRule(address)\":{\"notice\":\"Removes a specific rule from the current rule set.\"},\"rule(uint256)\":{\"notice\":\"Retrieves the rule address at a specific index.\"},\"rules()\":{\"notice\":\"Returns the full list of currently configured rules.\"},\"rulesCount()\":{\"notice\":\"Returns the total number of currently configured rules.\"},\"setRules(address[])\":{\"notice\":\"Defines the rules for the rule engine.\"},\"transferred(address,address,address,uint256)\":{\"notice\":\"Function called whenever tokens are transferred from one wallet to another\"},\"transferred(address,address,uint256)\":{\"notice\":\"Function called whenever tokens are transferred from one wallet to another\"},\"unbindToken(address)\":{\"notice\":\"Removes the association of a token contract from this compliance contract.\"},\"version()\":{\"notice\":\"Returns the current version of the token contract.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/deployment/RuleEngineOwnable2Step.sol\":\"RuleEngineOwnable2Step\"},\"evmVersion\":\"prague\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[\":@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\":@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\":CMTAT/=lib/CMTAT/contracts/\",\":CMTATv3.0.0/=lib/CMTATv3.0.0/contracts/\",\":erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/\",\":forge-std/=lib/forge-std/src/\",\":halmos-cheatcodes/=lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/\",\":openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\":openzeppelin-contracts/=lib/openzeppelin-contracts/\"]},\"sources\":{\"lib/CMTAT/contracts/interfaces/engine/IRuleEngine.sol\":{\"keccak256\":\"0x524a2cf2214a82fb96e97a18a94956fee68a419ecd6b2dc841aa1105f336c3f1\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://9c4728d80b6678101586515c0308c63bcba2a78b0a3c12d37b522d59f3175a01\",\"dweb:/ipfs/QmYP9SPbe2hB69jKkSg43qkz1HVxBayKrG14i9f6hx7hh8\"]},\"lib/CMTAT/contracts/interfaces/technical/IERC5679.sol\":{\"keccak256\":\"0xcc6f2e79d1d9eabcf4c7ffcbd85c0de31bb2b3cdf17eb847dffb7c2d2a8c4695\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://d618bc2be7c6bc167037fe57ca648523c671c61791f3f0c65965ab7139d6dc33\",\"dweb:/ipfs/QmSrCKWFjpg1SQ7v2k3vRyWpcU9dB6Pbk167R4oAzUc2Te\"]},\"lib/CMTAT/contracts/interfaces/tokenization/IERC3643Partial.sol\":{\"keccak256\":\"0x1707381177447b1a398c443c7e753942df0c5d4633e80d2864db472e89e43dc0\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://c4281d98847629b67222332bea67f336623937758be908ee9ca1aa40b3abe19d\",\"dweb:/ipfs/QmZQBruKJH3sStjBmCb28rxRkUkZ4EFsDCi8WZ7Y85spxS\"]},\"lib/CMTAT/contracts/interfaces/tokenization/draft-IERC1404.sol\":{\"keccak256\":\"0x17fb1f64b546fd882331dffbd8c7f4e53c51738b9e2621a0dcfcf30e64d8b66e\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://c35fe277d5d99a0943293b5da5622947095e6b719af35fda9ef2c714a7879a4b\",\"dweb:/ipfs/QmRV5q3XvjJE8sxJJBpEkwk1qyz3r4McH2BdX1v2ZxZGZh\"]},\"lib/CMTAT/contracts/interfaces/tokenization/draft-IERC7551.sol\":{\"keccak256\":\"0x709074d96bd5d7aa07d2ba3a1c9a99ae0fd4361f7322b528b42f3b83c5dcb984\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://ca67a06011b746b55bf2465988dc10a4e6371e40b5108c54531f03e938bda865\",\"dweb:/ipfs/QmbjFyDAJsUXywqzU2s96pFqFpC5DLKdfa8WjMBtQPhKGE\"]},\"lib/CMTAT/contracts/interfaces/tokenization/draft-IERC7943.sol\":{\"keccak256\":\"0x1a341fc7ee7d9b8b00b6168b35a6a844d90431749d8ca694174c52c41e11763f\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://4fb6b13953539b99262cb299961fb8ff8a020de79b12f76c63decf33ff9d5103\",\"dweb:/ipfs/QmQ3bnkQJgD2s6xpapThCPTSMbDREokVEiM7extwQgfrv7\"]},\"lib/CMTAT/contracts/library/ERC1404ExtendInterfaceId.sol\":{\"keccak256\":\"0xe5f6f08d319d27f20989936460d3947eed5fdcb470f80e920f4fb09ccc7e1e87\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://cb654fe37c2bc6c765c67c5f94a769580312d1d4109c50262677ac406362f91e\",\"dweb:/ipfs/Qmc8ZFVANCmULNozM2wFUSGKXBgUHR5bpDC3ZVjV4XoEv7\"]},\"lib/CMTAT/contracts/library/RuleEngineInterfaceId.sol\":{\"keccak256\":\"0x759990208069b5a0862a255eff790d52d1d64bbb6c334705fc12414936825692\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://0bce1c17cbbddac4bf123f602dc980246e5bec724f5ed3107e148548b930e124\",\"dweb:/ipfs/QmRZUxmRN9ji9UYueD6knhnz2nSsDRZgRTX74uenGczVjA\"]},\"lib/openzeppelin-contracts/contracts/access/Ownable.sol\":{\"keccak256\":\"0xff6d0bb2e285473e5311d9d3caacb525ae3538a80758c10649a4d61029b017bb\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://8ed324d3920bb545059d66ab97d43e43ee85fd3bd52e03e401f020afb0b120f6\",\"dweb:/ipfs/QmfEckWLmZkDDcoWrkEvMWhms66xwTLff9DDhegYpvHo1a\"]},\"lib/openzeppelin-contracts/contracts/access/Ownable2Step.sol\":{\"keccak256\":\"0xdcad8898fda432696597752e8ec361b87d85c82cb258115427af006dacf7128c\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://e2c9d517f0c136d54bd00cd57959d25681d4d6273f5bbbc263afe228303772f0\",\"dweb:/ipfs/QmReNFjXBiufByiAAzfSQ2SM5r3qeUErn46BmN3yVRvrek\"]},\"lib/openzeppelin-contracts/contracts/interfaces/IERC165.sol\":{\"keccak256\":\"0x0afcb7e740d1537b252cb2676f600465ce6938398569f09ba1b9ca240dde2dfc\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://1c299900ac4ec268d4570ecef0d697a3013cd11a6eb74e295ee3fbc945056037\",\"dweb:/ipfs/Qmab9owJoxcA7vJT5XNayCMaUR1qxqj1NDzzisduwaJMcZ\"]},\"lib/openzeppelin-contracts/contracts/metatx/ERC2771Context.sol\":{\"keccak256\":\"0x9695d220b99dcf62910533bdf5d40d4cf6a4e04d5b106b6803a80586486dc7f7\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://83b7aecd65882d8953643dce144efe91367082cc01830c9c4ed3c8a4837fb558\",\"dweb:/ipfs/QmQ5HxGavcCKjuhd8buv177qjG6A4kvxx4pZviceKdspdM\"]},\"lib/openzeppelin-contracts/contracts/utils/Arrays.sol\":{\"keccak256\":\"0xb3b81029526a4c3acf39e57cc446407141ebce338cc99585942af1340e1a69e0\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://3857ce97e8f7a51ad78ea5419b3386e18fcc8af73b65803eedd8193ab7abc9df\",\"dweb:/ipfs/QmSQi6x2cYsUy76mfMNwuq151bVmh4kAND141kjume51Aq\"]},\"lib/openzeppelin-contracts/contracts/utils/Comparators.sol\":{\"keccak256\":\"0x302eecd8cf323b4690e3494a7d960b3cbce077032ab8ef655b323cdd136cec58\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://49ba706f1bc476d68fe6c1fad75517acea4e9e275be0989b548e292eb3a3eacd\",\"dweb:/ipfs/QmeBpvcdGWzWMKTQESUCEhHgnEQYYATVwPxLMxa6vMT7jC\"]},\"lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"keccak256\":\"0x493033a8d1b176a037b2cc6a04dad01a5c157722049bbecf632ca876224dd4b2\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6a708e8a5bdb1011c2c381c9a5cfd8a9a956d7d0a9dc1bd8bcdaf52f76ef2f12\",\"dweb:/ipfs/Qmax9WHBnVsZP46ZxEMNRQpLQnrdE4dK8LehML1Py8FowF\"]},\"lib/openzeppelin-contracts/contracts/utils/Panic.sol\":{\"keccak256\":\"0xf7fe324703a64fc51702311dc51562d5cb1497734f074e4f483bfb6717572d7a\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c6a5ff4f9fd8649b7ee20800b7fa387d3465bd77cf20c2d1068cd5c98e1ed57a\",\"dweb:/ipfs/QmVSaVJf9FXFhdYEYeCEfjMVHrxDh5qL4CGkxdMWpQCrqG\"]},\"lib/openzeppelin-contracts/contracts/utils/SlotDerivation.sol\":{\"keccak256\":\"0x94045fd4f268edf2b2d01ef119268548c320366d6f5294ad30c1b8f9d4f5225f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://edfda81f426f8948b3834115c21e83c48180e6db0d2a8cd2debb2185ed349337\",\"dweb:/ipfs/QmdYZneFyDAux1BuWQxLAdqtABrGS2k9WYCa7C9dvpKkWv\"]},\"lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol\":{\"keccak256\":\"0xcf74f855663ce2ae00ed8352666b7935f6cddea2932fdf2c3ecd30a9b1cd0e97\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://9f660b1f351b757dfe01438e59888f31f33ded3afcf5cb5b0d9bf9aa6f320a8b\",\"dweb:/ipfs/QmarDJ5hZEgBtCmmrVzEZWjub9769eD686jmzb2XpSU1cM\"]},\"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165Checker.sol\":{\"keccak256\":\"0x7c7ad70641a7f8cd44def0857ec97b0e40bfd073b2d6037a5f57ce9527ee9bc5\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://e05c6572dfe769f7aea6f3a8002951cc12d143d980dad29f6c5feedf9408bc14\",\"dweb:/ipfs/QmXM7C8YEptxisZiEefXUrwdXt3zMaCobmkCchxTtDg1oK\"]},\"lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"keccak256\":\"0x8891738ffe910f0cf2da09566928589bf5d63f4524dd734fd9cedbac3274dd5c\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://971f954442df5c2ef5b5ebf1eb245d7105d9fbacc7386ee5c796df1d45b21617\",\"dweb:/ipfs/QmadRjHbkicwqwwh61raUEapaVEtaLMcYbQZWs9gUkgj3u\"]},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"keccak256\":\"0x59973a93b1f983f94e10529f46ca46544a9fec2b5f56fb1390bbe9e0dc79f857\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c55ef8f0b9719790c2ae6f81d80a59ffb89f2f0abe6bc065585bd79edce058c5\",\"dweb:/ipfs/QmNNmCbX9NjPXKqHJN8R1WC2rNeZSQrPZLd6FF6AKLyH5Y\"]},\"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\":{\"keccak256\":\"0xc8cae21c9ae4a46e5162ff9bf5b351d6fa6a6eba72d515f3bc1bdfeda7fdf083\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://ce830ebcf28e31643caba318996db3763c36d52cd0f23798ba83c135355d45e9\",\"dweb:/ipfs/QmdGPcvptHN7UBCbUYBbRX3hiRVRFLRwno8b4uga6uFNif\"]},\"lib/openzeppelin-contracts/contracts/utils/structs/EnumerableSet.sol\":{\"keccak256\":\"0x5c298e834696707e274a71a224969d36faecd928a8076603210d67d091adb4ae\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://a93fe967b4d55b31157164cbb7e3e1ebaf3535fc1d3f8d0156da7abb9b565d90\",\"dweb:/ipfs/QmXH7nyxwEUeMPFDDmkdUwqxLEcezaSmVyunyMAuck1WqR\"]},\"src/RuleEngineBase.sol\":{\"keccak256\":\"0x9edae8ce7df18638cf56b571be18251d4ac4c435844c8cd77d1f7f651623c568\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://9758c7256a994b371c00d9e0098be5d76d9896f2a556208dfb83768d4d4e916b\",\"dweb:/ipfs/QmdZwwiB29tzheoaoRWiJdbbGMH2nM46ojLp7WFjm9D19h\"]},\"src/RuleEngineOwnableShared.sol\":{\"keccak256\":\"0xbe119365533074f6f59227e4b74432e03407f553f13c8361c21166f1fbb67f19\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://22b0689c774191b4065d1eda22d040fc79211f83e41f018dfe4bfcae7a328a57\",\"dweb:/ipfs/QmS9EgzvD45x72bNpMW3hyMQHfPyyBJN24iJmAuR1cEjpc\"]},\"src/deployment/RuleEngineOwnable2Step.sol\":{\"keccak256\":\"0xb38e07dc3fca6e25f18ce11dbef8af3692ac8f5c115c45adf01f854d9b68efb5\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://1cee543cfeab07d772c245ced21140273fc5c2b9bd106f72bc971cc70ae0c726\",\"dweb:/ipfs/QmSDgmt41PpCDU6XRWkipgJtcMoh2VSr7ttBDfsQ7oJ9rT\"]},\"src/interfaces/IERC3643Compliance.sol\":{\"keccak256\":\"0xf86e78e8f737795c3762b402b121b0f1822d6b27414aeca08ea6f036cccea07b\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://c795d1b89a1393b2225f6e58c0310d345d78ff534ab028353413c4a5aaf9ecf7\",\"dweb:/ipfs/QmNcJsJzLWzSAV77whMzu7je2Mj2pWoTYYn1z76kqB5mKH\"]},\"src/interfaces/IRule.sol\":{\"keccak256\":\"0x315fd1d0147d40d3cc1ee35f6ddb8c9e25e6e4f96034a285e6f342c59c3cc222\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://5b0ecca410bf89169e5c6393bc4d8fce97a5b3dcf8a2bba02317da85c98f4d0c\",\"dweb:/ipfs/QmeGS5vbFwkmEvJh7s27Q9xW4xGXuUohh2zGPVbgxgjfnu\"]},\"src/interfaces/IRulesManagementModule.sol\":{\"keccak256\":\"0x1be8087ef526f664cf8ba5dd35d4d12fc1880f905e3ba2e553ee02cb7d6506c1\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://545cafd73f2fe9b2b89b37e905057637f58ae2c1da7f3dc33493b515c87a720f\",\"dweb:/ipfs/QmXiTEhLSpN6sj1fiwFT9V6bGD1VCXTqQJiNnXcLrYmW7N\"]},\"src/modules/ERC2771ModuleStandalone.sol\":{\"keccak256\":\"0xecc9aec20ff41c46404f6fcb9bfb0fd5588781fbb4f2fbec351f603a31c178b0\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://48674e77afe59b6c6e6aa8b0d5e370ca58c9a354b5dc294bb3c9f10fbd12a3f3\",\"dweb:/ipfs/QmY3HhbBDqsBvrGBXoRwgVpfSNtiK2XmhaxVpS1F3dSPx9\"]},\"src/modules/ERC3643ComplianceModule.sol\":{\"keccak256\":\"0xdb472471270ea23d4694ca2d2eb107ce668affc9dbe18b5a6eda312ab4800a33\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://6200e990afca50a32fb0a0ad76ffe955447a67cab6e93f64281fc9f14208aab1\",\"dweb:/ipfs/QmXXhRsBq3eGDgBqQwWL5w4Sn6pdTeeXRvpC4jZBDVb6nQ\"]},\"src/modules/RulesManagementModule.sol\":{\"keccak256\":\"0xc9c58e027874658577285de9c9bf9069cd773573a615df7c9644c6c96c69dbc3\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://a6c9ca74cc247b42b9852b35cb4eeadc919d383d7bbd4f4df0739ee6a8bce2c3\",\"dweb:/ipfs/QmfJCvSQjqQrQXYt9JEHiJRZATy1s7q53DKxZC1QsSYMHZ\"]},\"src/modules/VersionModule.sol\":{\"keccak256\":\"0x077070dca24da125a764111d336c0a8fb3445b82d93692ff76b22384b0f4f39f\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://be8df88e667fb2de39d095f0c396d23ed263fdc51a4095fedc89a326540a03ee\",\"dweb:/ipfs/QmYfhhEvNee1XYwCYZCVAKpUUWBd5FP5qvTMYGr6ogC8kA\"]},\"src/modules/library/ComplianceInterfaceId.sol\":{\"keccak256\":\"0xa0f15ca7f9e0fa8ccb854ea2bd812f220c68c280682b56e8d1a437ddba4b6d1f\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://1e01a79b4a2110a401c3d2fbead97844f7428d6dc6603dccf795d42dbc142786\",\"dweb:/ipfs/QmV88ZcDHTU33oXNLFTshUBZ7otgcZRN1HXwywda7Fgz9a\"]},\"src/modules/library/RuleEngineInvariantStorage.sol\":{\"keccak256\":\"0x15005e56f8fbf8f9b8a41c4bfed6c842e37be49fa52b0dbb2edc6b08b9e50c2f\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://06c90dd748d060cb1b05de978cb42fd79d9b49a2beb3a479b4e49f8edaba1195\",\"dweb:/ipfs/QmYXEQWrwJkuzWBdi5hjSaM6pWhrNUf2kH2pHX8jRu9dZS\"]},\"src/modules/library/RuleInterfaceId.sol\":{\"keccak256\":\"0x3c57987589d6205e2546d4ce332e944d1667dddfe897087028a95ed804c50882\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://0e1718e500d4cb5cf4441131c57d23da788f2835e9a014e7d1f62dfb6161647a\",\"dweb:/ipfs/QmXY5cjc9Dzrp7ML7DfvDB9zg7t4cene3g4K9AAuDmLLfC\"]},\"src/modules/library/RulesManagementModuleInvariantStorage.sol\":{\"keccak256\":\"0xa6f9109698f169be74c309a1efadd48edffcb0e9585523258477bf07942c8ae6\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://4c28513636b660111b60a7028c9600b30dcfda291a831343d9e27e253b80856a\",\"dweb:/ipfs/QmQVSZ9N6vjPxNnJDTqEuGSWqNdoxHKhzTzP2cvgZpBSzj\"]}},\"version\":1}","metadata":{"compiler":{"version":"0.8.34+commit.80d5c536"},"language":"Solidity","output":{"abi":[{"inputs":[{"internalType":"address","name":"owner_","type":"address"},{"internalType":"address","name":"forwarderIrrevocable","type":"address"},{"internalType":"address","name":"tokenContract","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"type":"error","name":"OwnableInvalidOwner"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"type":"error","name":"OwnableUnauthorizedAccount"},{"inputs":[],"type":"error","name":"RuleEngine_AdminWithAddressZeroNotAllowed"},{"inputs":[],"type":"error","name":"RuleEngine_ERC3643Compliance_InvalidTokenAddress"},{"inputs":[],"type":"error","name":"RuleEngine_ERC3643Compliance_OperationNotSuccessful"},{"inputs":[],"type":"error","name":"RuleEngine_ERC3643Compliance_TokenAlreadyBound"},{"inputs":[],"type":"error","name":"RuleEngine_ERC3643Compliance_TokenNotBound"},{"inputs":[],"type":"error","name":"RuleEngine_ERC3643Compliance_UnauthorizedCaller"},{"inputs":[],"type":"error","name":"RuleEngine_RuleInvalidInterface"},{"inputs":[],"type":"error","name":"RuleEngine_RulesManagementModule_ArrayIsEmpty"},{"inputs":[],"type":"error","name":"RuleEngine_RulesManagementModule_OperationNotSuccessful"},{"inputs":[],"type":"error","name":"RuleEngine_RulesManagementModule_RuleAddressZeroNotAllowed"},{"inputs":[],"type":"error","name":"RuleEngine_RulesManagementModule_RuleAlreadyExists"},{"inputs":[],"type":"error","name":"RuleEngine_RulesManagementModule_RuleDoNotMatch"},{"inputs":[{"internalType":"contract IRule","name":"rule","type":"address","indexed":true}],"type":"event","name":"AddRule","anonymous":false},{"inputs":[],"type":"event","name":"ClearRules","anonymous":false},{"inputs":[{"internalType":"address","name":"previousOwner","type":"address","indexed":true},{"internalType":"address","name":"newOwner","type":"address","indexed":true}],"type":"event","name":"OwnershipTransferStarted","anonymous":false},{"inputs":[{"internalType":"address","name":"previousOwner","type":"address","indexed":true},{"internalType":"address","name":"newOwner","type":"address","indexed":true}],"type":"event","name":"OwnershipTransferred","anonymous":false},{"inputs":[{"internalType":"contract IRule","name":"rule","type":"address","indexed":true}],"type":"event","name":"RemoveRule","anonymous":false},{"inputs":[{"internalType":"address","name":"token","type":"address","indexed":false}],"type":"event","name":"TokenBound","anonymous":false},{"inputs":[{"internalType":"address","name":"token","type":"address","indexed":false}],"type":"event","name":"TokenUnbound","anonymous":false},{"inputs":[],"stateMutability":"view","type":"function","name":"COMPLIANCE_MANAGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"RULES_MANAGEMENT_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}]},{"inputs":[],"stateMutability":"nonpayable","type":"function","name":"acceptOwnership"},{"inputs":[{"internalType":"contract IRule","name":"rule_","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"addRule"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"bindToken"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"view","type":"function","name":"canTransfer","outputs":[{"internalType":"bool","name":"","type":"bool"}]},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"view","type":"function","name":"canTransferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}]},{"inputs":[],"stateMutability":"nonpayable","type":"function","name":"clearRules"},{"inputs":[{"internalType":"contract IRule","name":"rule_","type":"address"}],"stateMutability":"view","type":"function","name":"containsRule","outputs":[{"internalType":"bool","name":"","type":"bool"}]},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"nonpayable","type":"function","name":"created"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"nonpayable","type":"function","name":"destroyed"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"view","type":"function","name":"detectTransferRestriction","outputs":[{"internalType":"uint8","name":"","type":"uint8"}]},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"view","type":"function","name":"detectTransferRestrictionFrom","outputs":[{"internalType":"uint8","name":"","type":"uint8"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"getTokenBound","outputs":[{"internalType":"address","name":"","type":"address"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"getTokenBounds","outputs":[{"internalType":"address[]","name":"","type":"address[]"}]},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"stateMutability":"view","type":"function","name":"isTokenBound","outputs":[{"internalType":"bool","name":"","type":"bool"}]},{"inputs":[{"internalType":"address","name":"forwarder","type":"address"}],"stateMutability":"view","type":"function","name":"isTrustedForwarder","outputs":[{"internalType":"bool","name":"","type":"bool"}]},{"inputs":[{"internalType":"uint8","name":"restrictionCode","type":"uint8"}],"stateMutability":"view","type":"function","name":"messageForTransferRestriction","outputs":[{"internalType":"string","name":"","type":"string"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}]},{"inputs":[{"internalType":"contract IRule","name":"rule_","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"removeRule"},{"inputs":[],"stateMutability":"nonpayable","type":"function","name":"renounceOwnership"},{"inputs":[{"internalType":"uint256","name":"ruleId","type":"uint256"}],"stateMutability":"view","type":"function","name":"rule","outputs":[{"internalType":"address","name":"","type":"address"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"rules","outputs":[{"internalType":"address[]","name":"","type":"address[]"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"rulesCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}]},{"inputs":[{"internalType":"contract IRule[]","name":"rules_","type":"address[]"}],"stateMutability":"nonpayable","type":"function","name":"setRules"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"stateMutability":"view","type":"function","name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}]},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"transferOwnership"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"nonpayable","type":"function","name":"transferred"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"nonpayable","type":"function","name":"transferred"},{"inputs":[],"stateMutability":"view","type":"function","name":"trustedForwarder","outputs":[{"internalType":"address","name":"","type":"address"}]},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"unbindToken"},{"inputs":[],"stateMutability":"view","type":"function","name":"version","outputs":[{"internalType":"string","name":"version_","type":"string"}]}],"devdoc":{"kind":"dev","methods":{"acceptOwnership()":{"details":"The new owner accepts the ownership transfer."},"addRule(address)":{"details":"No on-chain maximum number of rules is enforced. Adding too many rules can increase transfer-time gas usage because rule checks are linear in rule count. Security convention: do not grant {RULES_MANAGEMENT_ROLE} to rule contracts.","params":{"rule_":"The IRule contract to add."}},"bindToken(address)":{"details":"Operator warning: \"multi-tenant\" means one RuleEngine is shared by multiple token contracts. In that setup, bind only tokens that are equally trusted and governed together.","params":{"token":"The address of the token to bind."}},"canTransfer(address,address,uint256)":{"details":"Don't check the balance and the user's right (access control)"},"canTransferFrom(address,address,address,uint256)":{"details":"Does not check balances or access rights (Access Control).","params":{"from":"The source address.","spender":"The address performing the transfer.","to":"The destination address.","value":"The number of tokens to transfer."},"returns":{"_0":"isCompliant True if the transfer complies with policy."}},"clearRules()":{"details":"After calling this function, no rules will remain set. Developers should keep in mind that this function has an unbounded cost and using it may render the function uncallable if the set grows to the point where clearing it consumes too much gas to fit in a block."},"constructor":{"params":{"forwarderIrrevocable":"Address of the forwarder, required for the gasless support","owner_":"Address of the contract owner (ERC-173)","tokenContract":"Address of the token contract to bind (can be zero address)"}},"containsRule(address)":{"details":"Complexity: O(1).","params":{"rule_":"The IRule contract to check for membership."},"returns":{"_0":"True if the rule is present, false otherwise."}},"created(address,uint256)":{"details":"Called by the token contract when new tokens are issued to an account. Reverts if the minting does not comply with the rules.","params":{"to":"The address receiving the minted tokens.","value":"The number of tokens created."}},"destroyed(address,uint256)":{"details":"Called by the token contract when tokens are redeemed or burned. Reverts if the burning does not comply with the rules.","params":{"from":"The address whose tokens are being destroyed.","value":"The number of tokens destroyed."}},"detectTransferRestriction(address,address,uint256)":{"params":{"from":"the origin address","to":"the destination address","value":"to transfer"},"returns":{"_0":"The restricion code or REJECTED_CODE_BASE.TRANSFER_OK (0) if the transfer is valid"}},"detectTransferRestrictionFrom(address,address,address,uint256)":{"details":" See {ERC-1404} Add an additionnal argument `spender` This function is where an issuer enforces the restriction logic of their token transfers. Some examples of this might include: - checking if the token recipient is whitelisted, - checking if a sender's tokens are frozen in a lock-up period, etc.","returns":{"_0":"uint8 restricted code, 0 means the transfer is authorized"}},"getTokenBound()":{"details":"If multiple tokens are supported, consider using getTokenBounds().","returns":{"_0":"The address of the currently bound token."}},"getTokenBounds()":{"details":"This is a view-only function and does not modify state. This function is not part of the original ERC-3643 specification This operation will copy the entire storage to memory, which can be quite expensive. This is designed to mostly be used by view accessors that are queried without any gas fees.","returns":{"_0":"An array of addresses of bound token contracts."}},"isTokenBound(address)":{"details":"Complexity: O(1). Note that there are no guarantees on the ordering of values inside the array, and it may change when more values are added or removed.","params":{"token":"The token address to verify."},"returns":{"_0":"True if the token is bound, false otherwise."}},"isTrustedForwarder(address)":{"details":"Indicates whether any particular address is the trusted forwarder."},"messageForTransferRestriction(uint8)":{"details":"See {ERC-1404} This function is effectively an accessor for the \"message\", a human-readable explanation as to why a transaction is restricted. "},"owner()":{"details":"Returns the address of the current owner."},"pendingOwner()":{"details":"Returns the address of the pending owner."},"removeRule(address)":{"details":"Reverts if the provided rule is not found or does not match the stored rule at its index. Complexity: O(1).","params":{"rule_":"The IRule contract to remove."}},"renounceOwnership()":{"details":"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner."},"rule(uint256)":{"details":"Reverts if `ruleId` is out of bounds. Complexity: O(1). Note that there are no guarantees on the ordering of values inside the array, and it may change when more values are added or removed.","params":{"ruleId":"The index of the desired rule in the array."},"returns":{"_0":"The address of the corresponding IRule contract, return the `zero address` is out of bounds."}},"rules()":{"details":"This is a view-only function that does not modify state. This operation will copy the entire storage to memory, which can be quite expensive. This is designed to mostly be used by view accessors that are queried without any gas fees.","returns":{"_0":"An array of all active rule contract addresses."}},"rulesCount()":{"details":"Equivalent to the length of the internal rules array. Complexity: O(1)","returns":{"_0":"The number of active rules."}},"setRules(address[])":{"details":"Replaces the entire rule set atomically. Reverts if `rules_` is empty. Use {clearRules} to remove all rules explicitly. To transition from one non-empty set to another without an enforcement gap, call this function directly with the new set. No on-chain maximum number of rules is enforced. Operators are responsible for keeping the rule set size compatible with the target chain gas limits. Security convention: rule contracts should be treated as trusted business logic, but should not also be granted {RULES_MANAGEMENT_ROLE}.","params":{"rules_":"The array of addresses representing the new rules to be set."}},"supportsInterface(bytes4)":{"details":"Returns true if this contract implements the interface defined by `interfaceId`. See the corresponding https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[ERC section] to learn more about how these ids are created. This function call must use less than 30 000 gas."},"transferOwnership(address)":{"details":"Starts the ownership transfer of the contract to a new account. Replaces the pending transfer if there is one. Can only be called by the current owner. Setting `newOwner` to the zero address is allowed; this can be used to cancel an initiated ownership transfer."},"transferred(address,address,address,uint256)":{"details":" Must revert if the transfer is invalid Same name as ERC-3643 but with one supplementary argument `spender` This function can be used to update state variables of the RuleEngine contract This function can be called ONLY by the token contract bound to the RuleEngine","params":{"from":"token holder address","spender":"spender address (sender)","to":"receiver address","value":"value of tokens involved in the transfer"}},"transferred(address,address,uint256)":{"details":" This function can be used to update state variables of the compliance contract This function can be called ONLY by the token contract bound to the compliance","params":{"from":"The address of the sender","to":"The address of the receiver","value":"value of tokens involved in the transfer"}},"trustedForwarder()":{"details":"Returns the address of the trusted forwarder."},"unbindToken(address)":{"details":"Operator warning: unbinding is an administrative operation and does not erase any state already stored by external rule contracts in a previously shared (\"multi-tenant\") setup.","params":{"token":"The address of the token to unbind."}},"version()":{"details":"This value is useful to know which smart contract version has been used","returns":{"version_":"A string representing the version of the token implementation (e.g., \"1.0.0\")."}}},"version":1},"userdoc":{"kind":"user","methods":{"RULES_MANAGEMENT_ROLE()":{"notice":"Role to manage the ruleEngine"},"addRule(address)":{"notice":"Adds a new rule to the current rule set."},"bindToken(address)":{"notice":"Associates a token contract with this compliance contract."},"canTransfer(address,address,uint256)":{"notice":"Returns true if the transfer is valid, and false otherwise."},"canTransferFrom(address,address,address,uint256)":{"notice":"Checks if `spender` can transfer `value` tokens from `from` to `to` under compliance rules."},"clearRules()":{"notice":"Removes all configured rules."},"containsRule(address)":{"notice":"Checks whether a specific rule is currently configured."},"created(address,uint256)":{"notice":"Updates the compliance contract state when tokens are created (minted)."},"destroyed(address,uint256)":{"notice":"Updates the compliance contract state when tokens are destroyed (burned)."},"detectTransferRestriction(address,address,uint256)":{"notice":"Go through all the rule to know if a restriction exists on the transfer"},"detectTransferRestrictionFrom(address,address,address,uint256)":{"notice":"Returns a uint8 code to indicate if a transfer is restricted or not"},"getTokenBound()":{"notice":"Returns the single token currently bound to this compliance contract."},"getTokenBounds()":{"notice":"Returns all tokens currently bound to this compliance contract."},"isTokenBound(address)":{"notice":"Checks whether a token is currently bound to this compliance contract."},"removeRule(address)":{"notice":"Removes a specific rule from the current rule set."},"rule(uint256)":{"notice":"Retrieves the rule address at a specific index."},"rules()":{"notice":"Returns the full list of currently configured rules."},"rulesCount()":{"notice":"Returns the total number of currently configured rules."},"setRules(address[])":{"notice":"Defines the rules for the rule engine."},"transferred(address,address,address,uint256)":{"notice":"Function called whenever tokens are transferred from one wallet to another"},"transferred(address,address,uint256)":{"notice":"Function called whenever tokens are transferred from one wallet to another"},"unbindToken(address)":{"notice":"Removes the association of a token contract from this compliance contract."},"version()":{"notice":"Returns the current version of the token contract."}},"version":1}},"settings":{"remappings":["@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/","@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/","CMTAT/=lib/CMTAT/contracts/","CMTATv3.0.0/=lib/CMTATv3.0.0/contracts/","erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/","forge-std/=lib/forge-std/src/","halmos-cheatcodes/=lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/","openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/","openzeppelin-contracts/=lib/openzeppelin-contracts/"],"optimizer":{"enabled":true,"runs":200},"metadata":{"bytecodeHash":"ipfs"},"compilationTarget":{"src/deployment/RuleEngineOwnable2Step.sol":"RuleEngineOwnable2Step"},"evmVersion":"prague","libraries":{}},"sources":{"lib/CMTAT/contracts/interfaces/engine/IRuleEngine.sol":{"keccak256":"0x524a2cf2214a82fb96e97a18a94956fee68a419ecd6b2dc841aa1105f336c3f1","urls":["bzz-raw://9c4728d80b6678101586515c0308c63bcba2a78b0a3c12d37b522d59f3175a01","dweb:/ipfs/QmYP9SPbe2hB69jKkSg43qkz1HVxBayKrG14i9f6hx7hh8"],"license":"MPL-2.0"},"lib/CMTAT/contracts/interfaces/technical/IERC5679.sol":{"keccak256":"0xcc6f2e79d1d9eabcf4c7ffcbd85c0de31bb2b3cdf17eb847dffb7c2d2a8c4695","urls":["bzz-raw://d618bc2be7c6bc167037fe57ca648523c671c61791f3f0c65965ab7139d6dc33","dweb:/ipfs/QmSrCKWFjpg1SQ7v2k3vRyWpcU9dB6Pbk167R4oAzUc2Te"],"license":"MPL-2.0"},"lib/CMTAT/contracts/interfaces/tokenization/IERC3643Partial.sol":{"keccak256":"0x1707381177447b1a398c443c7e753942df0c5d4633e80d2864db472e89e43dc0","urls":["bzz-raw://c4281d98847629b67222332bea67f336623937758be908ee9ca1aa40b3abe19d","dweb:/ipfs/QmZQBruKJH3sStjBmCb28rxRkUkZ4EFsDCi8WZ7Y85spxS"],"license":"MPL-2.0"},"lib/CMTAT/contracts/interfaces/tokenization/draft-IERC1404.sol":{"keccak256":"0x17fb1f64b546fd882331dffbd8c7f4e53c51738b9e2621a0dcfcf30e64d8b66e","urls":["bzz-raw://c35fe277d5d99a0943293b5da5622947095e6b719af35fda9ef2c714a7879a4b","dweb:/ipfs/QmRV5q3XvjJE8sxJJBpEkwk1qyz3r4McH2BdX1v2ZxZGZh"],"license":"MPL-2.0"},"lib/CMTAT/contracts/interfaces/tokenization/draft-IERC7551.sol":{"keccak256":"0x709074d96bd5d7aa07d2ba3a1c9a99ae0fd4361f7322b528b42f3b83c5dcb984","urls":["bzz-raw://ca67a06011b746b55bf2465988dc10a4e6371e40b5108c54531f03e938bda865","dweb:/ipfs/QmbjFyDAJsUXywqzU2s96pFqFpC5DLKdfa8WjMBtQPhKGE"],"license":"MPL-2.0"},"lib/CMTAT/contracts/interfaces/tokenization/draft-IERC7943.sol":{"keccak256":"0x1a341fc7ee7d9b8b00b6168b35a6a844d90431749d8ca694174c52c41e11763f","urls":["bzz-raw://4fb6b13953539b99262cb299961fb8ff8a020de79b12f76c63decf33ff9d5103","dweb:/ipfs/QmQ3bnkQJgD2s6xpapThCPTSMbDREokVEiM7extwQgfrv7"],"license":"MPL-2.0"},"lib/CMTAT/contracts/library/ERC1404ExtendInterfaceId.sol":{"keccak256":"0xe5f6f08d319d27f20989936460d3947eed5fdcb470f80e920f4fb09ccc7e1e87","urls":["bzz-raw://cb654fe37c2bc6c765c67c5f94a769580312d1d4109c50262677ac406362f91e","dweb:/ipfs/Qmc8ZFVANCmULNozM2wFUSGKXBgUHR5bpDC3ZVjV4XoEv7"],"license":"MPL-2.0"},"lib/CMTAT/contracts/library/RuleEngineInterfaceId.sol":{"keccak256":"0x759990208069b5a0862a255eff790d52d1d64bbb6c334705fc12414936825692","urls":["bzz-raw://0bce1c17cbbddac4bf123f602dc980246e5bec724f5ed3107e148548b930e124","dweb:/ipfs/QmRZUxmRN9ji9UYueD6knhnz2nSsDRZgRTX74uenGczVjA"],"license":"MPL-2.0"},"lib/openzeppelin-contracts/contracts/access/Ownable.sol":{"keccak256":"0xff6d0bb2e285473e5311d9d3caacb525ae3538a80758c10649a4d61029b017bb","urls":["bzz-raw://8ed324d3920bb545059d66ab97d43e43ee85fd3bd52e03e401f020afb0b120f6","dweb:/ipfs/QmfEckWLmZkDDcoWrkEvMWhms66xwTLff9DDhegYpvHo1a"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/access/Ownable2Step.sol":{"keccak256":"0xdcad8898fda432696597752e8ec361b87d85c82cb258115427af006dacf7128c","urls":["bzz-raw://e2c9d517f0c136d54bd00cd57959d25681d4d6273f5bbbc263afe228303772f0","dweb:/ipfs/QmReNFjXBiufByiAAzfSQ2SM5r3qeUErn46BmN3yVRvrek"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/interfaces/IERC165.sol":{"keccak256":"0x0afcb7e740d1537b252cb2676f600465ce6938398569f09ba1b9ca240dde2dfc","urls":["bzz-raw://1c299900ac4ec268d4570ecef0d697a3013cd11a6eb74e295ee3fbc945056037","dweb:/ipfs/Qmab9owJoxcA7vJT5XNayCMaUR1qxqj1NDzzisduwaJMcZ"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/metatx/ERC2771Context.sol":{"keccak256":"0x9695d220b99dcf62910533bdf5d40d4cf6a4e04d5b106b6803a80586486dc7f7","urls":["bzz-raw://83b7aecd65882d8953643dce144efe91367082cc01830c9c4ed3c8a4837fb558","dweb:/ipfs/QmQ5HxGavcCKjuhd8buv177qjG6A4kvxx4pZviceKdspdM"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/Arrays.sol":{"keccak256":"0xb3b81029526a4c3acf39e57cc446407141ebce338cc99585942af1340e1a69e0","urls":["bzz-raw://3857ce97e8f7a51ad78ea5419b3386e18fcc8af73b65803eedd8193ab7abc9df","dweb:/ipfs/QmSQi6x2cYsUy76mfMNwuq151bVmh4kAND141kjume51Aq"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/Comparators.sol":{"keccak256":"0x302eecd8cf323b4690e3494a7d960b3cbce077032ab8ef655b323cdd136cec58","urls":["bzz-raw://49ba706f1bc476d68fe6c1fad75517acea4e9e275be0989b548e292eb3a3eacd","dweb:/ipfs/QmeBpvcdGWzWMKTQESUCEhHgnEQYYATVwPxLMxa6vMT7jC"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/Context.sol":{"keccak256":"0x493033a8d1b176a037b2cc6a04dad01a5c157722049bbecf632ca876224dd4b2","urls":["bzz-raw://6a708e8a5bdb1011c2c381c9a5cfd8a9a956d7d0a9dc1bd8bcdaf52f76ef2f12","dweb:/ipfs/Qmax9WHBnVsZP46ZxEMNRQpLQnrdE4dK8LehML1Py8FowF"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/Panic.sol":{"keccak256":"0xf7fe324703a64fc51702311dc51562d5cb1497734f074e4f483bfb6717572d7a","urls":["bzz-raw://c6a5ff4f9fd8649b7ee20800b7fa387d3465bd77cf20c2d1068cd5c98e1ed57a","dweb:/ipfs/QmVSaVJf9FXFhdYEYeCEfjMVHrxDh5qL4CGkxdMWpQCrqG"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/SlotDerivation.sol":{"keccak256":"0x94045fd4f268edf2b2d01ef119268548c320366d6f5294ad30c1b8f9d4f5225f","urls":["bzz-raw://edfda81f426f8948b3834115c21e83c48180e6db0d2a8cd2debb2185ed349337","dweb:/ipfs/QmdYZneFyDAux1BuWQxLAdqtABrGS2k9WYCa7C9dvpKkWv"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol":{"keccak256":"0xcf74f855663ce2ae00ed8352666b7935f6cddea2932fdf2c3ecd30a9b1cd0e97","urls":["bzz-raw://9f660b1f351b757dfe01438e59888f31f33ded3afcf5cb5b0d9bf9aa6f320a8b","dweb:/ipfs/QmarDJ5hZEgBtCmmrVzEZWjub9769eD686jmzb2XpSU1cM"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165Checker.sol":{"keccak256":"0x7c7ad70641a7f8cd44def0857ec97b0e40bfd073b2d6037a5f57ce9527ee9bc5","urls":["bzz-raw://e05c6572dfe769f7aea6f3a8002951cc12d143d980dad29f6c5feedf9408bc14","dweb:/ipfs/QmXM7C8YEptxisZiEefXUrwdXt3zMaCobmkCchxTtDg1oK"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol":{"keccak256":"0x8891738ffe910f0cf2da09566928589bf5d63f4524dd734fd9cedbac3274dd5c","urls":["bzz-raw://971f954442df5c2ef5b5ebf1eb245d7105d9fbacc7386ee5c796df1d45b21617","dweb:/ipfs/QmadRjHbkicwqwwh61raUEapaVEtaLMcYbQZWs9gUkgj3u"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/math/Math.sol":{"keccak256":"0x59973a93b1f983f94e10529f46ca46544a9fec2b5f56fb1390bbe9e0dc79f857","urls":["bzz-raw://c55ef8f0b9719790c2ae6f81d80a59ffb89f2f0abe6bc065585bd79edce058c5","dweb:/ipfs/QmNNmCbX9NjPXKqHJN8R1WC2rNeZSQrPZLd6FF6AKLyH5Y"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol":{"keccak256":"0xc8cae21c9ae4a46e5162ff9bf5b351d6fa6a6eba72d515f3bc1bdfeda7fdf083","urls":["bzz-raw://ce830ebcf28e31643caba318996db3763c36d52cd0f23798ba83c135355d45e9","dweb:/ipfs/QmdGPcvptHN7UBCbUYBbRX3hiRVRFLRwno8b4uga6uFNif"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/structs/EnumerableSet.sol":{"keccak256":"0x5c298e834696707e274a71a224969d36faecd928a8076603210d67d091adb4ae","urls":["bzz-raw://a93fe967b4d55b31157164cbb7e3e1ebaf3535fc1d3f8d0156da7abb9b565d90","dweb:/ipfs/QmXH7nyxwEUeMPFDDmkdUwqxLEcezaSmVyunyMAuck1WqR"],"license":"MIT"},"src/RuleEngineBase.sol":{"keccak256":"0x9edae8ce7df18638cf56b571be18251d4ac4c435844c8cd77d1f7f651623c568","urls":["bzz-raw://9758c7256a994b371c00d9e0098be5d76d9896f2a556208dfb83768d4d4e916b","dweb:/ipfs/QmdZwwiB29tzheoaoRWiJdbbGMH2nM46ojLp7WFjm9D19h"],"license":"MPL-2.0"},"src/RuleEngineOwnableShared.sol":{"keccak256":"0xbe119365533074f6f59227e4b74432e03407f553f13c8361c21166f1fbb67f19","urls":["bzz-raw://22b0689c774191b4065d1eda22d040fc79211f83e41f018dfe4bfcae7a328a57","dweb:/ipfs/QmS9EgzvD45x72bNpMW3hyMQHfPyyBJN24iJmAuR1cEjpc"],"license":"MPL-2.0"},"src/deployment/RuleEngineOwnable2Step.sol":{"keccak256":"0xb38e07dc3fca6e25f18ce11dbef8af3692ac8f5c115c45adf01f854d9b68efb5","urls":["bzz-raw://1cee543cfeab07d772c245ced21140273fc5c2b9bd106f72bc971cc70ae0c726","dweb:/ipfs/QmSDgmt41PpCDU6XRWkipgJtcMoh2VSr7ttBDfsQ7oJ9rT"],"license":"MPL-2.0"},"src/interfaces/IERC3643Compliance.sol":{"keccak256":"0xf86e78e8f737795c3762b402b121b0f1822d6b27414aeca08ea6f036cccea07b","urls":["bzz-raw://c795d1b89a1393b2225f6e58c0310d345d78ff534ab028353413c4a5aaf9ecf7","dweb:/ipfs/QmNcJsJzLWzSAV77whMzu7je2Mj2pWoTYYn1z76kqB5mKH"],"license":"MPL-2.0"},"src/interfaces/IRule.sol":{"keccak256":"0x315fd1d0147d40d3cc1ee35f6ddb8c9e25e6e4f96034a285e6f342c59c3cc222","urls":["bzz-raw://5b0ecca410bf89169e5c6393bc4d8fce97a5b3dcf8a2bba02317da85c98f4d0c","dweb:/ipfs/QmeGS5vbFwkmEvJh7s27Q9xW4xGXuUohh2zGPVbgxgjfnu"],"license":"MPL-2.0"},"src/interfaces/IRulesManagementModule.sol":{"keccak256":"0x1be8087ef526f664cf8ba5dd35d4d12fc1880f905e3ba2e553ee02cb7d6506c1","urls":["bzz-raw://545cafd73f2fe9b2b89b37e905057637f58ae2c1da7f3dc33493b515c87a720f","dweb:/ipfs/QmXiTEhLSpN6sj1fiwFT9V6bGD1VCXTqQJiNnXcLrYmW7N"],"license":"MPL-2.0"},"src/modules/ERC2771ModuleStandalone.sol":{"keccak256":"0xecc9aec20ff41c46404f6fcb9bfb0fd5588781fbb4f2fbec351f603a31c178b0","urls":["bzz-raw://48674e77afe59b6c6e6aa8b0d5e370ca58c9a354b5dc294bb3c9f10fbd12a3f3","dweb:/ipfs/QmY3HhbBDqsBvrGBXoRwgVpfSNtiK2XmhaxVpS1F3dSPx9"],"license":"MPL-2.0"},"src/modules/ERC3643ComplianceModule.sol":{"keccak256":"0xdb472471270ea23d4694ca2d2eb107ce668affc9dbe18b5a6eda312ab4800a33","urls":["bzz-raw://6200e990afca50a32fb0a0ad76ffe955447a67cab6e93f64281fc9f14208aab1","dweb:/ipfs/QmXXhRsBq3eGDgBqQwWL5w4Sn6pdTeeXRvpC4jZBDVb6nQ"],"license":"MPL-2.0"},"src/modules/RulesManagementModule.sol":{"keccak256":"0xc9c58e027874658577285de9c9bf9069cd773573a615df7c9644c6c96c69dbc3","urls":["bzz-raw://a6c9ca74cc247b42b9852b35cb4eeadc919d383d7bbd4f4df0739ee6a8bce2c3","dweb:/ipfs/QmfJCvSQjqQrQXYt9JEHiJRZATy1s7q53DKxZC1QsSYMHZ"],"license":"MPL-2.0"},"src/modules/VersionModule.sol":{"keccak256":"0x077070dca24da125a764111d336c0a8fb3445b82d93692ff76b22384b0f4f39f","urls":["bzz-raw://be8df88e667fb2de39d095f0c396d23ed263fdc51a4095fedc89a326540a03ee","dweb:/ipfs/QmYfhhEvNee1XYwCYZCVAKpUUWBd5FP5qvTMYGr6ogC8kA"],"license":"MPL-2.0"},"src/modules/library/ComplianceInterfaceId.sol":{"keccak256":"0xa0f15ca7f9e0fa8ccb854ea2bd812f220c68c280682b56e8d1a437ddba4b6d1f","urls":["bzz-raw://1e01a79b4a2110a401c3d2fbead97844f7428d6dc6603dccf795d42dbc142786","dweb:/ipfs/QmV88ZcDHTU33oXNLFTshUBZ7otgcZRN1HXwywda7Fgz9a"],"license":"MPL-2.0"},"src/modules/library/RuleEngineInvariantStorage.sol":{"keccak256":"0x15005e56f8fbf8f9b8a41c4bfed6c842e37be49fa52b0dbb2edc6b08b9e50c2f","urls":["bzz-raw://06c90dd748d060cb1b05de978cb42fd79d9b49a2beb3a479b4e49f8edaba1195","dweb:/ipfs/QmYXEQWrwJkuzWBdi5hjSaM6pWhrNUf2kH2pHX8jRu9dZS"],"license":"MPL-2.0"},"src/modules/library/RuleInterfaceId.sol":{"keccak256":"0x3c57987589d6205e2546d4ce332e944d1667dddfe897087028a95ed804c50882","urls":["bzz-raw://0e1718e500d4cb5cf4441131c57d23da788f2835e9a014e7d1f62dfb6161647a","dweb:/ipfs/QmXY5cjc9Dzrp7ML7DfvDB9zg7t4cene3g4K9AAuDmLLfC"],"license":"MPL-2.0"},"src/modules/library/RulesManagementModuleInvariantStorage.sol":{"keccak256":"0xa6f9109698f169be74c309a1efadd48edffcb0e9585523258477bf07942c8ae6","urls":["bzz-raw://4c28513636b660111b60a7028c9600b30dcfda291a831343d9e27e253b80856a","dweb:/ipfs/QmQVSZ9N6vjPxNnJDTqEuGSWqNdoxHKhzTzP2cvgZpBSzj"],"license":"MPL-2.0"}},"version":1},"id":165} \ No newline at end of file diff --git a/doc/compilation/v3.0.0-rc2/hardhat/RuleEngine.sol/RuleEngine.dbg.json b/doc/compilation/v3.0.0-rc2/hardhat/RuleEngine.sol/RuleEngine.dbg.json deleted file mode 100644 index 35abe72a..00000000 --- a/doc/compilation/v3.0.0-rc2/hardhat/RuleEngine.sol/RuleEngine.dbg.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "_format": "hh-sol-dbg-1", - "buildInfo": "../../../build-info/6f3c11638d96ee863225bd1b2732b06d.json" -} diff --git a/doc/compilation/v3.0.0-rc2/hardhat/RuleEngine.sol/RuleEngine.json b/doc/compilation/v3.0.0-rc2/hardhat/RuleEngine.sol/RuleEngine.json deleted file mode 100644 index acccfe5a..00000000 --- a/doc/compilation/v3.0.0-rc2/hardhat/RuleEngine.sol/RuleEngine.json +++ /dev/null @@ -1,921 +0,0 @@ -{ - "_format": "hh-sol-artifact-1", - "contractName": "RuleEngine", - "sourceName": "src/deployment/RuleEngine.sol", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "admin", - "type": "address" - }, - { - "internalType": "address", - "name": "forwarderIrrevocable", - "type": "address" - }, - { - "internalType": "address", - "name": "tokenContract", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [], - "name": "AccessControlBadConfirmation", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "internalType": "bytes32", - "name": "neededRole", - "type": "bytes32" - } - ], - "name": "AccessControlUnauthorizedAccount", - "type": "error" - }, - { - "inputs": [], - "name": "RuleEngine_AdminWithAddressZeroNotAllowed", - "type": "error" - }, - { - "inputs": [], - "name": "RuleEngine_ERC3643Compliance_InvalidTokenAddress", - "type": "error" - }, - { - "inputs": [], - "name": "RuleEngine_ERC3643Compliance_OperationNotSuccessful", - "type": "error" - }, - { - "inputs": [], - "name": "RuleEngine_ERC3643Compliance_TokenAlreadyBound", - "type": "error" - }, - { - "inputs": [], - "name": "RuleEngine_ERC3643Compliance_TokenNotBound", - "type": "error" - }, - { - "inputs": [], - "name": "RuleEngine_ERC3643Compliance_UnauthorizedCaller", - "type": "error" - }, - { - "inputs": [], - "name": "RuleEngine_RuleInvalidInterface", - "type": "error" - }, - { - "inputs": [], - "name": "RuleEngine_RulesManagementModule_ArrayIsEmpty", - "type": "error" - }, - { - "inputs": [], - "name": "RuleEngine_RulesManagementModule_OperationNotSuccessful", - "type": "error" - }, - { - "inputs": [], - "name": "RuleEngine_RulesManagementModule_RuleAddressZeroNotAllowed", - "type": "error" - }, - { - "inputs": [], - "name": "RuleEngine_RulesManagementModule_RuleAlreadyExists", - "type": "error" - }, - { - "inputs": [], - "name": "RuleEngine_RulesManagementModule_RuleDoNotMatch", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "contract IRule", - "name": "rule", - "type": "address" - } - ], - "name": "AddRule", - "type": "event" - }, - { - "anonymous": false, - "inputs": [], - "name": "ClearRules", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "contract IRule", - "name": "rule", - "type": "address" - } - ], - "name": "RemoveRule", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "bytes32", - "name": "previousAdminRole", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "bytes32", - "name": "newAdminRole", - "type": "bytes32" - } - ], - "name": "RoleAdminChanged", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "RoleGranted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "indexed": true, - "internalType": "address", - "name": "account", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "sender", - "type": "address" - } - ], - "name": "RoleRevoked", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "token", - "type": "address" - } - ], - "name": "TokenBound", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "token", - "type": "address" - } - ], - "name": "TokenUnbound", - "type": "event" - }, - { - "inputs": [], - "name": "COMPLIANCE_MANAGER_ROLE", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "DEFAULT_ADMIN_ROLE", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "RULES_MANAGEMENT_ROLE", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract IRule", - "name": "rule_", - "type": "address" - } - ], - "name": "addRule", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "token", - "type": "address" - } - ], - "name": "bindToken", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "canTransfer", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "canTransferFrom", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "clearRules", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract IRule", - "name": "rule_", - "type": "address" - } - ], - "name": "containsRule", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "created", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "destroyed", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "detectTransferRestriction", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "detectTransferRestrictionFrom", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - } - ], - "name": "getRoleAdmin", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "internalType": "uint256", - "name": "index", - "type": "uint256" - } - ], - "name": "getRoleMember", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - } - ], - "name": "getRoleMemberCount", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - } - ], - "name": "getRoleMembers", - "outputs": [ - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getTokenBound", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getTokenBounds", - "outputs": [ - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "grantRole", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "hasRole", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "token", - "type": "address" - } - ], - "name": "isTokenBound", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "forwarder", - "type": "address" - } - ], - "name": "isTrustedForwarder", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint8", - "name": "restrictionCode", - "type": "uint8" - } - ], - "name": "messageForTransferRestriction", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract IRule", - "name": "rule_", - "type": "address" - } - ], - "name": "removeRule", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "callerConfirmation", - "type": "address" - } - ], - "name": "renounceRole", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes32", - "name": "role", - "type": "bytes32" - }, - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "revokeRole", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "ruleId", - "type": "uint256" - } - ], - "name": "rule", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "rules", - "outputs": [ - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "rulesCount", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract IRule[]", - "name": "rules_", - "type": "address[]" - } - ], - "name": "setRules", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes4", - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "transferred", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "transferred", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "trustedForwarder", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "token", - "type": "address" - } - ], - "name": "unbindToken", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "version", - "outputs": [ - { - "internalType": "string", - "name": "version_", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - } - ], - "bytecode": "0x60a060405234801561000f575f5ffd5b5060405161200438038061200483398101604081905261002e91610385565b6001600160a01b03808316608052831661005b57604051630872273360e21b815260040160405180910390fd5b6001600160a01b038116156100735761007381610086565b61007d5f8461013d565b50505050610424565b6001600160a01b0381166100ad576040516301b8831760e71b815260040160405180910390fd5b6100b8600282610173565b156100d65760405163f423354760e01b815260040160405180910390fd5b6100e1600282610194565b6100fe57604051631b4ddcf360e11b815260040160405180910390fd5b6040516001600160a01b03821681527f2de35142b19ed5a07796cf30791959c592018f70b1d2d7c460eef8ffe713692b9060200160405180910390a150565b5f8061014984846101a8565b9050801561016a575f8481526005602052604090206101689084610194565b505b90505b92915050565b6001600160a01b0381165f908152600183016020526040812054151561016a565b5f61016a836001600160a01b03841661023a565b5f6101b3838361027f565b610233575f8381526004602090815260408083206001600160a01b03861684529091529020805460ff191660011790556101eb6102f1565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a450600161016d565b505f61016d565b5f81815260018301602052604081205461023357508154600181810184555f84815260208082209093018490558454848252828601909352604090209190915561016d565b6001600160a01b0381165f9081527f17ef568e3e12ab5b9c7254a8d58478811de00f9e6eb34345acd53bf8fd09d3ec602052604081205460ff16156102c65750600161016d565b505f8281526004602090815260408083206001600160a01b038516845290915290205460ff1661016d565b5f6102fa6102ff565b905090565b5f366014808210801590610317575061031733610345565b1561033d5761032a36828403815f6103c5565b610333916103ec565b60601c9250505090565b339250505090565b5f61034f60805190565b6001600160a01b0316826001600160a01b0316149050919050565b80516001600160a01b0381168114610380575f5ffd5b919050565b5f5f5f60608486031215610397575f5ffd5b6103a08461036a565b92506103ae6020850161036a565b91506103bc6040850161036a565b90509250925092565b5f5f858511156103d3575f5ffd5b838611156103df575f5ffd5b5050820193919092039150565b80356001600160601b0319811690601484101561041d576001600160601b0319601485900360031b81901b82161691505b5092915050565b608051611bba61044a5f395f8181610364015281816103dc01526113460152611bba5ff3fe608060405234801561000f575f5ffd5b506004361061021e575f3560e01c80638d2ea7721161012a578063bc13eacc116100b4578063db18af6c11610079578063db18af6c14610534578063df21950f14610547578063e3c4602c1461055a578063e46638e61461056d578063e54621d214610580575f5ffd5b8063bc13eacc146104ce578063ca15c873146104d6578063d32c7bb5146104e9578063d4ce14151461050e578063d547741f14610521575f5ffd5b80639b11c115116100fa5780639b11c11514610472578063a217fddf14610499578063a3246ad3146104a0578063b043572e146104b3578063b27aef3a146104bb575f5ffd5b80638d2ea772146104265780639010d07c1461043957806391d148541461044c578063993e8b951461045f575f5ffd5b806354e4b945116101ab5780636a3edf281161017b5780636a3edf28146103a75780637157797f146103c75780637da0a877146103da5780637f4ab1dd146104005780638baf29b414610413575f5ffd5b806354e4b9451461031757806354fd4d501461032a578063572b6c05146103545780635f8dead314610394575f5ffd5b806336568abe116101f157806336568abe146102b65780633e5af4ca146102c95780633ff5aa02146102dc57806340db3b50146102ef57806352f6747a14610302575f5ffd5b806301ffc9a71461022257806303c26bcd1461024a578063248a9ca31461027f5780632f2ff15d146102a1575b5f5ffd5b61023561023036600461174a565b610588565b60405190151581526020015b60405180910390f35b6102717fe5c50d0927e06141e032cb9a67e1d7092dc85c0b0825191f7e1cede60002856881565b604051908152602001610241565b61027161028d366004611771565b5f9081526004602052604090206001015490565b6102b46102af36600461179c565b6105a7565b005b6102b46102c436600461179c565b6105d1565b6102b46102d73660046117ca565b610619565b6102b46102ea366004611818565b61062d565b6102b46102fd366004611818565b610641565b61030a610652565b6040516102419190611833565b610235610325366004611818565b610662565b6040805180820190915260058152640332e302e360dc1b60208201525b604051610241919061187e565b610235610362366004611818565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0390811691161490565b6102b46103a23660046118b3565b61066d565b6103af610684565b6040516001600160a01b039091168152602001610241565b6102356103d53660046117ca565b6106a6565b7f00000000000000000000000000000000000000000000000000000000000000006103af565b61034761040e3660046118eb565b6106c3565b6102b4610421366004611906565b6106ce565b6102b46104343660046118b3565b6106e1565b6103af610447366004611944565b6106f4565b61023561045a36600461179c565b610712565b61023561046d366004611818565b610784565b6102717fea5f4eb72290e50c32abd6c23e45de3d8300b3286e1cbc2e293114b92e034e5e81565b6102715f81565b61030a6104ae366004611771565b610790565b6102b46107a9565b6102b46104c9366004611964565b6107bb565b6102716108e7565b6102716104e4366004611771565b6108f1565b6104fc6104f73660046117ca565b610907565b60405160ff9091168152602001610241565b6104fc61051c366004611906565b61091d565b6102b461052f36600461179c565b610929565b6103af610542366004611771565b61094d565b6102b4610555366004611818565b61096f565b6102b4610568366004611818565b6109a7565b61023561057b366004611906565b610a15565b61030a610a2e565b5f61059282610a3a565b806105a157506105a182610aa5565b92915050565b5f828152600460205260409020600101546105c181610ac9565b6105cb8383610ada565b50505050565b6105d9610b0d565b6001600160a01b0316816001600160a01b03161461060a5760405163334bd91960e11b815260040160405180910390fd5b6106148282610b16565b505050565b610621610b41565b6105cb84848484610b71565b610635610c13565b61063e81610c3d565b50565b610649610c13565b61063e81610cf5565b606061065d5f610d7e565b905090565b5f6105a18183610d8a565b610675610b41565b6106805f8383610dab565b5050565b5f5f6106906002610e44565b11156106a15761065d60025f610e4d565b505f90565b5f806106b486868686610907565b60ff161490505b949350505050565b60606105a182610e58565b6106d6610b41565b610614838383610dab565b6106e9610b41565b610680825f83610dab565b5f82815260056020526040812061070b9083610e4d565b9392505050565b6001600160a01b0381165f9081527f17ef568e3e12ab5b9c7254a8d58478811de00f9e6eb34345acd53bf8fd09d3ec602052604081205460ff1615610759575060016105a1565b505f8281526004602090815260408083206001600160a01b038516845290915290205460ff166105a1565b5f6105a1600283610d8a565b5f8181526005602052604090206060906105a190610d7e565b6107b1610fa2565b6107b9610fcc565b565b6107c3610fa2565b5f8190036107e4576040516359203cb960e01b815260040160405180910390fd5b5f6107ee5f610e44565b11156107fc576107fc610fcc565b5f5b818110156106145761083583838381811061081b5761081b6119d5565b90506020020160208101906108309190611818565b610ffd565b61086683838381811061084a5761084a6119d5565b905060200201602081019061085f9190611818565b5f90611034565b6108835760405163f280d16160e01b815260040160405180910390fd5b828282818110610895576108956119d5565b90506020020160208101906108aa9190611818565b6001600160a01b03167f60305ce6c9104acd0969d358f926bf391174340660aaf5e6215261fd6847bf4660405160405180910390a26001016107fe565b5f61065d5f610e44565b5f8181526005602052604081206105a190610e44565b5f61091485858585611048565b95945050505050565b5f6106bb848484611113565b5f8281526004602052604090206001015461094381610ac9565b6105cb8383610b16565b5f6109575f610e44565b821015610968576105a15f83610e4d565b505f919050565b610977610fa2565b6109815f82610d8a565b61099e57604051632cdc3a4160e21b815260040160405180910390fd5b61063e816111d5565b6109af610fa2565b6109b881610ffd565b6109c25f82611034565b6109df5760405163f280d16160e01b815260040160405180910390fd5b6040516001600160a01b038216907f60305ce6c9104acd0969d358f926bf391174340660aaf5e6215261fd6847bf46905f90a250565b5f80610a2285858561091d565b60ff1614949350505050565b606061065d6002610d7e565b5f6001600160e01b031982166320c49ce760e01b1480610a6a57506001600160e01b031982166378a8de7d60e01b145b80610a8557506001600160e01b03198216630c51264760e21b145b806105a157506001600160e01b03198216637157797f60e01b1492915050565b5f6001600160e01b03198216635a05180f60e01b14806105a157506105a182611232565b61063e81610ad5610b0d565b611266565b5f5f610ae684846112a3565b9050801561070b575f848152600560205260409020610b059084611034565b509392505050565b5f61065d611335565b5f5f610b22848461139f565b9050801561070b575f848152600560205260409020610b059084611428565b610b54610b4c610b0d565b600290610d8a565b6107b95760405163e39b3c8f60e01b815260040160405180910390fd5b5f610b7b5f610e44565b90505f5b81811015610c0b57610b915f82610e4d565b604051631f2d7a6560e11b81526001600160a01b03888116600483015287811660248301528681166044830152606482018690529190911690633e5af4ca906084015f604051808303815f87803b158015610bea575f5ffd5b505af1158015610bfc573d5f5f3e3d5ffd5b50505050806001019050610b7f565b505050505050565b7fe5c50d0927e06141e032cb9a67e1d7092dc85c0b0825191f7e1cede60002856861063e81610ac9565b6001600160a01b038116610c64576040516301b8831760e71b815260040160405180910390fd5b610c6f600282610d8a565b15610c8d5760405163f423354760e01b815260040160405180910390fd5b610c98600282611034565b610cb557604051631b4ddcf360e11b815260040160405180910390fd5b6040516001600160a01b03821681527f2de35142b19ed5a07796cf30791959c592018f70b1d2d7c460eef8ffe713692b906020015b60405180910390a150565b610d00600282610d8a565b610d1d57604051636a2b488360e11b815260040160405180910390fd5b610d28600282611428565b610d4557604051631b4ddcf360e11b815260040160405180910390fd5b6040516001600160a01b03821681527f28a4ca7134a3b3f9aff286e79ad3daadb4a06d1b43d037a3a98bdc074edd9b7a90602001610cea565b60605f61070b8361143c565b6001600160a01b0381165f908152600183016020526040812054151561070b565b5f610db55f610e44565b90505f5b81811015610e3d57610dcb5f82610e4d565b6040516322ebca6d60e21b81526001600160a01b0387811660048301528681166024830152604482018690529190911690638baf29b4906064015f604051808303815f87803b158015610e1c575f5ffd5b505af1158015610e2e573d5f5f3e3d5ffd5b50505050806001019050610db9565b5050505050565b5f6105a1825490565b5f61070b8383611495565b60605f610e636108e7565b90505f5b81811015610f6657610e788161094d565b604051633e822efb60e11b815260ff861660048201526001600160a01b039190911690637d045df690602401602060405180830381865afa158015610ebf573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ee391906119e9565b15610f5e57610ef18161094d565b604051637f4ab1dd60e01b815260ff861660048201526001600160a01b039190911690637f4ab1dd906024015f60405180830381865afa158015610f37573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526106bb9190810190611a1c565b600101610e67565b505060408051808201909152601881527f556e6b6e6f776e207265737472696374696f6e20636f64650000000000000000602082015292915050565b7fea5f4eb72290e50c32abd6c23e45de3d8300b3286e1cbc2e293114b92e034e5e61063e81610ac9565b6040517fdbf61473843cd9be1c9791ce51ef66d0da6c9026d62ba80c1ca433b13fb729b2905f90a16107b95f6114bb565b611006816114c4565b61101781632497d6cb60e01b611513565b61063e57604051639952e34360e01b815260040160405180910390fd5b5f61070b836001600160a01b03841661152e565b5f5f6110526108e7565b90505f5b81811015611107575f6110688261094d565b60405163d32c7bb560e01b81526001600160a01b038a811660048301528981166024830152888116604483015260648201889052919091169063d32c7bb590608401602060405180830381865afa1580156110c5573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110e99190611acf565b905060ff8116156110fe5792506106bb915050565b50600101611056565b505f9695505050505050565b5f5f61111d6108e7565b90505f5b818110156111ca575f6111338261094d565b60405163d4ce141560e01b81526001600160a01b038981166004830152888116602483015260448201889052919091169063d4ce141590606401602060405180830381865afa158015611188573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111ac9190611acf565b905060ff8116156111c157925061070b915050565b50600101611121565b505f95945050505050565b6111df5f82611428565b6111fc5760405163f280d16160e01b815260040160405180910390fd5b6040516001600160a01b038216907f6d83315c9718799346b67584ec64301b1457e989c8e35a8e2982a7776c04bfc4905f90a250565b5f6001600160e01b03198216637965db0b60e01b14806105a157506301ffc9a760e01b6001600160e01b03198316146105a1565b6112708282610712565b6106805760405163e2517d3f60e01b81526001600160a01b03821660048201526024810183905260440160405180910390fd5b5f6112ae8383610712565b61132e575f8381526004602090815260408083206001600160a01b03861684529091529020805460ff191660011790556112e6610b0d565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45060016105a1565b505f6105a1565b5f36601480821080159061137157507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031633145b156113975761138436828403815f611aea565b61138d91611b11565b60601c9250505090565b339250505090565b5f6113aa8383610712565b1561132e575f8381526004602090815260408083206001600160a01b03861684529091529020805460ff191690556113e0610b0d565b6001600160a01b0316826001600160a01b0316847ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a45060016105a1565b5f61070b836001600160a01b038416611573565b6060815f0180548060200260200160405190810160405280929190818152602001828054801561148957602002820191905f5260205f20905b815481526020019060010190808311611475575b50505050509050919050565b5f825f0182815481106114aa576114aa6119d5565b905f5260205f200154905092915050565b61063e8161165d565b6001600160a01b0381166114eb5760405163f9d152fb60e01b815260040160405180910390fd5b6114f55f82610d8a565b1561063e5760405163cc790a4b60e01b815260040160405180910390fd5b5f61151d836116b6565b801561070b575061070b83836116f5565b5f81815260018301602052604081205461132e57508154600181810184555f8481526020808220909301849055845484825282860190935260409020919091556105a1565b5f818152600183016020526040812054801561164d575f611595600183611b51565b85549091505f906115a890600190611b51565b9050808214611607575f865f0182815481106115c6576115c66119d5565b905f5260205f200154905080875f0184815481106115e6576115e66119d5565b5f918252602080832090910192909255918252600188019052604090208390555b855486908061161857611618611b70565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f9055600193505050506105a1565b5f9150506105a1565b5092915050565b5f611666825490565b90505f5b818110156116af57826001015f845f01838154811061168b5761168b6119d5565b905f5260205f20015481526020019081526020015f205f905580600101905061166a565b50505f9055565b5f6116c8826301ffc9a760e01b6116f5565b15610968575f806116e1846001600160e01b0319611716565b915091508180156106bb5750159392505050565b5f5f5f6117028585611716565b915091508180156109145750949350505050565b6301ffc9a760e01b5f818152600483905290819060208260248188617530fa92505f511515601f3d11169150509250929050565b5f6020828403121561175a575f5ffd5b81356001600160e01b03198116811461070b575f5ffd5b5f60208284031215611781575f5ffd5b5035919050565b6001600160a01b038116811461063e575f5ffd5b5f5f604083850312156117ad575f5ffd5b8235915060208301356117bf81611788565b809150509250929050565b5f5f5f5f608085870312156117dd575f5ffd5b84356117e881611788565b935060208501356117f881611788565b9250604085013561180881611788565b9396929550929360600135925050565b5f60208284031215611828575f5ffd5b813561070b81611788565b602080825282518282018190525f918401906040840190835b818110156118735783516001600160a01b031683526020938401939092019160010161184c565b509095945050505050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b5f5f604083850312156118c4575f5ffd5b82356118cf81611788565b946020939093013593505050565b60ff8116811461063e575f5ffd5b5f602082840312156118fb575f5ffd5b813561070b816118dd565b5f5f5f60608486031215611918575f5ffd5b833561192381611788565b9250602084013561193381611788565b929592945050506040919091013590565b5f5f60408385031215611955575f5ffd5b50508035926020909101359150565b5f5f60208385031215611975575f5ffd5b823567ffffffffffffffff81111561198b575f5ffd5b8301601f8101851361199b575f5ffd5b803567ffffffffffffffff8111156119b1575f5ffd5b8560208260051b84010111156119c5575f5ffd5b6020919091019590945092505050565b634e487b7160e01b5f52603260045260245ffd5b5f602082840312156119f9575f5ffd5b8151801515811461070b575f5ffd5b634e487b7160e01b5f52604160045260245ffd5b5f60208284031215611a2c575f5ffd5b815167ffffffffffffffff811115611a42575f5ffd5b8201601f81018413611a52575f5ffd5b805167ffffffffffffffff811115611a6c57611a6c611a08565b604051601f8201601f19908116603f0116810167ffffffffffffffff81118282101715611a9b57611a9b611a08565b604052818152828201602001861015611ab2575f5ffd5b8160208401602083015e5f91810160200191909152949350505050565b5f60208284031215611adf575f5ffd5b815161070b816118dd565b5f5f85851115611af8575f5ffd5b83861115611b04575f5ffd5b5050820193919092039150565b80356bffffffffffffffffffffffff198116906014841015611656576bffffffffffffffffffffffff1960149490940360031b84901b1690921692915050565b818103818111156105a157634e487b7160e01b5f52601160045260245ffd5b634e487b7160e01b5f52603160045260245ffdfea2646970667358221220a009c07502662c5792e389f7aebf6f174ebd68a89148a2c900772663b8436d7664736f6c63430008220033", - "deployedBytecode": "0x608060405234801561000f575f5ffd5b506004361061021e575f3560e01c80638d2ea7721161012a578063bc13eacc116100b4578063db18af6c11610079578063db18af6c14610534578063df21950f14610547578063e3c4602c1461055a578063e46638e61461056d578063e54621d214610580575f5ffd5b8063bc13eacc146104ce578063ca15c873146104d6578063d32c7bb5146104e9578063d4ce14151461050e578063d547741f14610521575f5ffd5b80639b11c115116100fa5780639b11c11514610472578063a217fddf14610499578063a3246ad3146104a0578063b043572e146104b3578063b27aef3a146104bb575f5ffd5b80638d2ea772146104265780639010d07c1461043957806391d148541461044c578063993e8b951461045f575f5ffd5b806354e4b945116101ab5780636a3edf281161017b5780636a3edf28146103a75780637157797f146103c75780637da0a877146103da5780637f4ab1dd146104005780638baf29b414610413575f5ffd5b806354e4b9451461031757806354fd4d501461032a578063572b6c05146103545780635f8dead314610394575f5ffd5b806336568abe116101f157806336568abe146102b65780633e5af4ca146102c95780633ff5aa02146102dc57806340db3b50146102ef57806352f6747a14610302575f5ffd5b806301ffc9a71461022257806303c26bcd1461024a578063248a9ca31461027f5780632f2ff15d146102a1575b5f5ffd5b61023561023036600461174a565b610588565b60405190151581526020015b60405180910390f35b6102717fe5c50d0927e06141e032cb9a67e1d7092dc85c0b0825191f7e1cede60002856881565b604051908152602001610241565b61027161028d366004611771565b5f9081526004602052604090206001015490565b6102b46102af36600461179c565b6105a7565b005b6102b46102c436600461179c565b6105d1565b6102b46102d73660046117ca565b610619565b6102b46102ea366004611818565b61062d565b6102b46102fd366004611818565b610641565b61030a610652565b6040516102419190611833565b610235610325366004611818565b610662565b6040805180820190915260058152640332e302e360dc1b60208201525b604051610241919061187e565b610235610362366004611818565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0390811691161490565b6102b46103a23660046118b3565b61066d565b6103af610684565b6040516001600160a01b039091168152602001610241565b6102356103d53660046117ca565b6106a6565b7f00000000000000000000000000000000000000000000000000000000000000006103af565b61034761040e3660046118eb565b6106c3565b6102b4610421366004611906565b6106ce565b6102b46104343660046118b3565b6106e1565b6103af610447366004611944565b6106f4565b61023561045a36600461179c565b610712565b61023561046d366004611818565b610784565b6102717fea5f4eb72290e50c32abd6c23e45de3d8300b3286e1cbc2e293114b92e034e5e81565b6102715f81565b61030a6104ae366004611771565b610790565b6102b46107a9565b6102b46104c9366004611964565b6107bb565b6102716108e7565b6102716104e4366004611771565b6108f1565b6104fc6104f73660046117ca565b610907565b60405160ff9091168152602001610241565b6104fc61051c366004611906565b61091d565b6102b461052f36600461179c565b610929565b6103af610542366004611771565b61094d565b6102b4610555366004611818565b61096f565b6102b4610568366004611818565b6109a7565b61023561057b366004611906565b610a15565b61030a610a2e565b5f61059282610a3a565b806105a157506105a182610aa5565b92915050565b5f828152600460205260409020600101546105c181610ac9565b6105cb8383610ada565b50505050565b6105d9610b0d565b6001600160a01b0316816001600160a01b03161461060a5760405163334bd91960e11b815260040160405180910390fd5b6106148282610b16565b505050565b610621610b41565b6105cb84848484610b71565b610635610c13565b61063e81610c3d565b50565b610649610c13565b61063e81610cf5565b606061065d5f610d7e565b905090565b5f6105a18183610d8a565b610675610b41565b6106805f8383610dab565b5050565b5f5f6106906002610e44565b11156106a15761065d60025f610e4d565b505f90565b5f806106b486868686610907565b60ff161490505b949350505050565b60606105a182610e58565b6106d6610b41565b610614838383610dab565b6106e9610b41565b610680825f83610dab565b5f82815260056020526040812061070b9083610e4d565b9392505050565b6001600160a01b0381165f9081527f17ef568e3e12ab5b9c7254a8d58478811de00f9e6eb34345acd53bf8fd09d3ec602052604081205460ff1615610759575060016105a1565b505f8281526004602090815260408083206001600160a01b038516845290915290205460ff166105a1565b5f6105a1600283610d8a565b5f8181526005602052604090206060906105a190610d7e565b6107b1610fa2565b6107b9610fcc565b565b6107c3610fa2565b5f8190036107e4576040516359203cb960e01b815260040160405180910390fd5b5f6107ee5f610e44565b11156107fc576107fc610fcc565b5f5b818110156106145761083583838381811061081b5761081b6119d5565b90506020020160208101906108309190611818565b610ffd565b61086683838381811061084a5761084a6119d5565b905060200201602081019061085f9190611818565b5f90611034565b6108835760405163f280d16160e01b815260040160405180910390fd5b828282818110610895576108956119d5565b90506020020160208101906108aa9190611818565b6001600160a01b03167f60305ce6c9104acd0969d358f926bf391174340660aaf5e6215261fd6847bf4660405160405180910390a26001016107fe565b5f61065d5f610e44565b5f8181526005602052604081206105a190610e44565b5f61091485858585611048565b95945050505050565b5f6106bb848484611113565b5f8281526004602052604090206001015461094381610ac9565b6105cb8383610b16565b5f6109575f610e44565b821015610968576105a15f83610e4d565b505f919050565b610977610fa2565b6109815f82610d8a565b61099e57604051632cdc3a4160e21b815260040160405180910390fd5b61063e816111d5565b6109af610fa2565b6109b881610ffd565b6109c25f82611034565b6109df5760405163f280d16160e01b815260040160405180910390fd5b6040516001600160a01b038216907f60305ce6c9104acd0969d358f926bf391174340660aaf5e6215261fd6847bf46905f90a250565b5f80610a2285858561091d565b60ff1614949350505050565b606061065d6002610d7e565b5f6001600160e01b031982166320c49ce760e01b1480610a6a57506001600160e01b031982166378a8de7d60e01b145b80610a8557506001600160e01b03198216630c51264760e21b145b806105a157506001600160e01b03198216637157797f60e01b1492915050565b5f6001600160e01b03198216635a05180f60e01b14806105a157506105a182611232565b61063e81610ad5610b0d565b611266565b5f5f610ae684846112a3565b9050801561070b575f848152600560205260409020610b059084611034565b509392505050565b5f61065d611335565b5f5f610b22848461139f565b9050801561070b575f848152600560205260409020610b059084611428565b610b54610b4c610b0d565b600290610d8a565b6107b95760405163e39b3c8f60e01b815260040160405180910390fd5b5f610b7b5f610e44565b90505f5b81811015610c0b57610b915f82610e4d565b604051631f2d7a6560e11b81526001600160a01b03888116600483015287811660248301528681166044830152606482018690529190911690633e5af4ca906084015f604051808303815f87803b158015610bea575f5ffd5b505af1158015610bfc573d5f5f3e3d5ffd5b50505050806001019050610b7f565b505050505050565b7fe5c50d0927e06141e032cb9a67e1d7092dc85c0b0825191f7e1cede60002856861063e81610ac9565b6001600160a01b038116610c64576040516301b8831760e71b815260040160405180910390fd5b610c6f600282610d8a565b15610c8d5760405163f423354760e01b815260040160405180910390fd5b610c98600282611034565b610cb557604051631b4ddcf360e11b815260040160405180910390fd5b6040516001600160a01b03821681527f2de35142b19ed5a07796cf30791959c592018f70b1d2d7c460eef8ffe713692b906020015b60405180910390a150565b610d00600282610d8a565b610d1d57604051636a2b488360e11b815260040160405180910390fd5b610d28600282611428565b610d4557604051631b4ddcf360e11b815260040160405180910390fd5b6040516001600160a01b03821681527f28a4ca7134a3b3f9aff286e79ad3daadb4a06d1b43d037a3a98bdc074edd9b7a90602001610cea565b60605f61070b8361143c565b6001600160a01b0381165f908152600183016020526040812054151561070b565b5f610db55f610e44565b90505f5b81811015610e3d57610dcb5f82610e4d565b6040516322ebca6d60e21b81526001600160a01b0387811660048301528681166024830152604482018690529190911690638baf29b4906064015f604051808303815f87803b158015610e1c575f5ffd5b505af1158015610e2e573d5f5f3e3d5ffd5b50505050806001019050610db9565b5050505050565b5f6105a1825490565b5f61070b8383611495565b60605f610e636108e7565b90505f5b81811015610f6657610e788161094d565b604051633e822efb60e11b815260ff861660048201526001600160a01b039190911690637d045df690602401602060405180830381865afa158015610ebf573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ee391906119e9565b15610f5e57610ef18161094d565b604051637f4ab1dd60e01b815260ff861660048201526001600160a01b039190911690637f4ab1dd906024015f60405180830381865afa158015610f37573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526106bb9190810190611a1c565b600101610e67565b505060408051808201909152601881527f556e6b6e6f776e207265737472696374696f6e20636f64650000000000000000602082015292915050565b7fea5f4eb72290e50c32abd6c23e45de3d8300b3286e1cbc2e293114b92e034e5e61063e81610ac9565b6040517fdbf61473843cd9be1c9791ce51ef66d0da6c9026d62ba80c1ca433b13fb729b2905f90a16107b95f6114bb565b611006816114c4565b61101781632497d6cb60e01b611513565b61063e57604051639952e34360e01b815260040160405180910390fd5b5f61070b836001600160a01b03841661152e565b5f5f6110526108e7565b90505f5b81811015611107575f6110688261094d565b60405163d32c7bb560e01b81526001600160a01b038a811660048301528981166024830152888116604483015260648201889052919091169063d32c7bb590608401602060405180830381865afa1580156110c5573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110e99190611acf565b905060ff8116156110fe5792506106bb915050565b50600101611056565b505f9695505050505050565b5f5f61111d6108e7565b90505f5b818110156111ca575f6111338261094d565b60405163d4ce141560e01b81526001600160a01b038981166004830152888116602483015260448201889052919091169063d4ce141590606401602060405180830381865afa158015611188573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111ac9190611acf565b905060ff8116156111c157925061070b915050565b50600101611121565b505f95945050505050565b6111df5f82611428565b6111fc5760405163f280d16160e01b815260040160405180910390fd5b6040516001600160a01b038216907f6d83315c9718799346b67584ec64301b1457e989c8e35a8e2982a7776c04bfc4905f90a250565b5f6001600160e01b03198216637965db0b60e01b14806105a157506301ffc9a760e01b6001600160e01b03198316146105a1565b6112708282610712565b6106805760405163e2517d3f60e01b81526001600160a01b03821660048201526024810183905260440160405180910390fd5b5f6112ae8383610712565b61132e575f8381526004602090815260408083206001600160a01b03861684529091529020805460ff191660011790556112e6610b0d565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45060016105a1565b505f6105a1565b5f36601480821080159061137157507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031633145b156113975761138436828403815f611aea565b61138d91611b11565b60601c9250505090565b339250505090565b5f6113aa8383610712565b1561132e575f8381526004602090815260408083206001600160a01b03861684529091529020805460ff191690556113e0610b0d565b6001600160a01b0316826001600160a01b0316847ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a45060016105a1565b5f61070b836001600160a01b038416611573565b6060815f0180548060200260200160405190810160405280929190818152602001828054801561148957602002820191905f5260205f20905b815481526020019060010190808311611475575b50505050509050919050565b5f825f0182815481106114aa576114aa6119d5565b905f5260205f200154905092915050565b61063e8161165d565b6001600160a01b0381166114eb5760405163f9d152fb60e01b815260040160405180910390fd5b6114f55f82610d8a565b1561063e5760405163cc790a4b60e01b815260040160405180910390fd5b5f61151d836116b6565b801561070b575061070b83836116f5565b5f81815260018301602052604081205461132e57508154600181810184555f8481526020808220909301849055845484825282860190935260409020919091556105a1565b5f818152600183016020526040812054801561164d575f611595600183611b51565b85549091505f906115a890600190611b51565b9050808214611607575f865f0182815481106115c6576115c66119d5565b905f5260205f200154905080875f0184815481106115e6576115e66119d5565b5f918252602080832090910192909255918252600188019052604090208390555b855486908061161857611618611b70565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f9055600193505050506105a1565b5f9150506105a1565b5092915050565b5f611666825490565b90505f5b818110156116af57826001015f845f01838154811061168b5761168b6119d5565b905f5260205f20015481526020019081526020015f205f905580600101905061166a565b50505f9055565b5f6116c8826301ffc9a760e01b6116f5565b15610968575f806116e1846001600160e01b0319611716565b915091508180156106bb5750159392505050565b5f5f5f6117028585611716565b915091508180156109145750949350505050565b6301ffc9a760e01b5f818152600483905290819060208260248188617530fa92505f511515601f3d11169150509250929050565b5f6020828403121561175a575f5ffd5b81356001600160e01b03198116811461070b575f5ffd5b5f60208284031215611781575f5ffd5b5035919050565b6001600160a01b038116811461063e575f5ffd5b5f5f604083850312156117ad575f5ffd5b8235915060208301356117bf81611788565b809150509250929050565b5f5f5f5f608085870312156117dd575f5ffd5b84356117e881611788565b935060208501356117f881611788565b9250604085013561180881611788565b9396929550929360600135925050565b5f60208284031215611828575f5ffd5b813561070b81611788565b602080825282518282018190525f918401906040840190835b818110156118735783516001600160a01b031683526020938401939092019160010161184c565b509095945050505050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b5f5f604083850312156118c4575f5ffd5b82356118cf81611788565b946020939093013593505050565b60ff8116811461063e575f5ffd5b5f602082840312156118fb575f5ffd5b813561070b816118dd565b5f5f5f60608486031215611918575f5ffd5b833561192381611788565b9250602084013561193381611788565b929592945050506040919091013590565b5f5f60408385031215611955575f5ffd5b50508035926020909101359150565b5f5f60208385031215611975575f5ffd5b823567ffffffffffffffff81111561198b575f5ffd5b8301601f8101851361199b575f5ffd5b803567ffffffffffffffff8111156119b1575f5ffd5b8560208260051b84010111156119c5575f5ffd5b6020919091019590945092505050565b634e487b7160e01b5f52603260045260245ffd5b5f602082840312156119f9575f5ffd5b8151801515811461070b575f5ffd5b634e487b7160e01b5f52604160045260245ffd5b5f60208284031215611a2c575f5ffd5b815167ffffffffffffffff811115611a42575f5ffd5b8201601f81018413611a52575f5ffd5b805167ffffffffffffffff811115611a6c57611a6c611a08565b604051601f8201601f19908116603f0116810167ffffffffffffffff81118282101715611a9b57611a9b611a08565b604052818152828201602001861015611ab2575f5ffd5b8160208401602083015e5f91810160200191909152949350505050565b5f60208284031215611adf575f5ffd5b815161070b816118dd565b5f5f85851115611af8575f5ffd5b83861115611b04575f5ffd5b5050820193919092039150565b80356bffffffffffffffffffffffff198116906014841015611656576bffffffffffffffffffffffff1960149490940360031b84901b1690921692915050565b818103818111156105a157634e487b7160e01b5f52601160045260245ffd5b634e487b7160e01b5f52603160045260245ffdfea2646970667358221220a009c07502662c5792e389f7aebf6f174ebd68a89148a2c900772663b8436d7664736f6c63430008220033", - "linkReferences": {}, - "deployedLinkReferences": {} -} diff --git a/doc/compilation/v3.0.0-rc2/hardhat/RuleEngineOwnable.sol/RuleEngineOwnable.dbg.json b/doc/compilation/v3.0.0-rc2/hardhat/RuleEngineOwnable.sol/RuleEngineOwnable.dbg.json deleted file mode 100644 index 35abe72a..00000000 --- a/doc/compilation/v3.0.0-rc2/hardhat/RuleEngineOwnable.sol/RuleEngineOwnable.dbg.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "_format": "hh-sol-dbg-1", - "buildInfo": "../../../build-info/6f3c11638d96ee863225bd1b2732b06d.json" -} diff --git a/doc/compilation/v3.0.0-rc2/hardhat/RuleEngineOwnable.sol/RuleEngineOwnable.json b/doc/compilation/v3.0.0-rc2/hardhat/RuleEngineOwnable.sol/RuleEngineOwnable.json deleted file mode 100644 index af208b03..00000000 --- a/doc/compilation/v3.0.0-rc2/hardhat/RuleEngineOwnable.sol/RuleEngineOwnable.json +++ /dev/null @@ -1,727 +0,0 @@ -{ - "_format": "hh-sol-artifact-1", - "contractName": "RuleEngineOwnable", - "sourceName": "src/deployment/RuleEngineOwnable.sol", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "owner_", - "type": "address" - }, - { - "internalType": "address", - "name": "forwarderIrrevocable", - "type": "address" - }, - { - "internalType": "address", - "name": "tokenContract", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "OwnableInvalidOwner", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "OwnableUnauthorizedAccount", - "type": "error" - }, - { - "inputs": [], - "name": "RuleEngine_AdminWithAddressZeroNotAllowed", - "type": "error" - }, - { - "inputs": [], - "name": "RuleEngine_ERC3643Compliance_InvalidTokenAddress", - "type": "error" - }, - { - "inputs": [], - "name": "RuleEngine_ERC3643Compliance_OperationNotSuccessful", - "type": "error" - }, - { - "inputs": [], - "name": "RuleEngine_ERC3643Compliance_TokenAlreadyBound", - "type": "error" - }, - { - "inputs": [], - "name": "RuleEngine_ERC3643Compliance_TokenNotBound", - "type": "error" - }, - { - "inputs": [], - "name": "RuleEngine_ERC3643Compliance_UnauthorizedCaller", - "type": "error" - }, - { - "inputs": [], - "name": "RuleEngine_RuleInvalidInterface", - "type": "error" - }, - { - "inputs": [], - "name": "RuleEngine_RulesManagementModule_ArrayIsEmpty", - "type": "error" - }, - { - "inputs": [], - "name": "RuleEngine_RulesManagementModule_OperationNotSuccessful", - "type": "error" - }, - { - "inputs": [], - "name": "RuleEngine_RulesManagementModule_RuleAddressZeroNotAllowed", - "type": "error" - }, - { - "inputs": [], - "name": "RuleEngine_RulesManagementModule_RuleAlreadyExists", - "type": "error" - }, - { - "inputs": [], - "name": "RuleEngine_RulesManagementModule_RuleDoNotMatch", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "contract IRule", - "name": "rule", - "type": "address" - } - ], - "name": "AddRule", - "type": "event" - }, - { - "anonymous": false, - "inputs": [], - "name": "ClearRules", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "previousOwner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "contract IRule", - "name": "rule", - "type": "address" - } - ], - "name": "RemoveRule", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "token", - "type": "address" - } - ], - "name": "TokenBound", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "token", - "type": "address" - } - ], - "name": "TokenUnbound", - "type": "event" - }, - { - "inputs": [], - "name": "COMPLIANCE_MANAGER_ROLE", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "RULES_MANAGEMENT_ROLE", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract IRule", - "name": "rule_", - "type": "address" - } - ], - "name": "addRule", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "token", - "type": "address" - } - ], - "name": "bindToken", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "canTransfer", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "canTransferFrom", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "clearRules", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract IRule", - "name": "rule_", - "type": "address" - } - ], - "name": "containsRule", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "created", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "destroyed", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "detectTransferRestriction", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "detectTransferRestrictionFrom", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getTokenBound", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getTokenBounds", - "outputs": [ - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "token", - "type": "address" - } - ], - "name": "isTokenBound", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "forwarder", - "type": "address" - } - ], - "name": "isTrustedForwarder", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint8", - "name": "restrictionCode", - "type": "uint8" - } - ], - "name": "messageForTransferRestriction", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract IRule", - "name": "rule_", - "type": "address" - } - ], - "name": "removeRule", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "ruleId", - "type": "uint256" - } - ], - "name": "rule", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "rules", - "outputs": [ - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "rulesCount", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract IRule[]", - "name": "rules_", - "type": "address[]" - } - ], - "name": "setRules", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes4", - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "transferred", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "transferred", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "trustedForwarder", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "token", - "type": "address" - } - ], - "name": "unbindToken", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "version", - "outputs": [ - { - "internalType": "string", - "name": "version_", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - } - ], - "bytecode": "0x60a060405234801561000f575f5ffd5b50604051611ad2380380611ad283398101604081905261002e91610237565b6001600160a01b038083166080528390839083908116156100525761005281610093565b50506001600160a01b03811661008157604051631e4fbdf760e01b81525f600482015260240160405180910390fd5b61008a8161014a565b50505050610277565b6001600160a01b0381166100ba576040516301b8831760e71b815260040160405180910390fd5b6100c560028261019b565b156100e35760405163f423354760e01b815260040160405180910390fd5b6100ee6002826101c1565b61010b57604051631b4ddcf360e11b815260040160405180910390fd5b6040516001600160a01b03821681527f2de35142b19ed5a07796cf30791959c592018f70b1d2d7c460eef8ffe713692b9060200160405180910390a150565b600480546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b6001600160a01b0381165f90815260018301602052604081205415155b90505b92915050565b5f6101b8836001600160a01b0384165f81815260018301602052604081205461021557508154600181810184555f8481526020808220909301849055845484825282860190935260409020919091556101bb565b505f6101bb565b80516001600160a01b0381168114610232575f5ffd5b919050565b5f5f5f60608486031215610249575f5ffd5b6102528461021c565b92506102606020850161021c565b915061026e6040850161021c565b90509250925092565b60805161183561029d5f395f81816102da0152818161035a015261138601526118355ff3fe608060405234801561000f575f5ffd5b50600436106101dc575f3560e01c80638baf29b411610109578063d32c7bb51161009e578063e3c4602c1161006e578063e3c4602c14610483578063e46638e614610496578063e54621d2146104a9578063f2fde38b146104b1575f5ffd5b8063d32c7bb514610425578063d4ce14151461044a578063db18af6c1461045d578063df21950f14610470575f5ffd5b80639b11c115116100d95780639b11c115146103db578063b043572e14610402578063b27aef3a1461040a578063bc13eacc1461041d575f5ffd5b80638baf29b4146103915780638d2ea772146103a45780638da5cb5b146103b7578063993e8b95146103c8575f5ffd5b806354fd4d501161017f578063715018a61161014f578063715018a61461033d5780637157797f146103455780637da0a877146103585780637f4ab1dd1461037e575f5ffd5b806354fd4d50146102a0578063572b6c05146102ca5780635f8dead31461030a5780636a3edf281461031d575f5ffd5b80633ff5aa02116101ba5780633ff5aa021461025257806340db3b501461026557806352f6747a1461027857806354e4b9451461028d575f5ffd5b806301ffc9a7146101e057806303c26bcd146102085780633e5af4ca1461023d575b5f5ffd5b6101f36101ee366004611413565b6104c4565b60405190151581526020015b60405180910390f35b61022f7fe5c50d0927e06141e032cb9a67e1d7092dc85c0b0825191f7e1cede60002856881565b6040519081526020016101ff565b61025061024b36600461144e565b61050a565b005b61025061026036600461149c565b610524565b61025061027336600461149c565b610538565b610280610549565b6040516101ff91906114b7565b6101f361029b36600461149c565b610559565b6040805180820190915260058152640332e302e360dc1b60208201525b6040516101ff9190611502565b6101f36102d836600461149c565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0390811691161490565b610250610318366004611537565b610564565b61032561057b565b6040516001600160a01b0390911681526020016101ff565b61025061059d565b6101f361035336600461144e565b6105b0565b7f0000000000000000000000000000000000000000000000000000000000000000610325565b6102bd61038c36600461156f565b6105cd565b61025061039f36600461158a565b6105d8565b6102506103b2366004611537565b6105f0565b6004546001600160a01b0316610325565b6101f36103d636600461149c565b610603565b61022f7fea5f4eb72290e50c32abd6c23e45de3d8300b3286e1cbc2e293114b92e034e5e81565b61025061060f565b6102506104183660046115c8565b61061f565b61022f61074b565b61043861043336600461144e565b610755565b60405160ff90911681526020016101ff565b61043861045836600461158a565b61076b565b61032561046b366004611639565b610781565b61025061047e36600461149c565b6107a3565b61025061049136600461149c565b6107db565b6101f36104a436600461158a565b610849565b610280610862565b6102506104bf36600461149c565b61086e565b5f6104ce826108ad565b806104e957506001600160e01b031982166307f5828d60e41b145b8061050457506001600160e01b031982166301ffc9a760e01b145b92915050565b610512610918565b61051e84848484610948565b50505050565b61052c6109ea565b610535816109f2565b50565b6105406109ea565b61053581610aaa565b60606105545f610b33565b905090565b5f6105048183610b3f565b61056c610918565b6105775f8383610b5f565b5050565b5f5f6105876002610bf8565b11156105985761055460025f610c01565b505f90565b6105a5610c0c565b6105ae5f610c6a565b565b5f806105be86868686610755565b60ff161490505b949350505050565b606061050482610cbb565b6105e0610918565b6105eb838383610b5f565b505050565b6105f8610918565b610577825f83610b5f565b5f610504600283610b3f565b6106176109ea565b6105ae610e05565b6106276109ea565b5f819003610648576040516359203cb960e01b815260040160405180910390fd5b5f6106525f610bf8565b111561066057610660610e05565b5f5b818110156105eb5761069983838381811061067f5761067f611650565b9050602002016020810190610694919061149c565b610e36565b6106ca8383838181106106ae576106ae611650565b90506020020160208101906106c3919061149c565b5f90610e6d565b6106e75760405163f280d16160e01b815260040160405180910390fd5b8282828181106106f9576106f9611650565b905060200201602081019061070e919061149c565b6001600160a01b03167f60305ce6c9104acd0969d358f926bf391174340660aaf5e6215261fd6847bf4660405160405180910390a2600101610662565b5f6105545f610bf8565b5f61076285858585610e81565b95945050505050565b5f610777848484610f4c565b90505b9392505050565b5f61078b5f610bf8565b82101561079c576105045f83610c01565b505f919050565b6107ab6109ea565b6107b55f82610b3f565b6107d257604051632cdc3a4160e21b815260040160405180910390fd5b6105358161100e565b6107e36109ea565b6107ec81610e36565b6107f65f82610e6d565b6108135760405163f280d16160e01b815260040160405180910390fd5b6040516001600160a01b038216907f60305ce6c9104acd0969d358f926bf391174340660aaf5e6215261fd6847bf46905f90a250565b5f8061085685858561076b565b60ff1614949350505050565b60606105546002610b33565b610876610c0c565b6001600160a01b0381166108a457604051631e4fbdf760e01b81525f60048201526024015b60405180910390fd5b61053581610c6a565b5f6001600160e01b031982166320c49ce760e01b14806108dd57506001600160e01b031982166378a8de7d60e01b145b806108f857506001600160e01b03198216630c51264760e21b145b8061050457506001600160e01b03198216637157797f60e01b1492915050565b61092b61092361106b565b600290610b3f565b6105ae5760405163e39b3c8f60e01b815260040160405180910390fd5b5f6109525f610bf8565b90505f5b818110156109e2576109685f82610c01565b604051631f2d7a6560e11b81526001600160a01b03888116600483015287811660248301528681166044830152606482018690529190911690633e5af4ca906084015f604051808303815f87803b1580156109c1575f5ffd5b505af11580156109d3573d5f5f3e3d5ffd5b50505050806001019050610956565b505050505050565b6105ae610c0c565b6001600160a01b038116610a19576040516301b8831760e71b815260040160405180910390fd5b610a24600282610b3f565b15610a425760405163f423354760e01b815260040160405180910390fd5b610a4d600282610e6d565b610a6a57604051631b4ddcf360e11b815260040160405180910390fd5b6040516001600160a01b03821681527f2de35142b19ed5a07796cf30791959c592018f70b1d2d7c460eef8ffe713692b906020015b60405180910390a150565b610ab5600282610b3f565b610ad257604051636a2b488360e11b815260040160405180910390fd5b610add600282611074565b610afa57604051631b4ddcf360e11b815260040160405180910390fd5b6040516001600160a01b03821681527f28a4ca7134a3b3f9aff286e79ad3daadb4a06d1b43d037a3a98bdc074edd9b7a90602001610a9f565b60605f61077a83611088565b6001600160a01b03165f9081526001919091016020526040902054151590565b5f610b695f610bf8565b90505f5b81811015610bf157610b7f5f82610c01565b6040516322ebca6d60e21b81526001600160a01b0387811660048301528681166024830152604482018690529190911690638baf29b4906064015f604051808303815f87803b158015610bd0575f5ffd5b505af1158015610be2573d5f5f3e3d5ffd5b50505050806001019050610b6d565b5050505050565b5f610504825490565b5f61077a83836110e1565b610c1461106b565b6001600160a01b0316610c2f6004546001600160a01b031690565b6001600160a01b0316146105ae57610c4561106b565b60405163118cdaa760e01b81526001600160a01b03909116600482015260240161089b565b600480546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b60605f610cc661074b565b90505f5b81811015610dc957610cdb81610781565b604051633e822efb60e11b815260ff861660048201526001600160a01b039190911690637d045df690602401602060405180830381865afa158015610d22573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d469190611664565b15610dc157610d5481610781565b604051637f4ab1dd60e01b815260ff861660048201526001600160a01b039190911690637f4ab1dd906024015f60405180830381865afa158015610d9a573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526105c59190810190611697565b600101610cca565b505060408051808201909152601881527f556e6b6e6f776e207265737472696374696f6e20636f64650000000000000000602082015292915050565b6040517fdbf61473843cd9be1c9791ce51ef66d0da6c9026d62ba80c1ca433b13fb729b2905f90a16105ae5f611107565b610e3f81611110565b610e5081632497d6cb60e01b61115f565b61053557604051639952e34360e01b815260040160405180910390fd5b5f61077a836001600160a01b03841661117a565b5f5f610e8b61074b565b90505f5b81811015610f40575f610ea182610781565b60405163d32c7bb560e01b81526001600160a01b038a811660048301528981166024830152888116604483015260648201889052919091169063d32c7bb590608401602060405180830381865afa158015610efe573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f22919061174a565b905060ff811615610f375792506105c5915050565b50600101610e8f565b505f9695505050505050565b5f5f610f5661074b565b90505f5b81811015611003575f610f6c82610781565b60405163d4ce141560e01b81526001600160a01b038981166004830152888116602483015260448201889052919091169063d4ce141590606401602060405180830381865afa158015610fc1573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610fe5919061174a565b905060ff811615610ffa57925061077a915050565b50600101610f5a565b505f95945050505050565b6110185f82611074565b6110355760405163f280d16160e01b815260040160405180910390fd5b6040516001600160a01b038216907f6d83315c9718799346b67584ec64301b1457e989c8e35a8e2982a7776c04bfc4905f90a250565b5f6105546111c6565b5f61077a836001600160a01b0384166111d4565b6060815f018054806020026020016040519081016040528092919081815260200182805480156110d557602002820191905f5260205f20905b8154815260200190600101908083116110c1575b50505050509050919050565b5f825f0182815481106110f6576110f6611650565b905f5260205f200154905092915050565b610535816112be565b6001600160a01b0381166111375760405163f9d152fb60e01b815260040160405180910390fd5b6111415f82610b3f565b156105355760405163cc790a4b60e01b815260040160405180910390fd5b5f61116983611317565b801561077a575061077a8383611356565b5f8181526001830160205260408120546111bf57508154600181810184555f848152602080822090930184905584548482528286019093526040902091909155610504565b505f610504565b5f6105545f36816014611377565b5f81815260018301602052604081205480156112ae575f6111f6600183611765565b85549091505f9061120990600190611765565b9050808214611268575f865f01828154811061122757611227611650565b905f5260205f200154905080875f01848154811061124757611247611650565b5f918252602080832090910192909255918252600188019052604090208390555b855486908061127957611279611784565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f905560019350505050610504565b5f915050610504565b5092915050565b5f6112c7825490565b90505f5b8181101561131057826001015f845f0183815481106112ec576112ec611650565b905f5260205f20015481526020019081526020015f205f90558060010190506112cb565b50505f9055565b5f611329826301ffc9a760e01b611356565b1561079c575f80611342846001600160e01b03196113df565b915091508180156105c55750159392505050565b5f5f5f61136385856113df565b915091508180156107625750949350505050565b90508082101580156113b157507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031633145b156113d7576113c436828403815f611798565b6113cd916117bf565b60601c9250505090565b339250505090565b6301ffc9a760e01b5f818152600483905290819060208260248188617530fa92505f511515601f3d11169150509250929050565b5f60208284031215611423575f5ffd5b81356001600160e01b03198116811461077a575f5ffd5b6001600160a01b0381168114610535575f5ffd5b5f5f5f5f60808587031215611461575f5ffd5b843561146c8161143a565b9350602085013561147c8161143a565b9250604085013561148c8161143a565b9396929550929360600135925050565b5f602082840312156114ac575f5ffd5b813561077a8161143a565b602080825282518282018190525f918401906040840190835b818110156114f75783516001600160a01b03168352602093840193909201916001016114d0565b509095945050505050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b5f5f60408385031215611548575f5ffd5b82356115538161143a565b946020939093013593505050565b60ff81168114610535575f5ffd5b5f6020828403121561157f575f5ffd5b813561077a81611561565b5f5f5f6060848603121561159c575f5ffd5b83356115a78161143a565b925060208401356115b78161143a565b929592945050506040919091013590565b5f5f602083850312156115d9575f5ffd5b823567ffffffffffffffff8111156115ef575f5ffd5b8301601f810185136115ff575f5ffd5b803567ffffffffffffffff811115611615575f5ffd5b8560208260051b8401011115611629575f5ffd5b6020919091019590945092505050565b5f60208284031215611649575f5ffd5b5035919050565b634e487b7160e01b5f52603260045260245ffd5b5f60208284031215611674575f5ffd5b8151801515811461077a575f5ffd5b634e487b7160e01b5f52604160045260245ffd5b5f602082840312156116a7575f5ffd5b815167ffffffffffffffff8111156116bd575f5ffd5b8201601f810184136116cd575f5ffd5b805167ffffffffffffffff8111156116e7576116e7611683565b604051601f8201601f19908116603f0116810167ffffffffffffffff8111828210171561171657611716611683565b60405281815282820160200186101561172d575f5ffd5b8160208401602083015e5f91810160200191909152949350505050565b5f6020828403121561175a575f5ffd5b815161077a81611561565b8181038181111561050457634e487b7160e01b5f52601160045260245ffd5b634e487b7160e01b5f52603160045260245ffd5b5f5f858511156117a6575f5ffd5b838611156117b2575f5ffd5b5050820193919092039150565b80356bffffffffffffffffffffffff1981169060148410156112b7576bffffffffffffffffffffffff1960149490940360031b84901b169092169291505056fea26469706673582212201e9fb211c255bec6228b5933ad98df6d4ed24f7c9a53f9bea90aa6130d1d316b64736f6c63430008220033", - "deployedBytecode": "0x608060405234801561000f575f5ffd5b50600436106101dc575f3560e01c80638baf29b411610109578063d32c7bb51161009e578063e3c4602c1161006e578063e3c4602c14610483578063e46638e614610496578063e54621d2146104a9578063f2fde38b146104b1575f5ffd5b8063d32c7bb514610425578063d4ce14151461044a578063db18af6c1461045d578063df21950f14610470575f5ffd5b80639b11c115116100d95780639b11c115146103db578063b043572e14610402578063b27aef3a1461040a578063bc13eacc1461041d575f5ffd5b80638baf29b4146103915780638d2ea772146103a45780638da5cb5b146103b7578063993e8b95146103c8575f5ffd5b806354fd4d501161017f578063715018a61161014f578063715018a61461033d5780637157797f146103455780637da0a877146103585780637f4ab1dd1461037e575f5ffd5b806354fd4d50146102a0578063572b6c05146102ca5780635f8dead31461030a5780636a3edf281461031d575f5ffd5b80633ff5aa02116101ba5780633ff5aa021461025257806340db3b501461026557806352f6747a1461027857806354e4b9451461028d575f5ffd5b806301ffc9a7146101e057806303c26bcd146102085780633e5af4ca1461023d575b5f5ffd5b6101f36101ee366004611413565b6104c4565b60405190151581526020015b60405180910390f35b61022f7fe5c50d0927e06141e032cb9a67e1d7092dc85c0b0825191f7e1cede60002856881565b6040519081526020016101ff565b61025061024b36600461144e565b61050a565b005b61025061026036600461149c565b610524565b61025061027336600461149c565b610538565b610280610549565b6040516101ff91906114b7565b6101f361029b36600461149c565b610559565b6040805180820190915260058152640332e302e360dc1b60208201525b6040516101ff9190611502565b6101f36102d836600461149c565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0390811691161490565b610250610318366004611537565b610564565b61032561057b565b6040516001600160a01b0390911681526020016101ff565b61025061059d565b6101f361035336600461144e565b6105b0565b7f0000000000000000000000000000000000000000000000000000000000000000610325565b6102bd61038c36600461156f565b6105cd565b61025061039f36600461158a565b6105d8565b6102506103b2366004611537565b6105f0565b6004546001600160a01b0316610325565b6101f36103d636600461149c565b610603565b61022f7fea5f4eb72290e50c32abd6c23e45de3d8300b3286e1cbc2e293114b92e034e5e81565b61025061060f565b6102506104183660046115c8565b61061f565b61022f61074b565b61043861043336600461144e565b610755565b60405160ff90911681526020016101ff565b61043861045836600461158a565b61076b565b61032561046b366004611639565b610781565b61025061047e36600461149c565b6107a3565b61025061049136600461149c565b6107db565b6101f36104a436600461158a565b610849565b610280610862565b6102506104bf36600461149c565b61086e565b5f6104ce826108ad565b806104e957506001600160e01b031982166307f5828d60e41b145b8061050457506001600160e01b031982166301ffc9a760e01b145b92915050565b610512610918565b61051e84848484610948565b50505050565b61052c6109ea565b610535816109f2565b50565b6105406109ea565b61053581610aaa565b60606105545f610b33565b905090565b5f6105048183610b3f565b61056c610918565b6105775f8383610b5f565b5050565b5f5f6105876002610bf8565b11156105985761055460025f610c01565b505f90565b6105a5610c0c565b6105ae5f610c6a565b565b5f806105be86868686610755565b60ff161490505b949350505050565b606061050482610cbb565b6105e0610918565b6105eb838383610b5f565b505050565b6105f8610918565b610577825f83610b5f565b5f610504600283610b3f565b6106176109ea565b6105ae610e05565b6106276109ea565b5f819003610648576040516359203cb960e01b815260040160405180910390fd5b5f6106525f610bf8565b111561066057610660610e05565b5f5b818110156105eb5761069983838381811061067f5761067f611650565b9050602002016020810190610694919061149c565b610e36565b6106ca8383838181106106ae576106ae611650565b90506020020160208101906106c3919061149c565b5f90610e6d565b6106e75760405163f280d16160e01b815260040160405180910390fd5b8282828181106106f9576106f9611650565b905060200201602081019061070e919061149c565b6001600160a01b03167f60305ce6c9104acd0969d358f926bf391174340660aaf5e6215261fd6847bf4660405160405180910390a2600101610662565b5f6105545f610bf8565b5f61076285858585610e81565b95945050505050565b5f610777848484610f4c565b90505b9392505050565b5f61078b5f610bf8565b82101561079c576105045f83610c01565b505f919050565b6107ab6109ea565b6107b55f82610b3f565b6107d257604051632cdc3a4160e21b815260040160405180910390fd5b6105358161100e565b6107e36109ea565b6107ec81610e36565b6107f65f82610e6d565b6108135760405163f280d16160e01b815260040160405180910390fd5b6040516001600160a01b038216907f60305ce6c9104acd0969d358f926bf391174340660aaf5e6215261fd6847bf46905f90a250565b5f8061085685858561076b565b60ff1614949350505050565b60606105546002610b33565b610876610c0c565b6001600160a01b0381166108a457604051631e4fbdf760e01b81525f60048201526024015b60405180910390fd5b61053581610c6a565b5f6001600160e01b031982166320c49ce760e01b14806108dd57506001600160e01b031982166378a8de7d60e01b145b806108f857506001600160e01b03198216630c51264760e21b145b8061050457506001600160e01b03198216637157797f60e01b1492915050565b61092b61092361106b565b600290610b3f565b6105ae5760405163e39b3c8f60e01b815260040160405180910390fd5b5f6109525f610bf8565b90505f5b818110156109e2576109685f82610c01565b604051631f2d7a6560e11b81526001600160a01b03888116600483015287811660248301528681166044830152606482018690529190911690633e5af4ca906084015f604051808303815f87803b1580156109c1575f5ffd5b505af11580156109d3573d5f5f3e3d5ffd5b50505050806001019050610956565b505050505050565b6105ae610c0c565b6001600160a01b038116610a19576040516301b8831760e71b815260040160405180910390fd5b610a24600282610b3f565b15610a425760405163f423354760e01b815260040160405180910390fd5b610a4d600282610e6d565b610a6a57604051631b4ddcf360e11b815260040160405180910390fd5b6040516001600160a01b03821681527f2de35142b19ed5a07796cf30791959c592018f70b1d2d7c460eef8ffe713692b906020015b60405180910390a150565b610ab5600282610b3f565b610ad257604051636a2b488360e11b815260040160405180910390fd5b610add600282611074565b610afa57604051631b4ddcf360e11b815260040160405180910390fd5b6040516001600160a01b03821681527f28a4ca7134a3b3f9aff286e79ad3daadb4a06d1b43d037a3a98bdc074edd9b7a90602001610a9f565b60605f61077a83611088565b6001600160a01b03165f9081526001919091016020526040902054151590565b5f610b695f610bf8565b90505f5b81811015610bf157610b7f5f82610c01565b6040516322ebca6d60e21b81526001600160a01b0387811660048301528681166024830152604482018690529190911690638baf29b4906064015f604051808303815f87803b158015610bd0575f5ffd5b505af1158015610be2573d5f5f3e3d5ffd5b50505050806001019050610b6d565b5050505050565b5f610504825490565b5f61077a83836110e1565b610c1461106b565b6001600160a01b0316610c2f6004546001600160a01b031690565b6001600160a01b0316146105ae57610c4561106b565b60405163118cdaa760e01b81526001600160a01b03909116600482015260240161089b565b600480546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b60605f610cc661074b565b90505f5b81811015610dc957610cdb81610781565b604051633e822efb60e11b815260ff861660048201526001600160a01b039190911690637d045df690602401602060405180830381865afa158015610d22573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610d469190611664565b15610dc157610d5481610781565b604051637f4ab1dd60e01b815260ff861660048201526001600160a01b039190911690637f4ab1dd906024015f60405180830381865afa158015610d9a573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526105c59190810190611697565b600101610cca565b505060408051808201909152601881527f556e6b6e6f776e207265737472696374696f6e20636f64650000000000000000602082015292915050565b6040517fdbf61473843cd9be1c9791ce51ef66d0da6c9026d62ba80c1ca433b13fb729b2905f90a16105ae5f611107565b610e3f81611110565b610e5081632497d6cb60e01b61115f565b61053557604051639952e34360e01b815260040160405180910390fd5b5f61077a836001600160a01b03841661117a565b5f5f610e8b61074b565b90505f5b81811015610f40575f610ea182610781565b60405163d32c7bb560e01b81526001600160a01b038a811660048301528981166024830152888116604483015260648201889052919091169063d32c7bb590608401602060405180830381865afa158015610efe573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f22919061174a565b905060ff811615610f375792506105c5915050565b50600101610e8f565b505f9695505050505050565b5f5f610f5661074b565b90505f5b81811015611003575f610f6c82610781565b60405163d4ce141560e01b81526001600160a01b038981166004830152888116602483015260448201889052919091169063d4ce141590606401602060405180830381865afa158015610fc1573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610fe5919061174a565b905060ff811615610ffa57925061077a915050565b50600101610f5a565b505f95945050505050565b6110185f82611074565b6110355760405163f280d16160e01b815260040160405180910390fd5b6040516001600160a01b038216907f6d83315c9718799346b67584ec64301b1457e989c8e35a8e2982a7776c04bfc4905f90a250565b5f6105546111c6565b5f61077a836001600160a01b0384166111d4565b6060815f018054806020026020016040519081016040528092919081815260200182805480156110d557602002820191905f5260205f20905b8154815260200190600101908083116110c1575b50505050509050919050565b5f825f0182815481106110f6576110f6611650565b905f5260205f200154905092915050565b610535816112be565b6001600160a01b0381166111375760405163f9d152fb60e01b815260040160405180910390fd5b6111415f82610b3f565b156105355760405163cc790a4b60e01b815260040160405180910390fd5b5f61116983611317565b801561077a575061077a8383611356565b5f8181526001830160205260408120546111bf57508154600181810184555f848152602080822090930184905584548482528286019093526040902091909155610504565b505f610504565b5f6105545f36816014611377565b5f81815260018301602052604081205480156112ae575f6111f6600183611765565b85549091505f9061120990600190611765565b9050808214611268575f865f01828154811061122757611227611650565b905f5260205f200154905080875f01848154811061124757611247611650565b5f918252602080832090910192909255918252600188019052604090208390555b855486908061127957611279611784565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f905560019350505050610504565b5f915050610504565b5092915050565b5f6112c7825490565b90505f5b8181101561131057826001015f845f0183815481106112ec576112ec611650565b905f5260205f20015481526020019081526020015f205f90558060010190506112cb565b50505f9055565b5f611329826301ffc9a760e01b611356565b1561079c575f80611342846001600160e01b03196113df565b915091508180156105c55750159392505050565b5f5f5f61136385856113df565b915091508180156107625750949350505050565b90508082101580156113b157507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031633145b156113d7576113c436828403815f611798565b6113cd916117bf565b60601c9250505090565b339250505090565b6301ffc9a760e01b5f818152600483905290819060208260248188617530fa92505f511515601f3d11169150509250929050565b5f60208284031215611423575f5ffd5b81356001600160e01b03198116811461077a575f5ffd5b6001600160a01b0381168114610535575f5ffd5b5f5f5f5f60808587031215611461575f5ffd5b843561146c8161143a565b9350602085013561147c8161143a565b9250604085013561148c8161143a565b9396929550929360600135925050565b5f602082840312156114ac575f5ffd5b813561077a8161143a565b602080825282518282018190525f918401906040840190835b818110156114f75783516001600160a01b03168352602093840193909201916001016114d0565b509095945050505050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b5f5f60408385031215611548575f5ffd5b82356115538161143a565b946020939093013593505050565b60ff81168114610535575f5ffd5b5f6020828403121561157f575f5ffd5b813561077a81611561565b5f5f5f6060848603121561159c575f5ffd5b83356115a78161143a565b925060208401356115b78161143a565b929592945050506040919091013590565b5f5f602083850312156115d9575f5ffd5b823567ffffffffffffffff8111156115ef575f5ffd5b8301601f810185136115ff575f5ffd5b803567ffffffffffffffff811115611615575f5ffd5b8560208260051b8401011115611629575f5ffd5b6020919091019590945092505050565b5f60208284031215611649575f5ffd5b5035919050565b634e487b7160e01b5f52603260045260245ffd5b5f60208284031215611674575f5ffd5b8151801515811461077a575f5ffd5b634e487b7160e01b5f52604160045260245ffd5b5f602082840312156116a7575f5ffd5b815167ffffffffffffffff8111156116bd575f5ffd5b8201601f810184136116cd575f5ffd5b805167ffffffffffffffff8111156116e7576116e7611683565b604051601f8201601f19908116603f0116810167ffffffffffffffff8111828210171561171657611716611683565b60405281815282820160200186101561172d575f5ffd5b8160208401602083015e5f91810160200191909152949350505050565b5f6020828403121561175a575f5ffd5b815161077a81611561565b8181038181111561050457634e487b7160e01b5f52601160045260245ffd5b634e487b7160e01b5f52603160045260245ffd5b5f5f858511156117a6575f5ffd5b838611156117b2575f5ffd5b5050820193919092039150565b80356bffffffffffffffffffffffff1981169060148410156112b7576bffffffffffffffffffffffff1960149490940360031b84901b169092169291505056fea26469706673582212201e9fb211c255bec6228b5933ad98df6d4ed24f7c9a53f9bea90aa6130d1d316b64736f6c63430008220033", - "linkReferences": {}, - "deployedLinkReferences": {} -} diff --git a/doc/compilation/v3.0.0-rc2/hardhat/RuleEngineOwnable2Step.sol/RuleEngineOwnable2Step.dbg.json b/doc/compilation/v3.0.0-rc2/hardhat/RuleEngineOwnable2Step.sol/RuleEngineOwnable2Step.dbg.json deleted file mode 100644 index 35abe72a..00000000 --- a/doc/compilation/v3.0.0-rc2/hardhat/RuleEngineOwnable2Step.sol/RuleEngineOwnable2Step.dbg.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "_format": "hh-sol-dbg-1", - "buildInfo": "../../../build-info/6f3c11638d96ee863225bd1b2732b06d.json" -} diff --git a/doc/compilation/v3.0.0-rc2/hardhat/RuleEngineOwnable2Step.sol/RuleEngineOwnable2Step.json b/doc/compilation/v3.0.0-rc2/hardhat/RuleEngineOwnable2Step.sol/RuleEngineOwnable2Step.json deleted file mode 100644 index 2191aa7b..00000000 --- a/doc/compilation/v3.0.0-rc2/hardhat/RuleEngineOwnable2Step.sol/RuleEngineOwnable2Step.json +++ /dev/null @@ -1,766 +0,0 @@ -{ - "_format": "hh-sol-artifact-1", - "contractName": "RuleEngineOwnable2Step", - "sourceName": "src/deployment/RuleEngineOwnable2Step.sol", - "abi": [ - { - "inputs": [ - { - "internalType": "address", - "name": "owner_", - "type": "address" - }, - { - "internalType": "address", - "name": "forwarderIrrevocable", - "type": "address" - }, - { - "internalType": "address", - "name": "tokenContract", - "type": "address" - } - ], - "stateMutability": "nonpayable", - "type": "constructor" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "owner", - "type": "address" - } - ], - "name": "OwnableInvalidOwner", - "type": "error" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "account", - "type": "address" - } - ], - "name": "OwnableUnauthorizedAccount", - "type": "error" - }, - { - "inputs": [], - "name": "RuleEngine_AdminWithAddressZeroNotAllowed", - "type": "error" - }, - { - "inputs": [], - "name": "RuleEngine_ERC3643Compliance_InvalidTokenAddress", - "type": "error" - }, - { - "inputs": [], - "name": "RuleEngine_ERC3643Compliance_OperationNotSuccessful", - "type": "error" - }, - { - "inputs": [], - "name": "RuleEngine_ERC3643Compliance_TokenAlreadyBound", - "type": "error" - }, - { - "inputs": [], - "name": "RuleEngine_ERC3643Compliance_TokenNotBound", - "type": "error" - }, - { - "inputs": [], - "name": "RuleEngine_ERC3643Compliance_UnauthorizedCaller", - "type": "error" - }, - { - "inputs": [], - "name": "RuleEngine_RuleInvalidInterface", - "type": "error" - }, - { - "inputs": [], - "name": "RuleEngine_RulesManagementModule_ArrayIsEmpty", - "type": "error" - }, - { - "inputs": [], - "name": "RuleEngine_RulesManagementModule_OperationNotSuccessful", - "type": "error" - }, - { - "inputs": [], - "name": "RuleEngine_RulesManagementModule_RuleAddressZeroNotAllowed", - "type": "error" - }, - { - "inputs": [], - "name": "RuleEngine_RulesManagementModule_RuleAlreadyExists", - "type": "error" - }, - { - "inputs": [], - "name": "RuleEngine_RulesManagementModule_RuleDoNotMatch", - "type": "error" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "contract IRule", - "name": "rule", - "type": "address" - } - ], - "name": "AddRule", - "type": "event" - }, - { - "anonymous": false, - "inputs": [], - "name": "ClearRules", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "previousOwner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "OwnershipTransferStarted", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "address", - "name": "previousOwner", - "type": "address" - }, - { - "indexed": true, - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "OwnershipTransferred", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": true, - "internalType": "contract IRule", - "name": "rule", - "type": "address" - } - ], - "name": "RemoveRule", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "token", - "type": "address" - } - ], - "name": "TokenBound", - "type": "event" - }, - { - "anonymous": false, - "inputs": [ - { - "indexed": false, - "internalType": "address", - "name": "token", - "type": "address" - } - ], - "name": "TokenUnbound", - "type": "event" - }, - { - "inputs": [], - "name": "COMPLIANCE_MANAGER_ROLE", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "RULES_MANAGEMENT_ROLE", - "outputs": [ - { - "internalType": "bytes32", - "name": "", - "type": "bytes32" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "acceptOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract IRule", - "name": "rule_", - "type": "address" - } - ], - "name": "addRule", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "token", - "type": "address" - } - ], - "name": "bindToken", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "canTransfer", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "canTransferFrom", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "clearRules", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract IRule", - "name": "rule_", - "type": "address" - } - ], - "name": "containsRule", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "created", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "destroyed", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "detectTransferRestriction", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "detectTransferRestrictionFrom", - "outputs": [ - { - "internalType": "uint8", - "name": "", - "type": "uint8" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getTokenBound", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "getTokenBounds", - "outputs": [ - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "token", - "type": "address" - } - ], - "name": "isTokenBound", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "forwarder", - "type": "address" - } - ], - "name": "isTrustedForwarder", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint8", - "name": "restrictionCode", - "type": "uint8" - } - ], - "name": "messageForTransferRestriction", - "outputs": [ - { - "internalType": "string", - "name": "", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "owner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "pendingOwner", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract IRule", - "name": "rule_", - "type": "address" - } - ], - "name": "removeRule", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "renounceOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "uint256", - "name": "ruleId", - "type": "uint256" - } - ], - "name": "rule", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "rules", - "outputs": [ - { - "internalType": "address[]", - "name": "", - "type": "address[]" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [], - "name": "rulesCount", - "outputs": [ - { - "internalType": "uint256", - "name": "", - "type": "uint256" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "contract IRule[]", - "name": "rules_", - "type": "address[]" - } - ], - "name": "setRules", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "bytes4", - "name": "interfaceId", - "type": "bytes4" - } - ], - "name": "supportsInterface", - "outputs": [ - { - "internalType": "bool", - "name": "", - "type": "bool" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "newOwner", - "type": "address" - } - ], - "name": "transferOwnership", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "spender", - "type": "address" - }, - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "transferred", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "from", - "type": "address" - }, - { - "internalType": "address", - "name": "to", - "type": "address" - }, - { - "internalType": "uint256", - "name": "value", - "type": "uint256" - } - ], - "name": "transferred", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "trustedForwarder", - "outputs": [ - { - "internalType": "address", - "name": "", - "type": "address" - } - ], - "stateMutability": "view", - "type": "function" - }, - { - "inputs": [ - { - "internalType": "address", - "name": "token", - "type": "address" - } - ], - "name": "unbindToken", - "outputs": [], - "stateMutability": "nonpayable", - "type": "function" - }, - { - "inputs": [], - "name": "version", - "outputs": [ - { - "internalType": "string", - "name": "version_", - "type": "string" - } - ], - "stateMutability": "view", - "type": "function" - } - ], - "bytecode": "0x60a060405234801561000f575f5ffd5b50604051611bd1380380611bd183398101604081905261002e91610258565b6001600160a01b038083166080528390839083908116156100525761005281610093565b50506001600160a01b03811661008157604051631e4fbdf760e01b81525f600482015260240160405180910390fd5b61008a8161014a565b50505050610298565b6001600160a01b0381166100ba576040516301b8831760e71b815260040160405180910390fd5b6100c5600282610166565b156100e35760405163f423354760e01b815260040160405180910390fd5b6100ee60028261018c565b61010b57604051631b4ddcf360e11b815260040160405180910390fd5b6040516001600160a01b03821681527f2de35142b19ed5a07796cf30791959c592018f70b1d2d7c460eef8ffe713692b9060200160405180910390a150565b600580546001600160a01b0319169055610163816101a0565b50565b6001600160a01b0381165f90815260018301602052604081205415155b90505b92915050565b5f610183836001600160a01b0384166101f1565b600480546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b5f81815260018301602052604081205461023657508154600181810184555f848152602080822090930184905584548482528286019093526040902091909155610186565b505f610186565b80516001600160a01b0381168114610253575f5ffd5b919050565b5f5f5f6060848603121561026a575f5ffd5b6102738461023d565b92506102816020850161023d565b915061028f6040850161023d565b90509250925092565b6080516119136102be5f395f81816102f00152818161037801526113ab01526119135ff3fe608060405234801561000f575f5ffd5b50600436106101f2575f3560e01c80638baf29b411610114578063d32c7bb5116100a9578063e30c397811610079578063e30c3978146104a1578063e3c4602c146104b2578063e46638e6146104c5578063e54621d2146104d8578063f2fde38b146104e0575f5ffd5b8063d32c7bb514610443578063d4ce141514610468578063db18af6c1461047b578063df21950f1461048e575f5ffd5b80639b11c115116100e45780639b11c115146103f9578063b043572e14610420578063b27aef3a14610428578063bc13eacc1461043b575f5ffd5b80638baf29b4146103af5780638d2ea772146103c25780638da5cb5b146103d5578063993e8b95146103e6575f5ffd5b8063572b6c051161018a5780637157797f1161015a5780637157797f1461035b57806379ba50971461036e5780637da0a877146103765780637f4ab1dd1461039c575f5ffd5b8063572b6c05146102e05780635f8dead3146103205780636a3edf2814610333578063715018a614610353575f5ffd5b806340db3b50116101c557806340db3b501461027b57806352f6747a1461028e57806354e4b945146102a357806354fd4d50146102b6575f5ffd5b806301ffc9a7146101f657806303c26bcd1461021e5780633e5af4ca146102535780633ff5aa0214610268575b5f5ffd5b6102096102043660046114f1565b6104f3565b60405190151581526020015b60405180910390f35b6102457fe5c50d0927e06141e032cb9a67e1d7092dc85c0b0825191f7e1cede60002856881565b604051908152602001610215565b61026661026136600461152c565b610539565b005b61026661027636600461157a565b610553565b61026661028936600461157a565b610567565b610296610578565b6040516102159190611595565b6102096102b136600461157a565b610588565b6040805180820190915260058152640332e302e360dc1b60208201525b60405161021591906115e0565b6102096102ee36600461157a565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0390811691161490565b61026661032e366004611615565b610593565b61033b6105aa565b6040516001600160a01b039091168152602001610215565b6102666105cc565b61020961036936600461152c565b6105df565b6102666105fc565b7f000000000000000000000000000000000000000000000000000000000000000061033b565b6102d36103aa36600461164d565b610663565b6102666103bd366004611668565b61066e565b6102666103d0366004611615565b610686565b6004546001600160a01b031661033b565b6102096103f436600461157a565b610699565b6102457fea5f4eb72290e50c32abd6c23e45de3d8300b3286e1cbc2e293114b92e034e5e81565b6102666106a5565b6102666104363660046116a6565b6106b5565b6102456107e1565b61045661045136600461152c565b6107eb565b60405160ff9091168152602001610215565b610456610476366004611668565b610801565b61033b610489366004611717565b610817565b61026661049c36600461157a565b610839565b6005546001600160a01b031661033b565b6102666104c036600461157a565b610871565b6102096104d3366004611668565b6108df565b6102966108f8565b6102666104ee36600461157a565b610904565b5f6104fd82610975565b8061051857506001600160e01b031982166307f5828d60e41b145b8061053357506001600160e01b031982166301ffc9a760e01b145b92915050565b6105416109e0565b61054d84848484610a10565b50505050565b61055b610ab2565b61056481610aba565b50565b61056f610ab2565b61056481610b72565b60606105835f610bfb565b905090565b5f6105338183610c07565b61059b6109e0565b6105a65f8383610c27565b5050565b5f5f6105b66002610cc0565b11156105c75761058360025f610cc9565b505f90565b6105d4610cd4565b6105dd5f610d32565b565b5f806105ed868686866107eb565b60ff161490505b949350505050565b5f610605610d4b565b9050806001600160a01b03166106236005546001600160a01b031690565b6001600160a01b03161461065a5760405163118cdaa760e01b81526001600160a01b03821660048201526024015b60405180910390fd5b61056481610d32565b606061053382610d54565b6106766109e0565b610681838383610c27565b505050565b61068e6109e0565b6105a6825f83610c27565b5f610533600283610c07565b6106ad610ab2565b6105dd610e9e565b6106bd610ab2565b5f8190036106de576040516359203cb960e01b815260040160405180910390fd5b5f6106e85f610cc0565b11156106f6576106f6610e9e565b5f5b818110156106815761072f8383838181106107155761071561172e565b905060200201602081019061072a919061157a565b610ecf565b6107608383838181106107445761074461172e565b9050602002016020810190610759919061157a565b5f90610f06565b61077d5760405163f280d16160e01b815260040160405180910390fd5b82828281811061078f5761078f61172e565b90506020020160208101906107a4919061157a565b6001600160a01b03167f60305ce6c9104acd0969d358f926bf391174340660aaf5e6215261fd6847bf4660405160405180910390a26001016106f8565b5f6105835f610cc0565b5f6107f885858585610f1a565b95945050505050565b5f61080d848484610fe5565b90505b9392505050565b5f6108215f610cc0565b821015610832576105335f83610cc9565b505f919050565b610841610ab2565b61084b5f82610c07565b61086857604051632cdc3a4160e21b815260040160405180910390fd5b610564816110a7565b610879610ab2565b61088281610ecf565b61088c5f82610f06565b6108a95760405163f280d16160e01b815260040160405180910390fd5b6040516001600160a01b038216907f60305ce6c9104acd0969d358f926bf391174340660aaf5e6215261fd6847bf46905f90a250565b5f806108ec858585610801565b60ff1614949350505050565b60606105836002610bfb565b61090c610cd4565b600580546001600160a01b0383166001600160a01b0319909116811790915561093d6004546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b5f6001600160e01b031982166320c49ce760e01b14806109a557506001600160e01b031982166378a8de7d60e01b145b806109c057506001600160e01b03198216630c51264760e21b145b8061053357506001600160e01b03198216637157797f60e01b1492915050565b6109f36109eb610d4b565b600290610c07565b6105dd5760405163e39b3c8f60e01b815260040160405180910390fd5b5f610a1a5f610cc0565b90505f5b81811015610aaa57610a305f82610cc9565b604051631f2d7a6560e11b81526001600160a01b03888116600483015287811660248301528681166044830152606482018690529190911690633e5af4ca906084015f604051808303815f87803b158015610a89575f5ffd5b505af1158015610a9b573d5f5f3e3d5ffd5b50505050806001019050610a1e565b505050505050565b6105dd610cd4565b6001600160a01b038116610ae1576040516301b8831760e71b815260040160405180910390fd5b610aec600282610c07565b15610b0a5760405163f423354760e01b815260040160405180910390fd5b610b15600282610f06565b610b3257604051631b4ddcf360e11b815260040160405180910390fd5b6040516001600160a01b03821681527f2de35142b19ed5a07796cf30791959c592018f70b1d2d7c460eef8ffe713692b906020015b60405180910390a150565b610b7d600282610c07565b610b9a57604051636a2b488360e11b815260040160405180910390fd5b610ba5600282611104565b610bc257604051631b4ddcf360e11b815260040160405180910390fd5b6040516001600160a01b03821681527f28a4ca7134a3b3f9aff286e79ad3daadb4a06d1b43d037a3a98bdc074edd9b7a90602001610b67565b60605f61081083611118565b6001600160a01b03165f9081526001919091016020526040902054151590565b5f610c315f610cc0565b90505f5b81811015610cb957610c475f82610cc9565b6040516322ebca6d60e21b81526001600160a01b0387811660048301528681166024830152604482018690529190911690638baf29b4906064015f604051808303815f87803b158015610c98575f5ffd5b505af1158015610caa573d5f5f3e3d5ffd5b50505050806001019050610c35565b5050505050565b5f610533825490565b5f6108108383611171565b610cdc610d4b565b6001600160a01b0316610cf76004546001600160a01b031690565b6001600160a01b0316146105dd57610d0d610d4b565b60405163118cdaa760e01b81526001600160a01b039091166004820152602401610651565b600580546001600160a01b031916905561056481611197565b5f6105836111e8565b60605f610d5f6107e1565b90505f5b81811015610e6257610d7481610817565b604051633e822efb60e11b815260ff861660048201526001600160a01b039190911690637d045df690602401602060405180830381865afa158015610dbb573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ddf9190611742565b15610e5a57610ded81610817565b604051637f4ab1dd60e01b815260ff861660048201526001600160a01b039190911690637f4ab1dd906024015f60405180830381865afa158015610e33573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526105f49190810190611775565b600101610d63565b505060408051808201909152601881527f556e6b6e6f776e207265737472696374696f6e20636f64650000000000000000602082015292915050565b6040517fdbf61473843cd9be1c9791ce51ef66d0da6c9026d62ba80c1ca433b13fb729b2905f90a16105dd5f6111f1565b610ed8816111fa565b610ee981632497d6cb60e01b611249565b61056457604051639952e34360e01b815260040160405180910390fd5b5f610810836001600160a01b038416611264565b5f5f610f246107e1565b90505f5b81811015610fd9575f610f3a82610817565b60405163d32c7bb560e01b81526001600160a01b038a811660048301528981166024830152888116604483015260648201889052919091169063d32c7bb590608401602060405180830381865afa158015610f97573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610fbb9190611828565b905060ff811615610fd05792506105f4915050565b50600101610f28565b505f9695505050505050565b5f5f610fef6107e1565b90505f5b8181101561109c575f61100582610817565b60405163d4ce141560e01b81526001600160a01b038981166004830152888116602483015260448201889052919091169063d4ce141590606401602060405180830381865afa15801561105a573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061107e9190611828565b905060ff811615611093579250610810915050565b50600101610ff3565b505f95945050505050565b6110b15f82611104565b6110ce5760405163f280d16160e01b815260040160405180910390fd5b6040516001600160a01b038216907f6d83315c9718799346b67584ec64301b1457e989c8e35a8e2982a7776c04bfc4905f90a250565b5f610810836001600160a01b0384166112b0565b6060815f0180548060200260200160405190810160405280929190818152602001828054801561116557602002820191905f5260205f20905b815481526020019060010190808311611151575b50505050509050919050565b5f825f0182815481106111865761118661172e565b905f5260205f200154905092915050565b600480546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b5f61058361139a565b61056481611404565b6001600160a01b0381166112215760405163f9d152fb60e01b815260040160405180910390fd5b61122b5f82610c07565b156105645760405163cc790a4b60e01b815260040160405180910390fd5b5f6112538361145d565b80156108105750610810838361149c565b5f8181526001830160205260408120546112a957508154600181810184555f848152602080822090930184905584548482528286019093526040902091909155610533565b505f610533565b5f818152600183016020526040812054801561138a575f6112d2600183611843565b85549091505f906112e590600190611843565b9050808214611344575f865f0182815481106113035761130361172e565b905f5260205f200154905080875f0184815481106113235761132361172e565b5f918252602080832090910192909255918252600188019052604090208390555b855486908061135557611355611862565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f905560019350505050610533565b5f915050610533565b5092915050565b5f3660148082108015906113d657507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031633145b156113fc576113e936828403815f611876565b6113f29161189d565b60601c9250505090565b339250505090565b5f61140d825490565b90505f5b8181101561145657826001015f845f0183815481106114325761143261172e565b905f5260205f20015481526020019081526020015f205f9055806001019050611411565b50505f9055565b5f61146f826301ffc9a760e01b61149c565b15610832575f80611488846001600160e01b03196114bd565b915091508180156105f45750159392505050565b5f5f5f6114a985856114bd565b915091508180156107f85750949350505050565b6301ffc9a760e01b5f818152600483905290819060208260248188617530fa92505f511515601f3d11169150509250929050565b5f60208284031215611501575f5ffd5b81356001600160e01b031981168114610810575f5ffd5b6001600160a01b0381168114610564575f5ffd5b5f5f5f5f6080858703121561153f575f5ffd5b843561154a81611518565b9350602085013561155a81611518565b9250604085013561156a81611518565b9396929550929360600135925050565b5f6020828403121561158a575f5ffd5b813561081081611518565b602080825282518282018190525f918401906040840190835b818110156115d55783516001600160a01b03168352602093840193909201916001016115ae565b509095945050505050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b5f5f60408385031215611626575f5ffd5b823561163181611518565b946020939093013593505050565b60ff81168114610564575f5ffd5b5f6020828403121561165d575f5ffd5b81356108108161163f565b5f5f5f6060848603121561167a575f5ffd5b833561168581611518565b9250602084013561169581611518565b929592945050506040919091013590565b5f5f602083850312156116b7575f5ffd5b823567ffffffffffffffff8111156116cd575f5ffd5b8301601f810185136116dd575f5ffd5b803567ffffffffffffffff8111156116f3575f5ffd5b8560208260051b8401011115611707575f5ffd5b6020919091019590945092505050565b5f60208284031215611727575f5ffd5b5035919050565b634e487b7160e01b5f52603260045260245ffd5b5f60208284031215611752575f5ffd5b81518015158114610810575f5ffd5b634e487b7160e01b5f52604160045260245ffd5b5f60208284031215611785575f5ffd5b815167ffffffffffffffff81111561179b575f5ffd5b8201601f810184136117ab575f5ffd5b805167ffffffffffffffff8111156117c5576117c5611761565b604051601f8201601f19908116603f0116810167ffffffffffffffff811182821017156117f4576117f4611761565b60405281815282820160200186101561180b575f5ffd5b8160208401602083015e5f91810160200191909152949350505050565b5f60208284031215611838575f5ffd5b81516108108161163f565b8181038181111561053357634e487b7160e01b5f52601160045260245ffd5b634e487b7160e01b5f52603160045260245ffd5b5f5f85851115611884575f5ffd5b83861115611890575f5ffd5b5050820193919092039150565b80356bffffffffffffffffffffffff198116906014841015611393576bffffffffffffffffffffffff1960149490940360031b84901b169092169291505056fea26469706673582212203eeb560dee8ab479a1244c47104759fd3416c361073c50829fba85457e2504a264736f6c63430008220033", - "deployedBytecode": "0x608060405234801561000f575f5ffd5b50600436106101f2575f3560e01c80638baf29b411610114578063d32c7bb5116100a9578063e30c397811610079578063e30c3978146104a1578063e3c4602c146104b2578063e46638e6146104c5578063e54621d2146104d8578063f2fde38b146104e0575f5ffd5b8063d32c7bb514610443578063d4ce141514610468578063db18af6c1461047b578063df21950f1461048e575f5ffd5b80639b11c115116100e45780639b11c115146103f9578063b043572e14610420578063b27aef3a14610428578063bc13eacc1461043b575f5ffd5b80638baf29b4146103af5780638d2ea772146103c25780638da5cb5b146103d5578063993e8b95146103e6575f5ffd5b8063572b6c051161018a5780637157797f1161015a5780637157797f1461035b57806379ba50971461036e5780637da0a877146103765780637f4ab1dd1461039c575f5ffd5b8063572b6c05146102e05780635f8dead3146103205780636a3edf2814610333578063715018a614610353575f5ffd5b806340db3b50116101c557806340db3b501461027b57806352f6747a1461028e57806354e4b945146102a357806354fd4d50146102b6575f5ffd5b806301ffc9a7146101f657806303c26bcd1461021e5780633e5af4ca146102535780633ff5aa0214610268575b5f5ffd5b6102096102043660046114f1565b6104f3565b60405190151581526020015b60405180910390f35b6102457fe5c50d0927e06141e032cb9a67e1d7092dc85c0b0825191f7e1cede60002856881565b604051908152602001610215565b61026661026136600461152c565b610539565b005b61026661027636600461157a565b610553565b61026661028936600461157a565b610567565b610296610578565b6040516102159190611595565b6102096102b136600461157a565b610588565b6040805180820190915260058152640332e302e360dc1b60208201525b60405161021591906115e0565b6102096102ee36600461157a565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0390811691161490565b61026661032e366004611615565b610593565b61033b6105aa565b6040516001600160a01b039091168152602001610215565b6102666105cc565b61020961036936600461152c565b6105df565b6102666105fc565b7f000000000000000000000000000000000000000000000000000000000000000061033b565b6102d36103aa36600461164d565b610663565b6102666103bd366004611668565b61066e565b6102666103d0366004611615565b610686565b6004546001600160a01b031661033b565b6102096103f436600461157a565b610699565b6102457fea5f4eb72290e50c32abd6c23e45de3d8300b3286e1cbc2e293114b92e034e5e81565b6102666106a5565b6102666104363660046116a6565b6106b5565b6102456107e1565b61045661045136600461152c565b6107eb565b60405160ff9091168152602001610215565b610456610476366004611668565b610801565b61033b610489366004611717565b610817565b61026661049c36600461157a565b610839565b6005546001600160a01b031661033b565b6102666104c036600461157a565b610871565b6102096104d3366004611668565b6108df565b6102966108f8565b6102666104ee36600461157a565b610904565b5f6104fd82610975565b8061051857506001600160e01b031982166307f5828d60e41b145b8061053357506001600160e01b031982166301ffc9a760e01b145b92915050565b6105416109e0565b61054d84848484610a10565b50505050565b61055b610ab2565b61056481610aba565b50565b61056f610ab2565b61056481610b72565b60606105835f610bfb565b905090565b5f6105338183610c07565b61059b6109e0565b6105a65f8383610c27565b5050565b5f5f6105b66002610cc0565b11156105c75761058360025f610cc9565b505f90565b6105d4610cd4565b6105dd5f610d32565b565b5f806105ed868686866107eb565b60ff161490505b949350505050565b5f610605610d4b565b9050806001600160a01b03166106236005546001600160a01b031690565b6001600160a01b03161461065a5760405163118cdaa760e01b81526001600160a01b03821660048201526024015b60405180910390fd5b61056481610d32565b606061053382610d54565b6106766109e0565b610681838383610c27565b505050565b61068e6109e0565b6105a6825f83610c27565b5f610533600283610c07565b6106ad610ab2565b6105dd610e9e565b6106bd610ab2565b5f8190036106de576040516359203cb960e01b815260040160405180910390fd5b5f6106e85f610cc0565b11156106f6576106f6610e9e565b5f5b818110156106815761072f8383838181106107155761071561172e565b905060200201602081019061072a919061157a565b610ecf565b6107608383838181106107445761074461172e565b9050602002016020810190610759919061157a565b5f90610f06565b61077d5760405163f280d16160e01b815260040160405180910390fd5b82828281811061078f5761078f61172e565b90506020020160208101906107a4919061157a565b6001600160a01b03167f60305ce6c9104acd0969d358f926bf391174340660aaf5e6215261fd6847bf4660405160405180910390a26001016106f8565b5f6105835f610cc0565b5f6107f885858585610f1a565b95945050505050565b5f61080d848484610fe5565b90505b9392505050565b5f6108215f610cc0565b821015610832576105335f83610cc9565b505f919050565b610841610ab2565b61084b5f82610c07565b61086857604051632cdc3a4160e21b815260040160405180910390fd5b610564816110a7565b610879610ab2565b61088281610ecf565b61088c5f82610f06565b6108a95760405163f280d16160e01b815260040160405180910390fd5b6040516001600160a01b038216907f60305ce6c9104acd0969d358f926bf391174340660aaf5e6215261fd6847bf46905f90a250565b5f806108ec858585610801565b60ff1614949350505050565b60606105836002610bfb565b61090c610cd4565b600580546001600160a01b0383166001600160a01b0319909116811790915561093d6004546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b5f6001600160e01b031982166320c49ce760e01b14806109a557506001600160e01b031982166378a8de7d60e01b145b806109c057506001600160e01b03198216630c51264760e21b145b8061053357506001600160e01b03198216637157797f60e01b1492915050565b6109f36109eb610d4b565b600290610c07565b6105dd5760405163e39b3c8f60e01b815260040160405180910390fd5b5f610a1a5f610cc0565b90505f5b81811015610aaa57610a305f82610cc9565b604051631f2d7a6560e11b81526001600160a01b03888116600483015287811660248301528681166044830152606482018690529190911690633e5af4ca906084015f604051808303815f87803b158015610a89575f5ffd5b505af1158015610a9b573d5f5f3e3d5ffd5b50505050806001019050610a1e565b505050505050565b6105dd610cd4565b6001600160a01b038116610ae1576040516301b8831760e71b815260040160405180910390fd5b610aec600282610c07565b15610b0a5760405163f423354760e01b815260040160405180910390fd5b610b15600282610f06565b610b3257604051631b4ddcf360e11b815260040160405180910390fd5b6040516001600160a01b03821681527f2de35142b19ed5a07796cf30791959c592018f70b1d2d7c460eef8ffe713692b906020015b60405180910390a150565b610b7d600282610c07565b610b9a57604051636a2b488360e11b815260040160405180910390fd5b610ba5600282611104565b610bc257604051631b4ddcf360e11b815260040160405180910390fd5b6040516001600160a01b03821681527f28a4ca7134a3b3f9aff286e79ad3daadb4a06d1b43d037a3a98bdc074edd9b7a90602001610b67565b60605f61081083611118565b6001600160a01b03165f9081526001919091016020526040902054151590565b5f610c315f610cc0565b90505f5b81811015610cb957610c475f82610cc9565b6040516322ebca6d60e21b81526001600160a01b0387811660048301528681166024830152604482018690529190911690638baf29b4906064015f604051808303815f87803b158015610c98575f5ffd5b505af1158015610caa573d5f5f3e3d5ffd5b50505050806001019050610c35565b5050505050565b5f610533825490565b5f6108108383611171565b610cdc610d4b565b6001600160a01b0316610cf76004546001600160a01b031690565b6001600160a01b0316146105dd57610d0d610d4b565b60405163118cdaa760e01b81526001600160a01b039091166004820152602401610651565b600580546001600160a01b031916905561056481611197565b5f6105836111e8565b60605f610d5f6107e1565b90505f5b81811015610e6257610d7481610817565b604051633e822efb60e11b815260ff861660048201526001600160a01b039190911690637d045df690602401602060405180830381865afa158015610dbb573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610ddf9190611742565b15610e5a57610ded81610817565b604051637f4ab1dd60e01b815260ff861660048201526001600160a01b039190911690637f4ab1dd906024015f60405180830381865afa158015610e33573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526105f49190810190611775565b600101610d63565b505060408051808201909152601881527f556e6b6e6f776e207265737472696374696f6e20636f64650000000000000000602082015292915050565b6040517fdbf61473843cd9be1c9791ce51ef66d0da6c9026d62ba80c1ca433b13fb729b2905f90a16105dd5f6111f1565b610ed8816111fa565b610ee981632497d6cb60e01b611249565b61056457604051639952e34360e01b815260040160405180910390fd5b5f610810836001600160a01b038416611264565b5f5f610f246107e1565b90505f5b81811015610fd9575f610f3a82610817565b60405163d32c7bb560e01b81526001600160a01b038a811660048301528981166024830152888116604483015260648201889052919091169063d32c7bb590608401602060405180830381865afa158015610f97573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610fbb9190611828565b905060ff811615610fd05792506105f4915050565b50600101610f28565b505f9695505050505050565b5f5f610fef6107e1565b90505f5b8181101561109c575f61100582610817565b60405163d4ce141560e01b81526001600160a01b038981166004830152888116602483015260448201889052919091169063d4ce141590606401602060405180830381865afa15801561105a573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061107e9190611828565b905060ff811615611093579250610810915050565b50600101610ff3565b505f95945050505050565b6110b15f82611104565b6110ce5760405163f280d16160e01b815260040160405180910390fd5b6040516001600160a01b038216907f6d83315c9718799346b67584ec64301b1457e989c8e35a8e2982a7776c04bfc4905f90a250565b5f610810836001600160a01b0384166112b0565b6060815f0180548060200260200160405190810160405280929190818152602001828054801561116557602002820191905f5260205f20905b815481526020019060010190808311611151575b50505050509050919050565b5f825f0182815481106111865761118661172e565b905f5260205f200154905092915050565b600480546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b5f61058361139a565b61056481611404565b6001600160a01b0381166112215760405163f9d152fb60e01b815260040160405180910390fd5b61122b5f82610c07565b156105645760405163cc790a4b60e01b815260040160405180910390fd5b5f6112538361145d565b80156108105750610810838361149c565b5f8181526001830160205260408120546112a957508154600181810184555f848152602080822090930184905584548482528286019093526040902091909155610533565b505f610533565b5f818152600183016020526040812054801561138a575f6112d2600183611843565b85549091505f906112e590600190611843565b9050808214611344575f865f0182815481106113035761130361172e565b905f5260205f200154905080875f0184815481106113235761132361172e565b5f918252602080832090910192909255918252600188019052604090208390555b855486908061135557611355611862565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f905560019350505050610533565b5f915050610533565b5092915050565b5f3660148082108015906113d657507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031633145b156113fc576113e936828403815f611876565b6113f29161189d565b60601c9250505090565b339250505090565b5f61140d825490565b90505f5b8181101561145657826001015f845f0183815481106114325761143261172e565b905f5260205f20015481526020019081526020015f205f9055806001019050611411565b50505f9055565b5f61146f826301ffc9a760e01b61149c565b15610832575f80611488846001600160e01b03196114bd565b915091508180156105f45750159392505050565b5f5f5f6114a985856114bd565b915091508180156107f85750949350505050565b6301ffc9a760e01b5f818152600483905290819060208260248188617530fa92505f511515601f3d11169150509250929050565b5f60208284031215611501575f5ffd5b81356001600160e01b031981168114610810575f5ffd5b6001600160a01b0381168114610564575f5ffd5b5f5f5f5f6080858703121561153f575f5ffd5b843561154a81611518565b9350602085013561155a81611518565b9250604085013561156a81611518565b9396929550929360600135925050565b5f6020828403121561158a575f5ffd5b813561081081611518565b602080825282518282018190525f918401906040840190835b818110156115d55783516001600160a01b03168352602093840193909201916001016115ae565b509095945050505050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b5f5f60408385031215611626575f5ffd5b823561163181611518565b946020939093013593505050565b60ff81168114610564575f5ffd5b5f6020828403121561165d575f5ffd5b81356108108161163f565b5f5f5f6060848603121561167a575f5ffd5b833561168581611518565b9250602084013561169581611518565b929592945050506040919091013590565b5f5f602083850312156116b7575f5ffd5b823567ffffffffffffffff8111156116cd575f5ffd5b8301601f810185136116dd575f5ffd5b803567ffffffffffffffff8111156116f3575f5ffd5b8560208260051b8401011115611707575f5ffd5b6020919091019590945092505050565b5f60208284031215611727575f5ffd5b5035919050565b634e487b7160e01b5f52603260045260245ffd5b5f60208284031215611752575f5ffd5b81518015158114610810575f5ffd5b634e487b7160e01b5f52604160045260245ffd5b5f60208284031215611785575f5ffd5b815167ffffffffffffffff81111561179b575f5ffd5b8201601f810184136117ab575f5ffd5b805167ffffffffffffffff8111156117c5576117c5611761565b604051601f8201601f19908116603f0116810167ffffffffffffffff811182821017156117f4576117f4611761565b60405281815282820160200186101561180b575f5ffd5b8160208401602083015e5f91810160200191909152949350505050565b5f60208284031215611838575f5ffd5b81516108108161163f565b8181038181111561053357634e487b7160e01b5f52601160045260245ffd5b634e487b7160e01b5f52603160045260245ffd5b5f5f85851115611884575f5ffd5b83861115611890575f5ffd5b5050820193919092039150565b80356bffffffffffffffffffffffff198116906014841015611393576bffffffffffffffffffffffff1960149490940360031b84901b169092169291505056fea26469706673582212203eeb560dee8ab479a1244c47104759fd3416c361073c50829fba85457e2504a264736f6c63430008220033", - "linkReferences": {}, - "deployedLinkReferences": {} -} diff --git a/doc/compilation/v3.0.0-rc7/foundry/RuleEngine.sol/RuleEngine.json b/doc/compilation/v3.0.0-rc7/foundry/RuleEngine.sol/RuleEngine.json new file mode 100644 index 00000000..0abe12a2 --- /dev/null +++ b/doc/compilation/v3.0.0-rc7/foundry/RuleEngine.sol/RuleEngine.json @@ -0,0 +1 @@ +{"abi":[{"type":"constructor","inputs":[{"name":"admin","type":"address","internalType":"address"},{"name":"tokenContract","type":"address","internalType":"address"}],"stateMutability":"nonpayable"},{"type":"function","name":"COMPLIANCE_MANAGER_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"DEFAULT_ADMIN_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"DEFAULT_MAX_RULES","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"RULES_MANAGEMENT_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"addRule","inputs":[{"name":"rule_","type":"address","internalType":"contract IRule"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"bindToken","inputs":[{"name":"token","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"bindTokens","inputs":[{"name":"tokens","type":"address[]","internalType":"address[]"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"canTransfer","inputs":[{"name":"from","type":"address","internalType":"address"},{"name":"to","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"canTransferFrom","inputs":[{"name":"spender","type":"address","internalType":"address"},{"name":"from","type":"address","internalType":"address"},{"name":"to","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"clearRules","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"containsRule","inputs":[{"name":"rule_","type":"address","internalType":"contract IRule"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"created","inputs":[{"name":"to","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"destroyed","inputs":[{"name":"from","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"detectTransferRestriction","inputs":[{"name":"from","type":"address","internalType":"address"},{"name":"to","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint8","internalType":"uint8"}],"stateMutability":"view"},{"type":"function","name":"detectTransferRestrictionFrom","inputs":[{"name":"spender","type":"address","internalType":"address"},{"name":"from","type":"address","internalType":"address"},{"name":"to","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint8","internalType":"uint8"}],"stateMutability":"view"},{"type":"function","name":"getRoleAdmin","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"getRoleMember","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"index","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"getRoleMemberCount","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getRoleMembers","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"","type":"address[]","internalType":"address[]"}],"stateMutability":"view"},{"type":"function","name":"getTokenBound","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"getTokenBounds","inputs":[],"outputs":[{"name":"","type":"address[]","internalType":"address[]"}],"stateMutability":"view"},{"type":"function","name":"grantRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"hasRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"isTokenBound","inputs":[{"name":"token","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"isTokenSelfBindingApproved","inputs":[{"name":"token","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"maxRules","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"messageForTransferRestriction","inputs":[{"name":"restrictionCode","type":"uint8","internalType":"uint8"}],"outputs":[{"name":"","type":"string","internalType":"string"}],"stateMutability":"view"},{"type":"function","name":"removeRule","inputs":[{"name":"rule_","type":"address","internalType":"contract IRule"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"renounceRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"callerConfirmation","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"revokeRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"rule","inputs":[{"name":"ruleId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"rules","inputs":[],"outputs":[{"name":"","type":"address[]","internalType":"address[]"}],"stateMutability":"view"},{"type":"function","name":"rulesCount","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"setMaxRules","inputs":[{"name":"maxRules_","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setRules","inputs":[{"name":"rules_","type":"address[]","internalType":"contract IRule[]"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setTokenSelfBindingApproval","inputs":[{"name":"token","type":"address","internalType":"address"},{"name":"approved","type":"bool","internalType":"bool"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setTokenSelfBindingApprovalBatch","inputs":[{"name":"tokens","type":"address[]","internalType":"address[]"},{"name":"approved","type":"bool","internalType":"bool"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"supportsInterface","inputs":[{"name":"interfaceId","type":"bytes4","internalType":"bytes4"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"transferred","inputs":[{"name":"spender","type":"address","internalType":"address"},{"name":"from","type":"address","internalType":"address"},{"name":"to","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"transferred","inputs":[{"name":"from","type":"address","internalType":"address"},{"name":"to","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"unbindToken","inputs":[{"name":"token","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"unbindTokens","inputs":[{"name":"tokens","type":"address[]","internalType":"address[]"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"version","inputs":[],"outputs":[{"name":"version_","type":"string","internalType":"string"}],"stateMutability":"view"},{"type":"event","name":"AddRule","inputs":[{"name":"rule","type":"address","indexed":true,"internalType":"contract IRule"}],"anonymous":false},{"type":"event","name":"ClearRules","inputs":[],"anonymous":false},{"type":"event","name":"RemoveRule","inputs":[{"name":"rule","type":"address","indexed":true,"internalType":"contract IRule"}],"anonymous":false},{"type":"event","name":"RoleAdminChanged","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"previousAdminRole","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"newAdminRole","type":"bytes32","indexed":true,"internalType":"bytes32"}],"anonymous":false},{"type":"event","name":"RoleGranted","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"account","type":"address","indexed":true,"internalType":"address"},{"name":"sender","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"RoleRevoked","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"account","type":"address","indexed":true,"internalType":"address"},{"name":"sender","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"SetMaxRules","inputs":[{"name":"maxRules","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"TokenBound","inputs":[{"name":"token","type":"address","indexed":false,"internalType":"address"}],"anonymous":false},{"type":"event","name":"TokenSelfBindingApprovalBatchSet","inputs":[{"name":"tokens","type":"address[]","indexed":false,"internalType":"address[]"},{"name":"approved","type":"bool","indexed":false,"internalType":"bool"}],"anonymous":false},{"type":"event","name":"TokenSelfBindingApprovalSet","inputs":[{"name":"token","type":"address","indexed":true,"internalType":"address"},{"name":"approved","type":"bool","indexed":false,"internalType":"bool"}],"anonymous":false},{"type":"event","name":"TokenUnbound","inputs":[{"name":"token","type":"address","indexed":false,"internalType":"address"}],"anonymous":false},{"type":"error","name":"AccessControlBadConfirmation","inputs":[]},{"type":"error","name":"AccessControlUnauthorizedAccount","inputs":[{"name":"account","type":"address","internalType":"address"},{"name":"neededRole","type":"bytes32","internalType":"bytes32"}]},{"type":"error","name":"RuleEngine_AdminWithAddressZeroNotAllowed","inputs":[]},{"type":"error","name":"RuleEngine_RuleInvalidInterface","inputs":[]},{"type":"error","name":"RuleEngine_RulesManagementModule_ArrayIsEmpty","inputs":[]},{"type":"error","name":"RuleEngine_RulesManagementModule_MaxRulesExceeded","inputs":[{"name":"maxRules","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"RuleEngine_RulesManagementModule_MaxRulesZeroNotAllowed","inputs":[]},{"type":"error","name":"RuleEngine_RulesManagementModule_RuleAccountCannotReceivePrivileges","inputs":[]},{"type":"error","name":"RuleEngine_RulesManagementModule_RuleAddressZeroNotAllowed","inputs":[]},{"type":"error","name":"RuleEngine_RulesManagementModule_RuleAlreadyExists","inputs":[]},{"type":"error","name":"RuleEngine_RulesManagementModule_RuleDoNotMatch","inputs":[]},{"type":"error","name":"TokenBinding_InvalidTokenAddress","inputs":[]},{"type":"error","name":"TokenBinding_TokenAlreadyBound","inputs":[]},{"type":"error","name":"TokenBinding_TokenNotBound","inputs":[]},{"type":"error","name":"TokenBinding_UnauthorizedCaller","inputs":[]}],"bytecode":{"object":"0x6080604052600a600255348015610014575f5ffd5b506040516122ef3803806122ef83398101604081905261003391610374565b6001600160a01b03821661005a57604051630872273360e21b815260040160405180910390fd5b6001600160a01b03811615610072576100728161008e565b61007c5f83610126565b50610087600a61015c565b50506103a5565b6001600160a01b0381166100b55760405163135217db60e21b815260040160405180910390fd5b6100be816101b1565b6100c96003826101dc565b6100e6576040516371b3c56560e11b815260040160405180910390fd5b6040516001600160a01b03821681527f2de35142b19ed5a07796cf30791959c592018f70b1d2d7c460eef8ffe713692b906020015b60405180910390a150565b5f8061013284846101f0565b90508015610153575f84815260076020526040902061015190846101dc565b505b90505b92915050565b805f0361017c57604051631e69e71760e21b815260040160405180910390fd5b60028190556040518181527f2292ad4720fff63e2bd104c6b1c0d72c2c729a6001c8ab4bb947cbcc511098639060200161011b565b6101bb5f82610281565b156101d9576040516302925f7360e11b815260040160405180910390fd5b50565b5f610153836001600160a01b0384166102a2565b5f6101fb83836102e7565b61027a575f8381526006602090815260408083206001600160a01b03861684529091529020805460ff191660011790556102323390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4506001610156565b505f610156565b6001600160a01b0381165f9081526001830160205260408120541515610153565b5f81815260018301602052604081205461027a57508154600181810184555f848152602080822090930184905584548482528286019093526040902091909155610156565b6001600160a01b0381165f9081527f54cdd369e4e8a8515e52ca72ec816c2101831ad1f18bf44102ed171459c9b4f8602052604081205460ff161561032e57506001610156565b505f8281526006602090815260408083206001600160a01b038516845290915290205460ff16610156565b80516001600160a01b038116811461036f575f5ffd5b919050565b5f5f60408385031215610385575f5ffd5b61038e83610359565b915061039c60208401610359565b90509250929050565b611f3d806103b25f395ff3fe608060405234801561000f575f5ffd5b5060043610610260575f3560e01c80639010d07c1161014b578063ca15c873116100bf578063db75d01711610084578063db75d0171461058e578063df21950f146105b9578063e3c4602c146105cc578063e46638e6146105df578063e54621d2146105f2578063f76bf550146105fa575f5ffd5b8063ca15c8731461051d578063d32c7bb514610530578063d4ce141514610555578063d547741f14610568578063db18af6c1461057b575f5ffd5b8063a3246ad311610110578063a3246ad3146104c1578063b043572e146104d4578063b27aef3a146104dc578063bb4b6121146104ef578063bc13eacc14610502578063c7c24b181461050a575f5ffd5b80639010d07c1461045a57806391d148541461046d578063993e8b95146104805780639b11c11514610493578063a217fddf146104ba575f5ffd5b806340db3b50116101e25780636a3edf28116101a75780636a3edf28146103e65780636ae728c6146104065780637157797f1461040e5780637f4ab1dd146104215780638baf29b4146104345780638d2ea77214610447575f5ffd5b806340db3b501461036a57806352f6747a1461037d57806354e4b9451461039257806354fd4d50146103a55780635f8dead3146103d3575f5ffd5b80633284a9a5116102285780633284a9a51461030b57806336568abe1461031e5780633a56d6d5146103315780633e5af4ca146103445780633ff5aa0214610357575f5ffd5b806301ffc9a71461026457806303c26bcd1461028c5780631455d0e7146102c1578063248a9ca3146102d65780632f2ff15d146102f8575b5f5ffd5b610277610272366004611a3e565b610602565b60405190151581526020015b60405180910390f35b6102b37fe5c50d0927e06141e032cb9a67e1d7092dc85c0b0825191f7e1cede60002856881565b604051908152602001610283565b6102d46102cf366004611aad565b610621565b005b6102b36102e4366004611aec565b5f9081526006602052604090206001015490565b6102d4610306366004611b17565b61066f565b6102d4610319366004611b52565b6106a5565b6102d461032c366004611b17565b6106de565b6102d461033f366004611aec565b610711565b6102d4610352366004611b7e565b610725565b6102d4610365366004611bcc565b61073f565b6102d4610378366004611bcc565b610751565b610385610763565b6040516102839190611be7565b6102776103a0366004611bcc565b610773565b604080518082019091526009815268332e302e302d72633760b81b60208201525b6040516102839190611c32565b6102d46103e1366004611c67565b61077e565b6103ee610791565b6040516001600160a01b039091168152602001610283565b6002546102b3565b61027761041c366004611b7e565b6107b3565b6103c661042f366004611c9f565b6107d0565b6102d4610442366004611cba565b6107db565b6102d4610455366004611c67565b6107ee565b6103ee610468366004611cf8565b610801565b61027761047b366004611b17565b61081f565b61027761048e366004611bcc565b610891565b6102b37fea5f4eb72290e50c32abd6c23e45de3d8300b3286e1cbc2e293114b92e034e5e81565b6102b35f81565b6103856104cf366004611aec565b61089d565b6102d46108b6565b6102d46104ea366004611aad565b6108c8565b6102d46104fd366004611d18565b61097b565b6102b3610a49565b6102d4610518366004611aad565b610a53565b6102b361052b366004611aec565b610a9c565b61054361053e366004611b7e565b610ab2565b60405160ff9091168152602001610283565b610543610563366004611cba565b610ac8565b6102d4610576366004611b17565b610ad4565b6103ee610589366004611aec565b610af8565b61027761059c366004611bcc565b6001600160a01b03165f9081526005602052604090205460ff1690565b6102d46105c7366004611bcc565b610b1a565b6102d46105da366004611bcc565b610b2b565b6102776105ed366004611cba565b610b6d565b610385610b86565b6102b3600a81565b5f61060c82610b92565b8061061b575061061b82610c33565b92915050565b610629610c57565b5f5b8181101561066a5761066283838381811061064857610648611d6b565b905060200201602081019061065d9190611bcc565b610c5f565b60010161062b565b505050565b6106795f82610c68565b15610697576040516302925f7360e11b815260040160405180910390fd5b6106a18282610c89565b5050565b6106ad610c57565b6001600160a01b0382166106d45760405163135217db60e21b815260040160405180910390fd5b6106a18282610cad565b6001600160a01b03811633146107075760405163334bd91960e11b815260040160405180910390fd5b61066a8282610d0b565b610719610d3e565b61072281610d48565b50565b61072d610da4565b61073984848484610dcc565b50505050565b61074881610e6e565b61072281610e77565b61075a81610e6e565b61072281610c5f565b606061076e5f610f08565b905090565b5f61061b8183610c68565b610786610da4565b6106a15f8383610f14565b5f5f61079d6003610fad565b11156107ae5761076e60035f610fb6565b505f90565b5f806107c186868686610ab2565b60ff161490505b949350505050565b606061061b82610fc1565b6107e3610da4565b61066a838383610f14565b6107f6610da4565b6106a1825f83610f14565b5f8281526007602052604081206108189083610fb6565b9392505050565b6001600160a01b0381165f9081527f54cdd369e4e8a8515e52ca72ec816c2101831ad1f18bf44102ed171459c9b4f8602052604081205460ff16156108665750600161061b565b505f8281526006602090815260408083206001600160a01b038516845290915290205460ff1661061b565b5f61061b600383610c68565b5f81815260076020526040902060609061061b90610f08565b6108be611136565b6108c6611160565b565b6108d0611136565b5f8190036108f1576040516359203cb960e01b815260040160405180910390fd5b6002548082111561092157604051630befc49d60e01b815260040161091891815260200190565b60405180910390fd5b505f61092c5f610fad565b111561093a5761093a611160565b5f5b8181101561066a5761097383838381811061095957610959611d6b565b905060200201602081019061096e9190611bcc565b611191565b60010161093c565b610983610c57565b5f5b82811015610a08575f8484838181106109a0576109a0611d6b565b90506020020160208101906109b59190611bcc565b90506001600160a01b0381166109de5760405163135217db60e21b815260040160405180910390fd5b6001600160a01b03165f908152600560205260409020805460ff1916831515179055600101610985565b507f430881f04f203566ee9b32d6444cf02e1b2a0f17ab6b4263a1ee2074d3d0f483838383604051610a3c93929190611d7f565b60405180910390a1505050565b5f61076e5f610fad565b610a5b610c57565b5f5b8181101561066a57610a94838383818110610a7a57610a7a611d6b565b9050602002016020810190610a8f9190611bcc565b610e77565b600101610a5d565b5f81815260076020526040812061061b90610fad565b5f610abf858585856111f7565b95945050505050565b5f6107c88484846112c4565b5f82815260066020526040902060010154610aee81611388565b6107398383610d0b565b5f610b025f610fad565b821015610b135761061b5f83610fb6565b505f919050565b610b22611136565b61072281611392565b610b33611136565b60025480610b405f610fad565b108190610b6357604051630befc49d60e01b815260040161091891815260200190565b506106a182611191565b5f80610b7a858585610ac8565b60ff1614949350505050565b606061076e6003610f08565b5f6001600160e01b031982166320c49ce760e01b1480610bc257506001600160e01b0319821663157094b960e31b145b80610bdd57506001600160e01b031982166378a8de7d60e01b145b80610bf857506001600160e01b03198216630c51264760e21b145b80610c1357506001600160e01b03198216633235d15f60e11b145b8061061b57506001600160e01b03198216637157797f60e01b1492915050565b5f6001600160e01b03198216635a05180f60e01b148061061b575061061b826113ef565b6108c6611423565b6107228161144d565b6001600160a01b0381165f9081526001830160205260408120541515610818565b5f82815260066020526040902060010154610ca381611388565b6107398383611495565b6001600160a01b0382165f81815260056020908152604091829020805460ff191685151590811790915591519182527f407b412a9b6db334d48445ec9bcad46fb50bc4b2e97f73e963e397101957a729910160405180910390a25050565b5f5f610d1784846114c0565b90508015610818575f848152600760205260409020610d369084611532565b509392505050565b5f61072281611388565b805f03610d6857604051631e69e71760e21b815260040160405180910390fd5b60028190556040518181527f2292ad4720fff63e2bd104c6b1c0d72c2c729a6001c8ab4bb947cbcc51109863906020015b60405180910390a150565b610daf600333610c68565b6108c657604051630599c0e960e01b815260040160405180910390fd5b5f610dd65f610fad565b90505f5b81811015610e6657610dec5f82610fb6565b604051631f2d7a6560e11b81526001600160a01b03888116600483015287811660248301528681166044830152606482018690529190911690633e5af4ca906084015f604051808303815f87803b158015610e45575f5ffd5b505af1158015610e57573d5f5f3e3d5ffd5b50505050806001019050610dda565b505050505050565b61072281611546565b6001600160a01b038116610e9e5760405163135217db60e21b815260040160405180910390fd5b610ea781611585565b610eb26003826115ad565b610ecf576040516371b3c56560e11b815260040160405180910390fd5b6040516001600160a01b03821681527f2de35142b19ed5a07796cf30791959c592018f70b1d2d7c460eef8ffe713692b90602001610d99565b60605f610818836115c1565b5f610f1e5f610fad565b90505f5b81811015610fa657610f345f82610fb6565b6040516322ebca6d60e21b81526001600160a01b0387811660048301528681166024830152604482018690529190911690638baf29b4906064015f604051808303815f87803b158015610f85575f5ffd5b505af1158015610f97573d5f5f3e3d5ffd5b50505050806001019050610f22565b5050505050565b5f61061b825490565b5f610818838361161a565b606060ff8216610ff457505060408051808201909152600d81526c2737a932b9ba3934b1ba34b7b760991b602082015290565b5f610ffe5f610fad565b90505f5b818110156110fa575f6110158183610fb6565b604051633e822efb60e11b815260ff871660048201529091506001600160a01b03821690637d045df690602401602060405180830381865afa15801561105d573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110819190611dd7565b156110f157604051637f4ab1dd60e01b815260ff861660048201526001600160a01b03821690637f4ab1dd906024015f60405180830381865afa1580156110ca573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610abf9190810190611e06565b50600101611002565b505060408051808201909152601881527f556e6b6e6f776e207265737472696374696f6e20636f64650000000000000000602082015292915050565b7fea5f4eb72290e50c32abd6c23e45de3d8300b3286e1cbc2e293114b92e034e5e61072281611388565b6040517fdbf61473843cd9be1c9791ce51ef66d0da6c9026d62ba80c1ca433b13fb729b2905f90a16108c65f611640565b61119a81611649565b6111a45f826115ad565b6111c15760405163cc790a4b60e01b815260040160405180910390fd5b6040516001600160a01b038216907f60305ce6c9104acd0969d358f926bf391174340660aaf5e6215261fd6847bf46905f90a250565b5f5f6112025f610fad565b90505f5b818110156112b8575f6112198183610fb6565b60405163d32c7bb560e01b81526001600160a01b038a811660048301528981166024830152888116604483015260648201889052919091169063d32c7bb590608401602060405180830381865afa158015611276573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061129a9190611eb9565b905060ff8116156112af5792506107c8915050565b50600101611206565b505f9695505050505050565b5f5f6112cf5f610fad565b90505f5b8181101561137d575f6112e68183610fb6565b60405163d4ce141560e01b81526001600160a01b038981166004830152888116602483015260448201889052919091169063d4ce141590606401602060405180830381865afa15801561133b573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061135f9190611eb9565b905060ff811615611374579250610818915050565b506001016112d3565b505f95945050505050565b61072281336116a1565b61139c5f82611532565b6113b957604051632cdc3a4160e21b815260040160405180910390fd5b6040516001600160a01b038216907f6d83315c9718799346b67584ec64301b1457e989c8e35a8e2982a7776c04bfc4905f90a250565b5f6001600160e01b03198216637965db0b60e01b148061061b57506301ffc9a760e01b6001600160e01b031983161461061b565b7fe5c50d0927e06141e032cb9a67e1d7092dc85c0b0825191f7e1cede60002856861072281611388565b611456816116da565b336001600160a01b0382161480159061148657506001600160a01b0381165f9081526005602052604090205460ff165b1561072257610722815f610cad565b5f5f6114a1848461173b565b90508015610818575f848152600760205260409020610d3690846115ad565b5f6114cb838361081f565b1561152b575f8381526006602090815260408083206001600160a01b0386168085529252808320805460ff1916905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a450600161061b565b505f61061b565b5f610818836001600160a01b0384166117c5565b336001600160a01b03821614801561157557506001600160a01b0381165f9081526005602052604090205460ff165b1561157d5750565b610722610c57565b61158f5f82610c68565b15610722576040516302925f7360e11b815260040160405180910390fd5b5f610818836001600160a01b0384166118a8565b6060815f0180548060200260200160405190810160405280929190818152602001828054801561160e57602002820191905f5260205f20905b8154815260200190600101908083116115fa575b50505050509050919050565b5f825f01828154811061162f5761162f611d6b565b905f5260205f200154905092915050565b610722816118ed565b61165281611946565b61165d600382610c68565b1561167b576040516302925f7360e11b815260040160405180910390fd5b6116848161196d565b61072257604051639952e34360e01b815260040160405180910390fd5b6116ab828261081f565b6106a15760405163e2517d3f60e01b81526001600160a01b038216600482015260248101839052604401610918565b6116e5600382611532565b61170257604051633477dd1760e01b815260040160405180910390fd5b6040516001600160a01b03821681527f28a4ca7134a3b3f9aff286e79ad3daadb4a06d1b43d037a3a98bdc074edd9b7a90602001610d99565b5f611746838361081f565b61152b575f8381526006602090815260408083206001600160a01b03861684529091529020805460ff1916600117905561177d3390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a450600161061b565b5f818152600183016020526040812054801561189f575f6117e7600183611ed4565b85549091505f906117fa90600190611ed4565b9050808214611859575f865f01828154811061181857611818611d6b565b905f5260205f200154905080875f01848154811061183857611838611d6b565b5f918252602080832090910192909255918252600188019052604090208390555b855486908061186a5761186a611ef3565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f90556001935050505061061b565b5f91505061061b565b5f81815260018301602052604081205461152b57508154600181810184555f84815260208082209093018490558454848252828601909352604090209190915561061b565b5f6118f6825490565b90505f5b8181101561193f57826001015f845f01838154811061191b5761191b611d6b565b905f5260205f20015481526020019081526020015f205f90558060010190506118fa565b50505f9055565b6001600160a01b0381166107225760405163f9d152fb60e01b815260040160405180910390fd5b5f611977826119aa565b61198257505f919050565b611993826358d34ba960e11b6119e9565b8061061b575061061b82632497d6cb60e01b6119e9565b5f6119bc826301ffc9a760e01b6119e9565b15610b13575f806119d5846001600160e01b0319611a0a565b915091508180156107c85750159392505050565b5f5f5f6119f68585611a0a565b91509150818015610abf5750949350505050565b6301ffc9a760e01b5f818152600483905290819060208260248188617530fa92505f511515601f3d11169150509250929050565b5f60208284031215611a4e575f5ffd5b81356001600160e01b031981168114610818575f5ffd5b5f5f83601f840112611a75575f5ffd5b50813567ffffffffffffffff811115611a8c575f5ffd5b6020830191508360208260051b8501011115611aa6575f5ffd5b9250929050565b5f5f60208385031215611abe575f5ffd5b823567ffffffffffffffff811115611ad4575f5ffd5b611ae085828601611a65565b90969095509350505050565b5f60208284031215611afc575f5ffd5b5035919050565b6001600160a01b0381168114610722575f5ffd5b5f5f60408385031215611b28575f5ffd5b823591506020830135611b3a81611b03565b809150509250929050565b8015158114610722575f5ffd5b5f5f60408385031215611b63575f5ffd5b8235611b6e81611b03565b91506020830135611b3a81611b45565b5f5f5f5f60808587031215611b91575f5ffd5b8435611b9c81611b03565b93506020850135611bac81611b03565b92506040850135611bbc81611b03565b9396929550929360600135925050565b5f60208284031215611bdc575f5ffd5b813561081881611b03565b602080825282518282018190525f918401906040840190835b81811015611c275783516001600160a01b0316835260209384019390920191600101611c00565b509095945050505050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b5f5f60408385031215611c78575f5ffd5b8235611c8381611b03565b946020939093013593505050565b60ff81168114610722575f5ffd5b5f60208284031215611caf575f5ffd5b813561081881611c91565b5f5f5f60608486031215611ccc575f5ffd5b8335611cd781611b03565b92506020840135611ce781611b03565b929592945050506040919091013590565b5f5f60408385031215611d09575f5ffd5b50508035926020909101359150565b5f5f5f60408486031215611d2a575f5ffd5b833567ffffffffffffffff811115611d40575f5ffd5b611d4c86828701611a65565b9094509250506020840135611d6081611b45565b809150509250925092565b634e487b7160e01b5f52603260045260245ffd5b604080825281018390525f8460608301825b86811015611dc1578235611da481611b03565b6001600160a01b0316825260209283019290910190600101611d91565b5080925050508215156020830152949350505050565b5f60208284031215611de7575f5ffd5b815161081881611b45565b634e487b7160e01b5f52604160045260245ffd5b5f60208284031215611e16575f5ffd5b815167ffffffffffffffff811115611e2c575f5ffd5b8201601f81018413611e3c575f5ffd5b805167ffffffffffffffff811115611e5657611e56611df2565b604051601f8201601f19908116603f0116810167ffffffffffffffff81118282101715611e8557611e85611df2565b604052818152828201602001861015611e9c575f5ffd5b8160208401602083015e5f91810160200191909152949350505050565b5f60208284031215611ec9575f5ffd5b815161081881611c91565b8181038181111561061b57634e487b7160e01b5f52601160045260245ffd5b634e487b7160e01b5f52603160045260245ffdfea2646970667358221220a83715605231661526683aa5552db8854a654fe0db957bd2d428fa00754bb2f064736f6c63430008250033","sourceMap":"1155:3834:30:-:0;;;537:2:80;1188:46:69;;1663:410:30;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;1731:19:30;;1723:73;;;;-1:-1:-1;;;1723:73:30;;;;;;;;;;;;-1:-1:-1;;;;;1810:27:30;;;1806:83;;1853:25;1864:13;1853:10;:25::i;:::-;1898:37;2232:4:8;1929:5:30;1898:10;:37::i;:::-;-1:-1:-1;2035:31:30;537:2:80;2035:12:30;:31::i;:::-;1663:410;;1155:3834;;4440:400:71;-1:-1:-1;;;;;4510:19:71;;4502:64;;;;-1:-1:-1;;;4502:64:71;;;;;;;;;;;;4576:26;4596:5;4576:19;:26::i;:::-;4743:23;:12;4760:5;4743:16;:23::i;:::-;4735:66;;;;-1:-1:-1;;;4735:66:71;;;;;;;;;;;;4816:17;;-1:-1:-1;;;;;658:32:83;;640:51;;4816:17:71;;628:2:83;613:18;4816:17:71;;;;;;;;4440:400;:::o;2778:257:12:-;2864:4;;2895:31;2912:4;2918:7;2895:16;:31::i;:::-;2880:46;;2940:7;2936:69;;;2963:18;;;;:12;:18;;;;;:31;;2986:7;2963:22;:31::i;:::-;;2936:69;3021:7;-1:-1:-1;2778:257:12;;;;;:::o;6050:225:69:-;6126:9;6139:1;6126:14;6118:82;;;;-1:-1:-1;;;6118:82:69;;;;;;;;;;;;6210:9;:21;;;6246:22;;848:25:83;;;6246:22:69;;836:2:83;821:18;6246:22:69;702:177:83;9793:195:28;9887:22;:6;9903:5;9887:15;:22::i;:::-;9886:23;9878:103;;;;-1:-1:-1;;;9878:103:28;;;;;;;;;;;;9793:195;:::o;16462:150:27:-;16532:4;16555:50;16560:3;-1:-1:-1;;;;;16580:23:27;;16555:4;:50::i;6162:316:8:-;6239:4;6260:22;6268:4;6274:7;6260;:22::i;:::-;6255:217;;6298:12;;;;:6;:12;;;;;;;;-1:-1:-1;;;;;6298:29:8;;;;;;;;;:36;;-1:-1:-1;;6298:36:8;6330:4;6298:36;;;6380:12;735:10:18;;656:96;6380:12:8;-1:-1:-1;;;;;6353:40:8;6371:7;-1:-1:-1;;;;;6353:40:8;6365:4;6353:40;;;;;;;;;;-1:-1:-1;6414:4:8;6407:11;;6255:217;-1:-1:-1;6456:5:8;6449:12;;17414:165:27;-1:-1:-1;;;;;17547:23:27;;17494:4;5238:21;;;:14;;;:21;;;;;;:26;;17517:55;5142:129;2538:406;2601:4;5238:21;;;:14;;;:21;;;;;;2617:321;;-1:-1:-1;2659:23:27;;;;;;;;:11;:23;;;;;;;;;;;;;2841:18;;2817:21;;;:14;;;:21;;;;;;:42;;;;2873:11;;3305:349:30;-1:-1:-1;;;;;2920:29:8;;3462:4:30;2920:29:8;;;:12;;:29;:12;:29;;;;;3482:166:30;;;-1:-1:-1;3559:4:30;3552:11;;3482:166;-1:-1:-1;2897:4:8;2920:12;;;:6;:12;;;;;;;;-1:-1:-1;;;;;2920:29:8;;;;;;;;;;;;3594:43:30;;14:177:83;93:13;;-1:-1:-1;;;;;135:31:83;;125:42;;115:70;;181:1;178;171:12;115:70;14:177;;;:::o;196:293::-;275:6;283;336:2;324:9;315:7;311:23;307:32;304:52;;;352:1;349;342:12;304:52;375:40;405:9;375:40;:::i;:::-;365:50;;434:49;479:2;468:9;464:18;434:49;:::i;:::-;424:59;;196:293;;;;;:::o;702:177::-;1155:3834:30;;;;;;","linkReferences":{}},"deployedBytecode":{"object":"0x608060405234801561000f575f5ffd5b5060043610610260575f3560e01c80639010d07c1161014b578063ca15c873116100bf578063db75d01711610084578063db75d0171461058e578063df21950f146105b9578063e3c4602c146105cc578063e46638e6146105df578063e54621d2146105f2578063f76bf550146105fa575f5ffd5b8063ca15c8731461051d578063d32c7bb514610530578063d4ce141514610555578063d547741f14610568578063db18af6c1461057b575f5ffd5b8063a3246ad311610110578063a3246ad3146104c1578063b043572e146104d4578063b27aef3a146104dc578063bb4b6121146104ef578063bc13eacc14610502578063c7c24b181461050a575f5ffd5b80639010d07c1461045a57806391d148541461046d578063993e8b95146104805780639b11c11514610493578063a217fddf146104ba575f5ffd5b806340db3b50116101e25780636a3edf28116101a75780636a3edf28146103e65780636ae728c6146104065780637157797f1461040e5780637f4ab1dd146104215780638baf29b4146104345780638d2ea77214610447575f5ffd5b806340db3b501461036a57806352f6747a1461037d57806354e4b9451461039257806354fd4d50146103a55780635f8dead3146103d3575f5ffd5b80633284a9a5116102285780633284a9a51461030b57806336568abe1461031e5780633a56d6d5146103315780633e5af4ca146103445780633ff5aa0214610357575f5ffd5b806301ffc9a71461026457806303c26bcd1461028c5780631455d0e7146102c1578063248a9ca3146102d65780632f2ff15d146102f8575b5f5ffd5b610277610272366004611a3e565b610602565b60405190151581526020015b60405180910390f35b6102b37fe5c50d0927e06141e032cb9a67e1d7092dc85c0b0825191f7e1cede60002856881565b604051908152602001610283565b6102d46102cf366004611aad565b610621565b005b6102b36102e4366004611aec565b5f9081526006602052604090206001015490565b6102d4610306366004611b17565b61066f565b6102d4610319366004611b52565b6106a5565b6102d461032c366004611b17565b6106de565b6102d461033f366004611aec565b610711565b6102d4610352366004611b7e565b610725565b6102d4610365366004611bcc565b61073f565b6102d4610378366004611bcc565b610751565b610385610763565b6040516102839190611be7565b6102776103a0366004611bcc565b610773565b604080518082019091526009815268332e302e302d72633760b81b60208201525b6040516102839190611c32565b6102d46103e1366004611c67565b61077e565b6103ee610791565b6040516001600160a01b039091168152602001610283565b6002546102b3565b61027761041c366004611b7e565b6107b3565b6103c661042f366004611c9f565b6107d0565b6102d4610442366004611cba565b6107db565b6102d4610455366004611c67565b6107ee565b6103ee610468366004611cf8565b610801565b61027761047b366004611b17565b61081f565b61027761048e366004611bcc565b610891565b6102b37fea5f4eb72290e50c32abd6c23e45de3d8300b3286e1cbc2e293114b92e034e5e81565b6102b35f81565b6103856104cf366004611aec565b61089d565b6102d46108b6565b6102d46104ea366004611aad565b6108c8565b6102d46104fd366004611d18565b61097b565b6102b3610a49565b6102d4610518366004611aad565b610a53565b6102b361052b366004611aec565b610a9c565b61054361053e366004611b7e565b610ab2565b60405160ff9091168152602001610283565b610543610563366004611cba565b610ac8565b6102d4610576366004611b17565b610ad4565b6103ee610589366004611aec565b610af8565b61027761059c366004611bcc565b6001600160a01b03165f9081526005602052604090205460ff1690565b6102d46105c7366004611bcc565b610b1a565b6102d46105da366004611bcc565b610b2b565b6102776105ed366004611cba565b610b6d565b610385610b86565b6102b3600a81565b5f61060c82610b92565b8061061b575061061b82610c33565b92915050565b610629610c57565b5f5b8181101561066a5761066283838381811061064857610648611d6b565b905060200201602081019061065d9190611bcc565b610c5f565b60010161062b565b505050565b6106795f82610c68565b15610697576040516302925f7360e11b815260040160405180910390fd5b6106a18282610c89565b5050565b6106ad610c57565b6001600160a01b0382166106d45760405163135217db60e21b815260040160405180910390fd5b6106a18282610cad565b6001600160a01b03811633146107075760405163334bd91960e11b815260040160405180910390fd5b61066a8282610d0b565b610719610d3e565b61072281610d48565b50565b61072d610da4565b61073984848484610dcc565b50505050565b61074881610e6e565b61072281610e77565b61075a81610e6e565b61072281610c5f565b606061076e5f610f08565b905090565b5f61061b8183610c68565b610786610da4565b6106a15f8383610f14565b5f5f61079d6003610fad565b11156107ae5761076e60035f610fb6565b505f90565b5f806107c186868686610ab2565b60ff161490505b949350505050565b606061061b82610fc1565b6107e3610da4565b61066a838383610f14565b6107f6610da4565b6106a1825f83610f14565b5f8281526007602052604081206108189083610fb6565b9392505050565b6001600160a01b0381165f9081527f54cdd369e4e8a8515e52ca72ec816c2101831ad1f18bf44102ed171459c9b4f8602052604081205460ff16156108665750600161061b565b505f8281526006602090815260408083206001600160a01b038516845290915290205460ff1661061b565b5f61061b600383610c68565b5f81815260076020526040902060609061061b90610f08565b6108be611136565b6108c6611160565b565b6108d0611136565b5f8190036108f1576040516359203cb960e01b815260040160405180910390fd5b6002548082111561092157604051630befc49d60e01b815260040161091891815260200190565b60405180910390fd5b505f61092c5f610fad565b111561093a5761093a611160565b5f5b8181101561066a5761097383838381811061095957610959611d6b565b905060200201602081019061096e9190611bcc565b611191565b60010161093c565b610983610c57565b5f5b82811015610a08575f8484838181106109a0576109a0611d6b565b90506020020160208101906109b59190611bcc565b90506001600160a01b0381166109de5760405163135217db60e21b815260040160405180910390fd5b6001600160a01b03165f908152600560205260409020805460ff1916831515179055600101610985565b507f430881f04f203566ee9b32d6444cf02e1b2a0f17ab6b4263a1ee2074d3d0f483838383604051610a3c93929190611d7f565b60405180910390a1505050565b5f61076e5f610fad565b610a5b610c57565b5f5b8181101561066a57610a94838383818110610a7a57610a7a611d6b565b9050602002016020810190610a8f9190611bcc565b610e77565b600101610a5d565b5f81815260076020526040812061061b90610fad565b5f610abf858585856111f7565b95945050505050565b5f6107c88484846112c4565b5f82815260066020526040902060010154610aee81611388565b6107398383610d0b565b5f610b025f610fad565b821015610b135761061b5f83610fb6565b505f919050565b610b22611136565b61072281611392565b610b33611136565b60025480610b405f610fad565b108190610b6357604051630befc49d60e01b815260040161091891815260200190565b506106a182611191565b5f80610b7a858585610ac8565b60ff1614949350505050565b606061076e6003610f08565b5f6001600160e01b031982166320c49ce760e01b1480610bc257506001600160e01b0319821663157094b960e31b145b80610bdd57506001600160e01b031982166378a8de7d60e01b145b80610bf857506001600160e01b03198216630c51264760e21b145b80610c1357506001600160e01b03198216633235d15f60e11b145b8061061b57506001600160e01b03198216637157797f60e01b1492915050565b5f6001600160e01b03198216635a05180f60e01b148061061b575061061b826113ef565b6108c6611423565b6107228161144d565b6001600160a01b0381165f9081526001830160205260408120541515610818565b5f82815260066020526040902060010154610ca381611388565b6107398383611495565b6001600160a01b0382165f81815260056020908152604091829020805460ff191685151590811790915591519182527f407b412a9b6db334d48445ec9bcad46fb50bc4b2e97f73e963e397101957a729910160405180910390a25050565b5f5f610d1784846114c0565b90508015610818575f848152600760205260409020610d369084611532565b509392505050565b5f61072281611388565b805f03610d6857604051631e69e71760e21b815260040160405180910390fd5b60028190556040518181527f2292ad4720fff63e2bd104c6b1c0d72c2c729a6001c8ab4bb947cbcc51109863906020015b60405180910390a150565b610daf600333610c68565b6108c657604051630599c0e960e01b815260040160405180910390fd5b5f610dd65f610fad565b90505f5b81811015610e6657610dec5f82610fb6565b604051631f2d7a6560e11b81526001600160a01b03888116600483015287811660248301528681166044830152606482018690529190911690633e5af4ca906084015f604051808303815f87803b158015610e45575f5ffd5b505af1158015610e57573d5f5f3e3d5ffd5b50505050806001019050610dda565b505050505050565b61072281611546565b6001600160a01b038116610e9e5760405163135217db60e21b815260040160405180910390fd5b610ea781611585565b610eb26003826115ad565b610ecf576040516371b3c56560e11b815260040160405180910390fd5b6040516001600160a01b03821681527f2de35142b19ed5a07796cf30791959c592018f70b1d2d7c460eef8ffe713692b90602001610d99565b60605f610818836115c1565b5f610f1e5f610fad565b90505f5b81811015610fa657610f345f82610fb6565b6040516322ebca6d60e21b81526001600160a01b0387811660048301528681166024830152604482018690529190911690638baf29b4906064015f604051808303815f87803b158015610f85575f5ffd5b505af1158015610f97573d5f5f3e3d5ffd5b50505050806001019050610f22565b5050505050565b5f61061b825490565b5f610818838361161a565b606060ff8216610ff457505060408051808201909152600d81526c2737a932b9ba3934b1ba34b7b760991b602082015290565b5f610ffe5f610fad565b90505f5b818110156110fa575f6110158183610fb6565b604051633e822efb60e11b815260ff871660048201529091506001600160a01b03821690637d045df690602401602060405180830381865afa15801561105d573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110819190611dd7565b156110f157604051637f4ab1dd60e01b815260ff861660048201526001600160a01b03821690637f4ab1dd906024015f60405180830381865afa1580156110ca573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610abf9190810190611e06565b50600101611002565b505060408051808201909152601881527f556e6b6e6f776e207265737472696374696f6e20636f64650000000000000000602082015292915050565b7fea5f4eb72290e50c32abd6c23e45de3d8300b3286e1cbc2e293114b92e034e5e61072281611388565b6040517fdbf61473843cd9be1c9791ce51ef66d0da6c9026d62ba80c1ca433b13fb729b2905f90a16108c65f611640565b61119a81611649565b6111a45f826115ad565b6111c15760405163cc790a4b60e01b815260040160405180910390fd5b6040516001600160a01b038216907f60305ce6c9104acd0969d358f926bf391174340660aaf5e6215261fd6847bf46905f90a250565b5f5f6112025f610fad565b90505f5b818110156112b8575f6112198183610fb6565b60405163d32c7bb560e01b81526001600160a01b038a811660048301528981166024830152888116604483015260648201889052919091169063d32c7bb590608401602060405180830381865afa158015611276573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061129a9190611eb9565b905060ff8116156112af5792506107c8915050565b50600101611206565b505f9695505050505050565b5f5f6112cf5f610fad565b90505f5b8181101561137d575f6112e68183610fb6565b60405163d4ce141560e01b81526001600160a01b038981166004830152888116602483015260448201889052919091169063d4ce141590606401602060405180830381865afa15801561133b573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061135f9190611eb9565b905060ff811615611374579250610818915050565b506001016112d3565b505f95945050505050565b61072281336116a1565b61139c5f82611532565b6113b957604051632cdc3a4160e21b815260040160405180910390fd5b6040516001600160a01b038216907f6d83315c9718799346b67584ec64301b1457e989c8e35a8e2982a7776c04bfc4905f90a250565b5f6001600160e01b03198216637965db0b60e01b148061061b57506301ffc9a760e01b6001600160e01b031983161461061b565b7fe5c50d0927e06141e032cb9a67e1d7092dc85c0b0825191f7e1cede60002856861072281611388565b611456816116da565b336001600160a01b0382161480159061148657506001600160a01b0381165f9081526005602052604090205460ff165b1561072257610722815f610cad565b5f5f6114a1848461173b565b90508015610818575f848152600760205260409020610d3690846115ad565b5f6114cb838361081f565b1561152b575f8381526006602090815260408083206001600160a01b0386168085529252808320805460ff1916905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a450600161061b565b505f61061b565b5f610818836001600160a01b0384166117c5565b336001600160a01b03821614801561157557506001600160a01b0381165f9081526005602052604090205460ff165b1561157d5750565b610722610c57565b61158f5f82610c68565b15610722576040516302925f7360e11b815260040160405180910390fd5b5f610818836001600160a01b0384166118a8565b6060815f0180548060200260200160405190810160405280929190818152602001828054801561160e57602002820191905f5260205f20905b8154815260200190600101908083116115fa575b50505050509050919050565b5f825f01828154811061162f5761162f611d6b565b905f5260205f200154905092915050565b610722816118ed565b61165281611946565b61165d600382610c68565b1561167b576040516302925f7360e11b815260040160405180910390fd5b6116848161196d565b61072257604051639952e34360e01b815260040160405180910390fd5b6116ab828261081f565b6106a15760405163e2517d3f60e01b81526001600160a01b038216600482015260248101839052604401610918565b6116e5600382611532565b61170257604051633477dd1760e01b815260040160405180910390fd5b6040516001600160a01b03821681527f28a4ca7134a3b3f9aff286e79ad3daadb4a06d1b43d037a3a98bdc074edd9b7a90602001610d99565b5f611746838361081f565b61152b575f8381526006602090815260408083206001600160a01b03861684529091529020805460ff1916600117905561177d3390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a450600161061b565b5f818152600183016020526040812054801561189f575f6117e7600183611ed4565b85549091505f906117fa90600190611ed4565b9050808214611859575f865f01828154811061181857611818611d6b565b905f5260205f200154905080875f01848154811061183857611838611d6b565b5f918252602080832090910192909255918252600188019052604090208390555b855486908061186a5761186a611ef3565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f90556001935050505061061b565b5f91505061061b565b5f81815260018301602052604081205461152b57508154600181810184555f84815260208082209093018490558454848252828601909352604090209190915561061b565b5f6118f6825490565b90505f5b8181101561193f57826001015f845f01838154811061191b5761191b611d6b565b905f5260205f20015481526020019081526020015f205f90558060010190506118fa565b50505f9055565b6001600160a01b0381166107225760405163f9d152fb60e01b815260040160405180910390fd5b5f611977826119aa565b61198257505f919050565b611993826358d34ba960e11b6119e9565b8061061b575061061b82632497d6cb60e01b6119e9565b5f6119bc826301ffc9a760e01b6119e9565b15610b13575f806119d5846001600160e01b0319611a0a565b915091508180156107c85750159392505050565b5f5f5f6119f68585611a0a565b91509150818015610abf5750949350505050565b6301ffc9a760e01b5f818152600483905290819060208260248188617530fa92505f511515601f3d11169150509250929050565b5f60208284031215611a4e575f5ffd5b81356001600160e01b031981168114610818575f5ffd5b5f5f83601f840112611a75575f5ffd5b50813567ffffffffffffffff811115611a8c575f5ffd5b6020830191508360208260051b8501011115611aa6575f5ffd5b9250929050565b5f5f60208385031215611abe575f5ffd5b823567ffffffffffffffff811115611ad4575f5ffd5b611ae085828601611a65565b90969095509350505050565b5f60208284031215611afc575f5ffd5b5035919050565b6001600160a01b0381168114610722575f5ffd5b5f5f60408385031215611b28575f5ffd5b823591506020830135611b3a81611b03565b809150509250929050565b8015158114610722575f5ffd5b5f5f60408385031215611b63575f5ffd5b8235611b6e81611b03565b91506020830135611b3a81611b45565b5f5f5f5f60808587031215611b91575f5ffd5b8435611b9c81611b03565b93506020850135611bac81611b03565b92506040850135611bbc81611b03565b9396929550929360600135925050565b5f60208284031215611bdc575f5ffd5b813561081881611b03565b602080825282518282018190525f918401906040840190835b81811015611c275783516001600160a01b0316835260209384019390920191600101611c00565b509095945050505050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b5f5f60408385031215611c78575f5ffd5b8235611c8381611b03565b946020939093013593505050565b60ff81168114610722575f5ffd5b5f60208284031215611caf575f5ffd5b813561081881611c91565b5f5f5f60608486031215611ccc575f5ffd5b8335611cd781611b03565b92506020840135611ce781611b03565b929592945050506040919091013590565b5f5f60408385031215611d09575f5ffd5b50508035926020909101359150565b5f5f5f60408486031215611d2a575f5ffd5b833567ffffffffffffffff811115611d40575f5ffd5b611d4c86828701611a65565b9094509250506020840135611d6081611b45565b809150509250925092565b634e487b7160e01b5f52603260045260245ffd5b604080825281018390525f8460608301825b86811015611dc1578235611da481611b03565b6001600160a01b0316825260209283019290910190600101611d91565b5080925050508215156020830152949350505050565b5f60208284031215611de7575f5ffd5b815161081881611b45565b634e487b7160e01b5f52604160045260245ffd5b5f60208284031215611e16575f5ffd5b815167ffffffffffffffff811115611e2c575f5ffd5b8201601f81018413611e3c575f5ffd5b805167ffffffffffffffff811115611e5657611e56611df2565b604051601f8201601f19908116603f0116810167ffffffffffffffff81118282101715611e8557611e85611df2565b604052818152828201602001861015611e9c575f5ffd5b8160208401602083015e5f91810160200191909152949350505050565b5f60208284031215611ec9575f5ffd5b815161081881611c91565b8181038181111561061b57634e487b7160e01b5f52601160045260245ffd5b634e487b7160e01b5f52603160045260245ffdfea2646970667358221220a83715605231661526683aa5552db8854a654fe0db957bd2d428fa00754bb2f064736f6c63430008250033","sourceMap":"1155:3834:30:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3893:296;;;;;;:::i;:::-;;:::i;:::-;;;470:14:83;;463:22;445:41;;433:2;418:18;3893:296:30;;;;;;;;369:86:75;;419:36;369:86;;;;;643:25:83;;;631:2;616:18;369:86:75;497:177:83;1872:205:70;;;;;;:::i;:::-;;:::i;:::-;;3776:120:8;;;;;;:::i;:::-;3841:7;3867:12;;;:6;:12;;;;;:22;;;;3776:120;2709:275:30;;;;;;:::i;:::-;;:::i;2125:251:70:-;;;;;;:::i;:::-;;:::i;5311:245:8:-;;;;;;:::i;:::-;;:::i;3487:150:69:-;;;;;;:::i;:::-;;:::i;2583:330:28:-;;;;;;:::i;:::-;;:::i;2979:137:71:-;;;;;;:::i;:::-;;:::i;3404:141::-;;;;;;:::i;:::-;;:::i;5029:136:69:-;;;:::i;:::-;;;;;;;:::i;4333:158::-;;;;;;:::i;:::-;;:::i;737:129:72:-;852:7;;;;;;;;;;;;-1:-1:-1;;;852:7:72;;;;737:129;;;;;;;:::i;3239:155:28:-;;;;;;:::i;:::-;;:::i;2211:383:68:-;;;:::i;:::-;;;-1:-1:-1;;;;;5748:32:83;;;5730:51;;5718:2;5703:18;2211:383:68;5584:203:83;3949:124:69;4057:9;;3949:124;;5266:311:28;;;;;;:::i;:::-;;:::i;4621:240::-;;;;;;:::i;:::-;;:::i;2982:212::-;;;;;;:::i;:::-;;:::i;3439:161::-;;;;;;:::i;:::-;;:::i;1555:143:12:-;;;;;;:::i;:::-;;:::i;3305:349:30:-;;;;;;:::i;:::-;;:::i;3636:133:71:-;;;;;;:::i;:::-;;:::i;357:82:81:-;;405:34;357:82;;2187:49:8;;2232:4;2187:49;;2540:136:12;;;;;;:::i;:::-;;:::i;2691:117:69:-;;;:::i;2150:477::-;;;;;;:::i;:::-;;:::i;2424:478:70:-;;;;;;:::i;:::-;;:::i;4137:132:69:-;;;:::i;1623:201:70:-;;;;;;:::i;:::-;;:::i;1866:131:12:-;;;;;;:::i;:::-;;:::i;4289:282:28:-;;;;;;:::i;:::-;;:::i;:::-;;;8405:4:83;8393:17;;;8375:36;;8363:2;8348:18;4289:282:28;8233:184:83;3991:242:28;;;;;;:::i;:::-;;:::i;4608:138:8:-;;;;;;:::i;:::-;;:::i;4555:410:69:-;;;;;;:::i;:::-;;:::i;3001:151:70:-;;;;;;:::i;:::-;-1:-1:-1;;;;;3113:32:70;3090:4;3113:32;;;:25;:32;;;;;;;;;3001:151;3701:133:69;;;;;;:::i;:::-;;:::i;3040:383::-;;;;;;:::i;:::-;;:::i;4925:281:28:-;;;;;;:::i;:::-;;:::i;3200:127:70:-;;;:::i;493:46:80:-;;537:2;493:46;;3893:296:30;4052:4;4079:45;4112:11;4079:32;:45::i;:::-;:103;;;;4128:54;4170:11;4128:41;:54::i;:::-;4072:110;3893:296;-1:-1:-1;;3893:296:30:o;1872:205:70:-;2185:26:71;:24;:26::i;:::-;1984:9:70::1;1979:92;1999:17:::0;;::::1;1979:92;;;2037:23;2050:6;;2057:1;2050:9;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;2037:12;:23::i;:::-;2018:3;;1979:92;;;;1872:205:::0;;:::o;2709:275:30:-;2833:24;:6;2849:7;2833:15;:24::i;:::-;2832:25;2824:105;;;;-1:-1:-1;;;2824:105:30;;;;;;;;;;;;2939:38;2963:4;2969:7;2939:23;:38::i;:::-;2709:275;;:::o;2125:251:70:-;2185:26:71;:24;:26::i;:::-;-1:-1:-1;;;;;2258:19:70;::::1;2250:64;;;;-1:-1:-1::0;;;2250:64:70::1;;;;;;;;;;;;2324:45;2353:5;2360:8;2324:28;:45::i;5311:245:8:-:0;-1:-1:-1;;;;;5404:34:8;;735:10:18;5404:34:8;5400:102;;5461:30;;-1:-1:-1;;;5461:30:8;;;;;;;;;;;5400:102;5512:37;5524:4;5530:18;5512:11;:37::i;3487:150:69:-;880:24;:22;:24::i;:::-;3607:23:::1;3620:9;3607:12;:23::i;:::-;3487:150:::0;:::o;2583:330:28:-;2002:18:71;:16;:18::i;:::-;2846:60:28::1;2881:7;2890:4;2896:2;2900:5;2846:34;:60::i;:::-;2583:330:::0;;;;:::o;2979:137:71:-;3047:35;3076:5;3047:28;:35::i;:::-;3092:17;3103:5;3092:10;:17::i;3404:141::-;3474:35;3503:5;3474:28;:35::i;:::-;3519:19;3532:5;3519:12;:19::i;5029:136:69:-;5108:16;5143:15;:6;:13;:15::i;:::-;5136:22;;5029:136;:::o;4333:158::-;4430:4;4453:31;4430:4;4477:5;4453:15;:31::i;3239:155:28:-;2002:18:71;:16;:18::i;:::-;3352:35:28::1;3373:1;3377:2;3381:5;3352:12;:35::i;2211:383:68:-:0;2274:7;2321:1;2297:21;:12;:19;:21::i;:::-;:25;2293:295;;;2510:19;:12;2527:1;2510:16;:19::i;2293:295::-;-1:-1:-1;2575:1:68;;2211:383::o;5266:311:28:-;5447:4;;5474:55;5504:7;5513:4;5519:2;5523:5;5474:29;:55::i;:::-;:96;;;5467:103;;5266:311;;;;;;;:::o;4621:240::-;4771:13;4807:47;4838:15;4807:30;:47::i;2982:212::-;2002:18:71;:16;:18::i;:::-;3158:29:28::1;3171:4;3177:2;3181:5;3158:12;:29::i;3439:161::-:0;2002:18:71;:16;:18::i;:::-;3556:37:28::1;3569:4;3583:1;3587:5;3556:12;:37::i;1555:143:12:-:0;1636:7;1662:18;;;:12;:18;;;;;:29;;1685:5;1662:22;:29::i;:::-;1655:36;1555:143;-1:-1:-1;;;1555:143:12:o;3305:349:30:-;-1:-1:-1;;;;;2920:29:8;;3462:4:30;2920:29:8;;;:12;;:29;:12;:29;;;;;3482:166:30;;;-1:-1:-1;3559:4:30;3552:11;;3482:166;-1:-1:-1;2897:4:8;2920:12;;;:6;:12;;;;;;;;-1:-1:-1;;;;;2920:29:8;;;;;;;;;;;;3594:43:30;;3636:133:71;3711:4;3734:28;:12;3756:5;3734:21;:28::i;2540:136:12:-;2642:18;;;;:12;:18;;;;;2607:16;;2642:27;;:25;:27::i;2691:117:69:-;794:19;:17;:19::i;:::-;2788:13:::1;:11;:13::i;:::-;2691:117::o:0;2150:477::-;794:19;:17;:19::i;:::-;2293:1:::1;2276:18:::0;;;2268:76:::1;;;;-1:-1:-1::0;;;2268:76:69::1;;;;;;;;;;;;2379:9;::::0;2362:26;;::::1;;2354:97;;;;-1:-1:-1::0;;;2354:97:69::1;;;;;;643:25:83::0;;631:2;616:18;;497:177;2354:97:69::1;;;;;;;;;;2483:1;2465:15;:6;:13;:15::i;:::-;:19;2461:63;;;2500:13;:11;:13::i;:::-;2538:9;2533:88;2553:17:::0;;::::1;2533:88;;;2591:19;2600:6;;2607:1;2600:9;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;2591:8;:19::i;:::-;2572:3;;2533:88;;2424:478:70::0;2185:26:71;:24;:26::i;:::-;2607:9:70::1;2602:229;2622:17:::0;;::::1;2602:229;;;2660:13;2676:6;;2683:1;2676:9;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;2660:25:::0;-1:-1:-1;;;;;;2707:19:70;::::1;2699:64;;;;-1:-1:-1::0;;;2699:64:70::1;;;;;;;;;;;;-1:-1:-1::0;;;;;2777:32:70::1;;::::0;;;:25:::1;:32;::::0;;;;:43;;-1:-1:-1;;2777:43:70::1;::::0;::::1;;;::::0;;-1:-1:-1;2641:3:70::1;2602:229;;;;2845:50;2878:6;;2886:8;2845:50;;;;;;;;:::i;:::-;;;;;;;;2424:478:::0;;;:::o;4137:132:69:-;4221:7;4247:15;:6;:13;:15::i;1623:201:70:-;2185:26:71;:24;:26::i;:::-;1733:9:70::1;1728:90;1748:17:::0;;::::1;1728:90;;;1786:21;1797:6;;1804:1;1797:9;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;1786:10;:21::i;:::-;1767:3;;1728:90;;1866:131:12::0;1937:7;1963:18;;;:12;:18;;;;;:27;;:25;:27::i;4289:282:28:-;4480:5;4508:56;4539:7;4548:4;4554:2;4558:5;4508:30;:56::i;:::-;4501:63;4289:282;-1:-1:-1;;;;;4289:282:28:o;3991:242::-;4155:5;4183:43;4210:4;4216:2;4220:5;4183:26;:43::i;4608:138:8:-;3841:7;3867:12;;;:6;:12;;;;;:22;;;2464:16;2475:4;2464:10;:16::i;:::-;4713:26:::1;4725:4;4731:7;4713:11;:26::i;4555:410:69:-:0;4647:7;4679:15;:6;:13;:15::i;:::-;4670:6;:24;4666:293;;;4882:18;:6;4893;4882:10;:18::i;4666:293::-;-1:-1:-1;4946:1:69;;4555:410;-1:-1:-1;4555:410:69:o;3701:133::-;794:19;:17;:19::i;:::-;3809:18:::1;3821:5;3809:11;:18::i;3040:383::-:0;794:19;:17;:19::i;:::-;3274:9:::1;::::0;;3301:15:::1;3254:17;3301:13;:15::i;:::-;:27;3380:9;3293:98;;;;;-1:-1:-1::0;;;3293:98:69::1;;;;;;643:25:83::0;;631:2;616:18;;497:177;3293:98:69::1;;3401:15;3410:5;3401:8;:15::i;4925:281:28:-:0;5089:4;;5116:42;5142:4;5148:2;5152:5;5116:25;:42::i;:::-;:83;;;;4925:281;-1:-1:-1;;;;4925:281:28:o;3200:127:70:-;3264:16;3299:21;:12;:19;:21::i;11440:599:28:-;11533:4;-1:-1:-1;;;;;;11556:61:28;;-1:-1:-1;;;11556:61:28;;:132;;-1:-1:-1;;;;;;;11633:55:28;;-1:-1:-1;;;11633:55:28;11556:132;:214;;;-1:-1:-1;;;;;;;11704:66:28;;-1:-1:-1;;;11704:66:28;11556:214;:298;;;-1:-1:-1;;;;;;;11786:68:28;;-1:-1:-1;;;11786:68:28;11556:298;:391;;;-1:-1:-1;;;;;;;11870:77:28;;-1:-1:-1;;;11870:77:28;11556:391;:476;;;-1:-1:-1;;;;;;;11963:69:28;;-1:-1:-1;;;11963:69:28;11549:483;11440:599;-1:-1:-1;;11440:599:28:o;758:212:12:-;843:4;-1:-1:-1;;;;;;866:57:12;;-1:-1:-1;;;866:57:12;;:97;;;927:36;951:11;927:23;:36::i;2998:103:68:-;3070:24;:22;:24::i;2008:174:67:-;2129:46;2169:5;2129:39;:46::i;17414:165:27:-;-1:-1:-1;;;;;17547:23:27;;17494:4;5238:21;;;:14;;;:21;;;;;;:26;;17517:55;5142:129;4192:136:8;3841:7;3867:12;;;:6;:12;;;;;:22;;;2464:16;2475:4;2464:10;:16::i;:::-;4296:25:::1;4307:4;4313:7;4296:10;:25::i;4883:204:70:-:0;-1:-1:-1;;;;;4978:32:70;;;;;;:25;:32;;;;;;;;;:43;;-1:-1:-1;;4978:43:70;;;;;;;;;;5036:44;;445:41:83;;;5036:44:70;;418:18:83;5036:44:70;;;;;;;4883:204;;:::o;3138:262:12:-;3225:4;3241:12;3256:32;3274:4;3280:7;3256:17;:32::i;:::-;3241:47;;3302:7;3298:72;;;3325:18;;;;:12;:18;;;;;:34;;3351:7;3325:25;:34::i;:::-;;3386:7;3138:262;-1:-1:-1;;;3138:262:12:o;4896:91:30:-;2232:4:8;2464:16;2232:4;2464:10;:16::i;6050:225:69:-;6126:9;6139:1;6126:14;6118:82;;;;-1:-1:-1;;;6118:82:69;;;;;;;;;;;;6210:9;:21;;;6246:22;;643:25:83;;;6246:22:69;;631:2:83;616:18;6246:22:69;;;;;;;;6050:225;:::o;6902:144:71:-;6970:33;:12;6992:10;6970:21;:33::i;:::-;6962:77;;;;-1:-1:-1;;;6962:77:71;;;;;;;;;;;9164:285:69;9271:19;9293:15;:6;:13;:15::i;:::-;9271:37;-1:-1:-1;9323:9:69;9318:125;9342:11;9338:1;:15;9318:125;;;9380:13;:6;9391:1;9380:10;:13::i;:::-;9374:58;;-1:-1:-1;;;9374:58:69;;-1:-1:-1;;;;;9711:32:83;;;9374:58:69;;;9693:51:83;9780:32;;;9760:18;;;9753:60;9849:32;;;9829:18;;;9822:60;9898:18;;;9891:34;;;9374:32:69;;;;;;;9665:19:83;;9374:58:69;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;9355:3;;;;;9318:125;;;;9261:188;9164:285;;;;:::o;1475:234:67:-;1640:62;1696:5;1640:55;:62::i;4440:400:71:-;-1:-1:-1;;;;;4510:19:71;;4502:64;;;;-1:-1:-1;;;4502:64:71;;;;;;;;;;;;4576:26;4596:5;4576:19;:26::i;:::-;4743:23;:12;4760:5;4743:16;:23::i;:::-;4735:66;;;;-1:-1:-1;;;4735:66:71;;;;;;;;;;;;4816:17;;-1:-1:-1;;;;;5748:32:83;;5730:51;;4816:17:71;;5718:2:83;5703:18;4816:17:71;5584:203:83;19500:273:27;19563:16;19591:22;19616:19;19624:3;19616:7;:19::i;8250:259:69:-;8340:19;8362:15;:6;:13;:15::i;:::-;8340:37;-1:-1:-1;8392:9:69;8387:116;8411:11;8407:1;:15;8387:116;;;8449:13;:6;8460:1;8449:10;:13::i;:::-;8443:49;;-1:-1:-1;;;8443:49:69;;-1:-1:-1;;;;;10156:32:83;;;8443:49:69;;;10138:51:83;10225:32;;;10205:18;;;10198:60;10274:18;;;10267:34;;;8443:32:69;;;;;;;10111:18:83;;8443:49:69;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8424:3;;;;;8387:116;;;;8330:179;8250:259;;;:::o;17660:115:27:-;17723:7;17749:19;17757:3;5434:18;;5352:107;18802:158;18877:7;18927:23;18932:3;18944:5;18927:4;:23::i;8179:594:28:-;8273:13;8302:56;;;8298:110;;-1:-1:-1;;8381:16:28;;;;;;;;;;;;-1:-1:-1;;;8381:16:28;;;;;8179:594::o;8298:110::-;8417:19;8439:15;:6;:13;:15::i;:::-;8417:37;-1:-1:-1;8469:9:28;8464:267;8488:11;8484:1;:15;8464:267;;;8520:11;8540:13;8520:11;8551:1;8540:10;:13::i;:::-;8572:55;;-1:-1:-1;;;8572:55:28;;8405:4:83;8393:17;;8572:55:28;;;8375:36:83;8520:34:28;;-1:-1:-1;;;;;;8572:38:28;;;;;8348:18:83;;8572:55:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;8568:153;;;8654:52;;-1:-1:-1;;;8654:52:28;;8405:4:83;8393:17;;8654:52:28;;;8375:36:83;-1:-1:-1;;;;;8654:35:28;;;;;8348:18:83;;8654:52:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;8654:52:28;;;;;;;;;;;;:::i;8568:153::-;-1:-1:-1;8501:3:28;;8464:267;;;-1:-1:-1;;8747:19:28;;;;;;;;;;;;;;;;;;8179:594;-1:-1:-1;;8179:594:28:o;4697:89:30:-;405:34:81;2464:16:8;2475:4;2464:10;:16::i;5444:98:69:-;5499:12;;;;;;;5521:14;:6;:12;:14::i;6762:312::-;6820:26;6839:5;6820:10;:26::i;:::-;6957;:6;6976:5;6957:10;:26::i;:::-;6949:89;;;;-1:-1:-1;;;6949:89:69;;;;;;;;;;;;7053:14;;-1:-1:-1;;;;;7053:14:69;;;;;;;;6762:312;:::o;6974:537:28:-;7135:5;7156:19;7178:15;:6;:13;:15::i;:::-;7156:37;-1:-1:-1;7208:9:28;7203:248;7227:11;7223:1;:15;7203:248;;;7259:17;7285:13;7259:17;7296:1;7285:10;:13::i;:::-;7279:76;;-1:-1:-1;;;7279:76:28;;-1:-1:-1;;;;;9711:32:83;;;7279:76:28;;;9693:51:83;9780:32;;;9760:18;;;9753:60;9849:32;;;9829:18;;;9822:60;9898:18;;;9891:34;;;7279:50:28;;;;;;;9665:19:83;;7279:76:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;7259:96;-1:-1:-1;7373:15:28;;;;7369:72;;7415:11;-1:-1:-1;7408:18:28;;-1:-1:-1;;7408:18:28;7369:72;-1:-1:-1;7240:3:28;;7203:248;;;-1:-1:-1;7473:30:28;7460:44;6974:537;-1:-1:-1;;;;;;6974:537:28:o;6110:467::-;6218:5;6235:19;6257:15;:6;:13;:15::i;:::-;6235:37;-1:-1:-1;6287:9:28;6282:235;6306:11;6302:1;:15;6282:235;;;6338:17;6364:13;6338:17;6375:1;6364:10;:13::i;:::-;6358:63;;-1:-1:-1;;;6358:63:28;;-1:-1:-1;;;;;10156:32:83;;;6358:63:28;;;10138:51:83;10225:32;;;10205:18;;;10198:60;10274:18;;;10267:34;;;6358:46:28;;;;;;;10111:18:83;;6358:63:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;6338:83;-1:-1:-1;6439:15:28;;;;6435:72;;6481:11;-1:-1:-1;6474:18:28;;-1:-1:-1;;6474:18:28;6435:72;-1:-1:-1;6319:3:28;;6282:235;;;-1:-1:-1;6539:30:28;6526:44;6110:467;-1:-1:-1;;;;;6110:467:28:o;3165:103:8:-;3231:30;3242:4;735:10:18;3231::8;:30::i;7335:255:69:-;7470:29;:6;7492:5;7470:13;:29::i;:::-;7462:89;;;;-1:-1:-1;;;7462:89:69;;;;;;;;;;;;7566:17;;-1:-1:-1;;;;;7566:17:69;;;;;;;;7335:255;:::o;2531:202:8:-;2616:4;-1:-1:-1;;;;;;2639:47:8;;-1:-1:-1;;;2639:47:8;;:87;;-1:-1:-1;;;;;;;;;;829:40:22;;;2690:36:8;730:146:22;4492:96:30;419:36:75;2464:16:8;2475:4;2464:10;:16::i;4275:255:70:-;4348:38;4380:5;4348:31;:38::i;:::-;4400:10;-1:-1:-1;;;;;4400:19:70;;;;;;:55;;-1:-1:-1;;;;;;4423:32:70;;;;;;:25;:32;;;;;;;;4400:55;4396:128;;;4471:42;4500:5;4507;4471:28;:42::i;2778:257:12:-;2864:4;2880:12;2895:31;2912:4;2918:7;2895:16;:31::i;:::-;2880:46;;2940:7;2936:69;;;2963:18;;;;:12;:18;;;;;:31;;2986:7;2963:22;:31::i;6715:317:8:-;6793:4;6813:22;6821:4;6827:7;6813;:22::i;:::-;6809:217;;;6883:5;6851:12;;;:6;:12;;;;;;;;-1:-1:-1;;;;;6851:29:8;;;;;;;;;;:37;;-1:-1:-1;;6851:37:8;;;6907:40;735:10:18;;6851:12:8;;6907:40;;6883:5;6907:40;-1:-1:-1;6968:4:8;6961:11;;6809:217;-1:-1:-1;7010:5:8;7003:12;;16780:156:27;16853:4;16876:53;16884:3;-1:-1:-1;;;;;16904:23:27;;16876:7;:53::i;5759:223:70:-;5852:10;-1:-1:-1;;;;;5852:19:70;;;:55;;;;-1:-1:-1;;;;;;5875:32:70;;;;;;:25;:32;;;;;;;;5852:55;5848:92;;;5759:223;:::o;5848:92::-;5949:26;:24;:26::i;9793:195:28:-;9887:22;:6;9903:5;9887:15;:22::i;:::-;9886:23;9878:103;;;;-1:-1:-1;;;9878:103:28;;;;;;;;;;;16462:150:27;16532:4;16555:50;16560:3;-1:-1:-1;;;;;16580:23:27;;16555:4;:50::i;6460:109::-;6516:16;6551:3;:11;;6544:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6460:109;;;:::o;5801:119::-;5869:7;5895:3;:11;;5907:5;5895:18;;;;;;;;:::i;:::-;;;;;;;;;5888:25;;5801:119;;;;:::o;17250:83::-;17308:18;17315:3;17308:6;:18::i;9061:324:28:-;9137:39;9170:5;9137:32;:39::i;:::-;9195:28;:12;9217:5;9195:21;:28::i;:::-;9194:29;9186:109;;;;-1:-1:-1;;;9186:109:28;;;;;;;;;;;;9313:29;9336:5;9313:22;:29::i;:::-;9305:73;;;;-1:-1:-1;;;9305:73:28;;;;;;;;;;;3398:197:8;3486:22;3494:4;3500:7;3486;:22::i;:::-;3481:108;;3531:47;;-1:-1:-1;;;3531:47:8;;-1:-1:-1;;;;;12078:32:83;;3531:47:8;;;12060:51:83;12127:18;;;12120:34;;;12033:18;;3531:47:8;11886:274:83;5410:294:71;5605:26;:12;5625:5;5605:19;:26::i;:::-;5597:65;;;;-1:-1:-1;;;5597:65:71;;;;;;;;;;;;5678:19;;-1:-1:-1;;;;;5748:32:83;;5730:51;;5678:19:71;;5718:2:83;5703:18;5678:19:71;5584:203:83;6162:316:8;6239:4;6260:22;6268:4;6274:7;6260;:22::i;:::-;6255:217;;6298:12;;;;:6;:12;;;;;;;;-1:-1:-1;;;;;6298:29:8;;;;;;;;;:36;;-1:-1:-1;;6298:36:8;6330:4;6298:36;;;6380:12;735:10:18;;656:96;6380:12:8;-1:-1:-1;;;;;6353:40:8;6371:7;-1:-1:-1;;;;;6353:40:8;6365:4;6353:40;;;;;;;;;;-1:-1:-1;6414:4:8;6407:11;;3112:1368:27;3178:4;3307:21;;;:14;;;:21;;;;;;3343:13;;3339:1135;;3710:18;3731:12;3742:1;3731:8;:12;:::i;:::-;3777:18;;3710:33;;-1:-1:-1;3757:17:27;;3777:22;;3798:1;;3777:22;:::i;:::-;3757:42;;3832:9;3818:10;:23;3814:378;;3861:17;3881:3;:11;;3893:9;3881:22;;;;;;;;:::i;:::-;;;;;;;;;3861:42;;4028:9;4002:3;:11;;4014:10;4002:23;;;;;;;;:::i;:::-;;;;;;;;;;;;:35;;;;4141:25;;;:14;;;:25;;;;;:36;;;3814:378;4270:17;;:3;;:17;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;4373:3;:14;;:21;4388:5;4373:21;;;;;;;;;;;4366:28;;;4416:4;4409:11;;;;;;;3339:1135;4458:5;4451:12;;;;;2538:406;2601:4;5238:21;;;:14;;;:21;;;;;;2617:321;;-1:-1:-1;2659:23:27;;;;;;;;:11;:23;;;;;;;;;;;;;2841:18;;2817:21;;;:14;;;:21;;;;;;:42;;;;2873:11;;4824:237;4875:11;4889:12;4897:3;5434:18;;5352:107;4889:12;4875:26;-1:-1:-1;4916:9:27;4911:96;4935:3;4931:1;:7;4911:96;;;4966:3;:14;;:30;4981:3;:11;;4993:1;4981:14;;;;;;;;:::i;:::-;;;;;;;;;4966:30;;;;;;;;;;;4959:37;;;4940:3;;;;;4911:96;;;-1:-1:-1;;5039:11:27;34209:23:16;;2709:275:30:o;9974:164:69:-;-1:-1:-1;;;;;10049:19:69;;10041:90;;;;-1:-1:-1;;;10041:90:69;;;;;;;;;;;10702:397:28;10780:4;10801:35;10830:5;10801:28;:35::i;:::-;10796:79;;-1:-1:-1;10859:5:28;;10702:397;-1:-1:-1;10702:397:28:o;10796:79::-;10891:89;10938:5;-1:-1:-1;;;10891:46:28;:89::i;:::-;:201;;;-1:-1:-1;10996:96:28;11043:5;-1:-1:-1;;;10996:46:28;:96::i;719:528:23:-;783:4;976:68;1009:7;-1:-1:-1;;;976:32:23;:68::i;:::-;972:269;;;1061:12;;1093:52;1115:7;-1:-1:-1;;;;;;1093:21:23;:52::i;:::-;1060:85;;;;1166:7;:21;;;;-1:-1:-1;1177:10:23;;1159:28;-1:-1:-1;;;719:528:23:o;4504:238::-;4606:4;4623:12;4637:14;4655:43;4677:7;4686:11;4655:21;:43::i;:::-;4622:76;;;;4715:7;:20;;;;-1:-1:-1;4726:9:23;4708:27;-1:-1:-1;;;;4504:238:23:o;5198:628::-;-1:-1:-1;;;5310:12:23;5452:22;;;5494:4;5487:25;;;5310:12;;;5581:4;5310:12;5569:4;5310:12;5554:7;5547:5;5536:50;5525:61;;5740:4;5734:11;5727:19;5720:27;5654:4;5636:16;5633:26;5612:198;5599:211;;5438:382;5198:628;;;;;:::o;14:286:83:-;72:6;125:2;113:9;104:7;100:23;96:32;93:52;;;141:1;138;131:12;93:52;167:23;;-1:-1:-1;;;;;;219:32:83;;209:43;;199:71;;266:1;263;256:12;679:367;742:8;752:6;806:3;799:4;791:6;787:17;783:27;773:55;;824:1;821;814:12;773:55;-1:-1:-1;847:20:83;;890:18;879:30;;876:50;;;922:1;919;912:12;876:50;959:4;951:6;947:17;935:29;;1019:3;1012:4;1002:6;999:1;995:14;987:6;983:27;979:38;976:47;973:67;;;1036:1;1033;1026:12;973:67;679:367;;;;;:::o;1051:437::-;1137:6;1145;1198:2;1186:9;1177:7;1173:23;1169:32;1166:52;;;1214:1;1211;1204:12;1166:52;1254:9;1241:23;1287:18;1279:6;1276:30;1273:50;;;1319:1;1316;1309:12;1273:50;1358:70;1420:7;1411:6;1400:9;1396:22;1358:70;:::i;:::-;1447:8;;1332:96;;-1:-1:-1;1051:437:83;-1:-1:-1;;;;1051:437:83:o;1493:226::-;1552:6;1605:2;1593:9;1584:7;1580:23;1576:32;1573:52;;;1621:1;1618;1611:12;1573:52;-1:-1:-1;1666:23:83;;1493:226;-1:-1:-1;1493:226:83:o;1724:131::-;-1:-1:-1;;;;;1799:31:83;;1789:42;;1779:70;;1845:1;1842;1835:12;1860:367;1928:6;1936;1989:2;1977:9;1968:7;1964:23;1960:32;1957:52;;;2005:1;2002;1995:12;1957:52;2050:23;;;-1:-1:-1;2149:2:83;2134:18;;2121:32;2162:33;2121:32;2162:33;:::i;:::-;2214:7;2204:17;;;1860:367;;;;;:::o;2232:118::-;2318:5;2311:13;2304:21;2297:5;2294:32;2284:60;;2340:1;2337;2330:12;2355:382;2420:6;2428;2481:2;2469:9;2460:7;2456:23;2452:32;2449:52;;;2497:1;2494;2487:12;2449:52;2536:9;2523:23;2555:31;2580:5;2555:31;:::i;:::-;2605:5;-1:-1:-1;2662:2:83;2647:18;;2634:32;2675:30;2634:32;2675:30;:::i;2973:650::-;3059:6;3067;3075;3083;3136:3;3124:9;3115:7;3111:23;3107:33;3104:53;;;3153:1;3150;3143:12;3104:53;3192:9;3179:23;3211:31;3236:5;3211:31;:::i;:::-;3261:5;-1:-1:-1;3318:2:83;3303:18;;3290:32;3331:33;3290:32;3331:33;:::i;:::-;3383:7;-1:-1:-1;3442:2:83;3427:18;;3414:32;3455:33;3414:32;3455:33;:::i;:::-;2973:650;;;;-1:-1:-1;3507:7:83;;3587:2;3572:18;3559:32;;-1:-1:-1;;2973:650:83:o;3628:247::-;3687:6;3740:2;3728:9;3719:7;3715:23;3711:32;3708:52;;;3756:1;3753;3746:12;3708:52;3795:9;3782:23;3814:31;3839:5;3814:31;:::i;3880:637::-;4070:2;4082:21;;;4152:13;;4055:18;;;4174:22;;;4022:4;;4253:15;;;4227:2;4212:18;;;4022:4;4296:195;4310:6;4307:1;4304:13;4296:195;;;4375:13;;-1:-1:-1;;;;;4371:39:83;4359:52;;4440:2;4466:15;;;;4431:12;;;;4407:1;4325:9;4296:195;;;-1:-1:-1;4508:3:83;;3880:637;-1:-1:-1;;;;;3880:637:83:o;4789:418::-;4938:2;4927:9;4920:21;4901:4;4970:6;4964:13;5013:6;5008:2;4997:9;4993:18;4986:34;5072:6;5067:2;5059:6;5055:15;5050:2;5039:9;5035:18;5029:50;5128:1;5123:2;5114:6;5103:9;5099:22;5095:31;5088:42;5198:2;5191;5187:7;5182:2;5174:6;5170:15;5166:29;5155:9;5151:45;5147:54;5139:62;;;4789:418;;;;:::o;5212:367::-;5280:6;5288;5341:2;5329:9;5320:7;5316:23;5312:32;5309:52;;;5357:1;5354;5347:12;5309:52;5396:9;5383:23;5415:31;5440:5;5415:31;:::i;:::-;5465:5;5543:2;5528:18;;;;5515:32;;-1:-1:-1;;;5212:367:83:o;5974:114::-;6058:4;6051:5;6047:16;6040:5;6037:27;6027:55;;6078:1;6075;6068:12;6093:243;6150:6;6203:2;6191:9;6182:7;6178:23;6174:32;6171:52;;;6219:1;6216;6209:12;6171:52;6258:9;6245:23;6277:29;6300:5;6277:29;:::i;6341:508::-;6418:6;6426;6434;6487:2;6475:9;6466:7;6462:23;6458:32;6455:52;;;6503:1;6500;6493:12;6455:52;6542:9;6529:23;6561:31;6586:5;6561:31;:::i;:::-;6611:5;-1:-1:-1;6668:2:83;6653:18;;6640:32;6681:33;6640:32;6681:33;:::i;:::-;6341:508;;6733:7;;-1:-1:-1;;;6813:2:83;6798:18;;;;6785:32;;6341:508::o;6854:346::-;6922:6;6930;6983:2;6971:9;6962:7;6958:23;6954:32;6951:52;;;6999:1;6996;6989:12;6951:52;-1:-1:-1;;7044:23:83;;;7164:2;7149:18;;;7136:32;;-1:-1:-1;6854:346:83:o;7662:566::-;7754:6;7762;7770;7823:2;7811:9;7802:7;7798:23;7794:32;7791:52;;;7839:1;7836;7829:12;7791:52;7879:9;7866:23;7912:18;7904:6;7901:30;7898:50;;;7944:1;7941;7934:12;7898:50;7983:70;8045:7;8036:6;8025:9;8021:22;7983:70;:::i;:::-;8072:8;;-1:-1:-1;7957:96:83;-1:-1:-1;;8157:2:83;8142:18;;8129:32;8170:28;8129:32;8170:28;:::i;:::-;8217:5;8207:15;;;7662:566;;;;;:::o;8422:127::-;8483:10;8478:3;8474:20;8471:1;8464:31;8514:4;8511:1;8504:15;8538:4;8535:1;8528:15;8686:771;8908:2;8920:21;;;8893:18;;8976:22;;;8860:4;9055:6;9029:2;9014:18;;8860:4;9089:281;9103:6;9100:1;9097:13;9089:281;;;9178:6;9165:20;9198:31;9223:5;9198:31;:::i;:::-;-1:-1:-1;;;;;9254:31:83;9242:44;;9315:4;9343:17;;;;9306:14;;;;9282:1;9118:9;9089:281;;;9093:3;9387;9379:11;;;;9442:6;9435:14;9428:22;9421:4;9410:9;9406:20;9399:52;8686:771;;;;;;:::o;10312:245::-;10379:6;10432:2;10420:9;10411:7;10407:23;10403:32;10400:52;;;10448:1;10445;10438:12;10400:52;10480:9;10474:16;10499:28;10521:5;10499:28;:::i;10562:127::-;10623:10;10618:3;10614:20;10611:1;10604:31;10654:4;10651:1;10644:15;10678:4;10675:1;10668:15;10694:935;10774:6;10827:2;10815:9;10806:7;10802:23;10798:32;10795:52;;;10843:1;10840;10833:12;10795:52;10876:9;10870:16;10909:18;10901:6;10898:30;10895:50;;;10941:1;10938;10931:12;10895:50;10964:22;;11017:4;11009:13;;11005:27;-1:-1:-1;10995:55:83;;11046:1;11043;11036:12;10995:55;11079:2;11073:9;11105:18;11097:6;11094:30;11091:56;;;11127:18;;:::i;:::-;11176:2;11170:9;11268:2;11230:17;;-1:-1:-1;;11226:31:83;;;11259:2;11222:40;11218:54;11206:67;;11303:18;11288:34;;11324:22;;;11285:62;11282:88;;;11350:18;;:::i;:::-;11386:2;11379:22;11410;;;11451:15;;;11468:2;11447:24;11444:37;-1:-1:-1;11441:57:83;;;11494:1;11491;11484:12;11441:57;11543:6;11538:2;11534;11530:11;11525:2;11517:6;11513:15;11507:43;11596:1;11570:19;;;11591:2;11566:28;11559:39;;;;11574:6;10694:935;-1:-1:-1;;;;10694:935:83:o;11634:247::-;11702:6;11755:2;11743:9;11734:7;11730:23;11726:32;11723:52;;;11771:1;11768;11761:12;11723:52;11803:9;11797:16;11822:29;11845:5;11822:29;:::i;12165:225::-;12232:9;;;12253:11;;;12250:134;;;12306:10;12301:3;12297:20;12294:1;12287:31;12341:4;12338:1;12331:15;12369:4;12366:1;12359:15;12395:127;12456:10;12451:3;12447:20;12444:1;12437:31;12487:4;12484:1;12477:15;12511:4;12508:1;12501:15","linkReferences":{}},"methodIdentifiers":{"COMPLIANCE_MANAGER_ROLE()":"03c26bcd","DEFAULT_ADMIN_ROLE()":"a217fddf","DEFAULT_MAX_RULES()":"f76bf550","RULES_MANAGEMENT_ROLE()":"9b11c115","addRule(address)":"e3c4602c","bindToken(address)":"3ff5aa02","bindTokens(address[])":"c7c24b18","canTransfer(address,address,uint256)":"e46638e6","canTransferFrom(address,address,address,uint256)":"7157797f","clearRules()":"b043572e","containsRule(address)":"54e4b945","created(address,uint256)":"5f8dead3","destroyed(address,uint256)":"8d2ea772","detectTransferRestriction(address,address,uint256)":"d4ce1415","detectTransferRestrictionFrom(address,address,address,uint256)":"d32c7bb5","getRoleAdmin(bytes32)":"248a9ca3","getRoleMember(bytes32,uint256)":"9010d07c","getRoleMemberCount(bytes32)":"ca15c873","getRoleMembers(bytes32)":"a3246ad3","getTokenBound()":"6a3edf28","getTokenBounds()":"e54621d2","grantRole(bytes32,address)":"2f2ff15d","hasRole(bytes32,address)":"91d14854","isTokenBound(address)":"993e8b95","isTokenSelfBindingApproved(address)":"db75d017","maxRules()":"6ae728c6","messageForTransferRestriction(uint8)":"7f4ab1dd","removeRule(address)":"df21950f","renounceRole(bytes32,address)":"36568abe","revokeRole(bytes32,address)":"d547741f","rule(uint256)":"db18af6c","rules()":"52f6747a","rulesCount()":"bc13eacc","setMaxRules(uint256)":"3a56d6d5","setRules(address[])":"b27aef3a","setTokenSelfBindingApproval(address,bool)":"3284a9a5","setTokenSelfBindingApprovalBatch(address[],bool)":"bb4b6121","supportsInterface(bytes4)":"01ffc9a7","transferred(address,address,address,uint256)":"3e5af4ca","transferred(address,address,uint256)":"8baf29b4","unbindToken(address)":"40db3b50","unbindTokens(address[])":"1455d0e7","version()":"54fd4d50"},"rawMetadata":"{\"compiler\":{\"version\":\"0.8.37+commit.f401782d\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenContract\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"AccessControlBadConfirmation\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"neededRole\",\"type\":\"bytes32\"}],\"name\":\"AccessControlUnauthorizedAccount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_AdminWithAddressZeroNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_RuleInvalidInterface\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_RulesManagementModule_ArrayIsEmpty\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"maxRules\",\"type\":\"uint256\"}],\"name\":\"RuleEngine_RulesManagementModule_MaxRulesExceeded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_RulesManagementModule_MaxRulesZeroNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_RulesManagementModule_RuleAccountCannotReceivePrivileges\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_RulesManagementModule_RuleAddressZeroNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_RulesManagementModule_RuleAlreadyExists\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_RulesManagementModule_RuleDoNotMatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TokenBinding_InvalidTokenAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TokenBinding_TokenAlreadyBound\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TokenBinding_TokenNotBound\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TokenBinding_UnauthorizedCaller\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract IRule\",\"name\":\"rule\",\"type\":\"address\"}],\"name\":\"AddRule\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"ClearRules\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract IRule\",\"name\":\"rule\",\"type\":\"address\"}],\"name\":\"RemoveRule\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"previousAdminRole\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"newAdminRole\",\"type\":\"bytes32\"}],\"name\":\"RoleAdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleRevoked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"maxRules\",\"type\":\"uint256\"}],\"name\":\"SetMaxRules\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"TokenBound\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"tokens\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"TokenSelfBindingApprovalBatchSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"TokenSelfBindingApprovalSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"TokenUnbound\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"COMPLIANCE_MANAGER_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"DEFAULT_ADMIN_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"DEFAULT_MAX_RULES\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"RULES_MANAGEMENT_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IRule\",\"name\":\"rule_\",\"type\":\"address\"}],\"name\":\"addRule\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"bindToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"tokens\",\"type\":\"address[]\"}],\"name\":\"bindTokens\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"canTransfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"canTransferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"clearRules\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IRule\",\"name\":\"rule_\",\"type\":\"address\"}],\"name\":\"containsRule\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"created\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"destroyed\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"detectTransferRestriction\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"detectTransferRestrictionFrom\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleAdmin\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"getRoleMember\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleMemberCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleMembers\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTokenBound\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTokenBounds\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRole\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"isTokenBound\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"isTokenSelfBindingApproved\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"maxRules\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"restrictionCode\",\"type\":\"uint8\"}],\"name\":\"messageForTransferRestriction\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IRule\",\"name\":\"rule_\",\"type\":\"address\"}],\"name\":\"removeRule\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"callerConfirmation\",\"type\":\"address\"}],\"name\":\"renounceRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"ruleId\",\"type\":\"uint256\"}],\"name\":\"rule\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"rules\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"rulesCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"maxRules_\",\"type\":\"uint256\"}],\"name\":\"setMaxRules\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IRule[]\",\"name\":\"rules_\",\"type\":\"address[]\"}],\"name\":\"setRules\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"setTokenSelfBindingApproval\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"tokens\",\"type\":\"address[]\"},{\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"setTokenSelfBindingApprovalBatch\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"transferred\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"transferred\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"unbindToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"tokens\",\"type\":\"address[]\"}],\"name\":\"unbindTokens\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"version_\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"No ERC-2771 support: every caller is the raw `msg.sender`. Deploy {RuleEngine2771}, which extends this contract, to administer the engine through a trusted forwarder (gasless transactions).\",\"errors\":{\"AccessControlBadConfirmation()\":[{\"details\":\"The caller of a function is not the expected one. NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\"}],\"AccessControlUnauthorizedAccount(address,bytes32)\":[{\"details\":\"The `account` is missing a role.\"}]},\"events\":{\"AddRule(address)\":{\"params\":{\"rule\":\"The address of the rule contract that was added.\"}},\"RemoveRule(address)\":{\"params\":{\"rule\":\"The address of the rule contract that was removed.\"}},\"RoleAdminChanged(bytes32,bytes32,bytes32)\":{\"details\":\"Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite {RoleAdminChanged} not being emitted to signal this.\"},\"RoleGranted(bytes32,address,address)\":{\"details\":\"Emitted when `account` is granted `role`. `sender` is the account that originated the contract call. This account bears the admin role (for the granted role). Expected in cases where the role was granted using the internal {AccessControl-_grantRole}.\"},\"RoleRevoked(bytes32,address,address)\":{\"details\":\"Emitted when `account` is revoked `role`. `sender` is the account that originated the contract call: - if using `revokeRole`, it is the admin role bearer - if using `renounceRole`, it is the role bearer (i.e. `account`)\"},\"SetMaxRules(uint256)\":{\"params\":{\"maxRules\":\"The new rule cap.\"}},\"TokenBound(address)\":{\"details\":\"Same declaration as ERC-3643 `TokenBound(address _token)`, which does not index the token. Keep it non-indexed: `indexed` would move `token` from the data to a topic and break consumers decoding with the standard ERC-3643 ABI.\",\"params\":{\"token\":\"The address of the token that was bound.\"}},\"TokenSelfBindingApprovalBatchSet(address[],bool)\":{\"details\":\"`tokens` is the array as passed: it may contain tokens already at `approved` and duplicates, and is empty for an empty batch, so it lists the tokens that were set, not only those that changed. No {TokenSelfBindingApprovalSet} is emitted per token, so a filter on that event's indexed `token` does not see batch updates. `tokens` is not indexed: an indexed array is stored as a hash and cannot be filtered per token.\",\"params\":{\"approved\":\"True if token self-bind/unbind is allowed, false otherwise.\",\"tokens\":\"The token addresses whose self-binding permission was set, as passed to the call.\"}},\"TokenSelfBindingApprovalSet(address,bool)\":{\"details\":\"Emitted on every call, also when `approved` equals the current value. Not emitted by {setTokenSelfBindingApprovalBatch}, which emits {TokenSelfBindingApprovalBatchSet} instead: a consumer reconstructing the approvals, or filtering on `token`, must handle both events, or read {isTokenSelfBindingApproved}, which is authoritative.\",\"params\":{\"approved\":\"True if token self-bind/unbind is allowed, false otherwise.\",\"token\":\"The token address whose self-binding permission was set.\"}},\"TokenUnbound(address)\":{\"details\":\"Same declaration as ERC-3643 `TokenUnbound(address _token)`; kept non-indexed for the same reason as {TokenBound}.\",\"params\":{\"token\":\"The address of the token that was unbound.\"}}},\"kind\":\"dev\",\"methods\":{\"addRule(address)\":{\"details\":\"Reverts when the configured maximum number of rules is already reached. Security convention: do not grant {RULES_MANAGEMENT_ROLE} to rule contracts.\",\"params\":{\"rule_\":\"The IRule contract to add.\"}},\"bindToken(address)\":{\"custom:security-note\":\"\\\"Multi-tenant\\\" means one instance is shared by multiple token contracts. Downstream state (for the RuleEngine: the per-address accounting held by stateful rules) is shared across all bound tokens, so binding tokens from different issuers silently cross-contaminates it. Only bind tokens that are equally trusted and governed together.\",\"details\":\"Authorized by {_authorizeTokenBindingChange}.\",\"params\":{\"token\":\"The address of the token to bind.\"}},\"bindTokens(address[])\":{\"custom:security-note\":\"See {bindToken} for multi-tenant state risks. All tokens bound in this batch share the same downstream state. Only bind tokens that are equally trusted and governed together.\",\"details\":\"Must be restricted by implementation-specific access control. Atomic: reverts if any token is invalid or already bound (or listed twice), and then binds none of them. This deliberately departs from the usual batch convention of skipping elements already in the target state: a binding change is security-relevant, and a token that is already bound in the list is most likely an operator mistake that should stop the whole operation. An empty array is a no-op.\",\"params\":{\"tokens\":\"The token addresses to bind.\"}},\"canTransfer(address,address,uint256)\":{\"details\":\"Don't check the balance and the user's right (access control)\",\"params\":{\"from\":\"The address sending tokens.\",\"to\":\"The address receiving tokens.\",\"value\":\"The amount of tokens to transfer.\"},\"returns\":{\"_0\":\"True if the transfer is valid, false otherwise.\"}},\"canTransferFrom(address,address,address,uint256)\":{\"details\":\"Does not check balances or access rights (Access Control).\",\"params\":{\"from\":\"The source address.\",\"spender\":\"The address performing the transfer.\",\"to\":\"The destination address.\",\"value\":\"The number of tokens to transfer.\"},\"returns\":{\"_0\":\"isCompliant True if the transfer complies with policy.\"}},\"clearRules()\":{\"details\":\"After calling this function, no rules will remain set. Cost is O(n) in the number of configured rules. With the default cap of 10 this is negligible, but a high {maxRules} setting re-exposes unbounded cost here even though per-transfer cost remains bounded.\"},\"constructor\":{\"params\":{\"admin\":\"Address receiving `DEFAULT_ADMIN_ROLE`; must not be the zero address.\",\"tokenContract\":\"Token to bind at deployment, or the zero address to bind none.\"}},\"containsRule(address)\":{\"details\":\"Complexity: O(1).\",\"params\":{\"rule_\":\"The IRule contract to check for membership.\"},\"returns\":{\"_0\":\"True if the rule is present, false otherwise.\"}},\"created(address,uint256)\":{\"details\":\"Called by the token contract when new tokens are issued to an account. Reverts if the minting does not comply with the rules.\",\"params\":{\"to\":\"The address receiving the minted tokens.\",\"value\":\"The number of tokens created.\"}},\"destroyed(address,uint256)\":{\"details\":\"Called by the token contract when tokens are redeemed or burned. Reverts if the burning does not comply with the rules.\",\"params\":{\"from\":\"The address whose tokens are being destroyed.\",\"value\":\"The number of tokens destroyed.\"}},\"detectTransferRestriction(address,address,uint256)\":{\"params\":{\"from\":\"the origin address\",\"to\":\"the destination address\",\"value\":\"to transfer\"},\"returns\":{\"_0\":\"The restriction code or REJECTED_CODE_BASE.TRANSFER_OK (0) if the transfer is valid\"}},\"detectTransferRestrictionFrom(address,address,address,uint256)\":{\"details\":\" See {ERC-1404} Add an additionnal argument `spender` This function is where an issuer enforces the restriction logic of their token transfers. Some examples of this might include: - checking if the token recipient is whitelisted, - checking if a sender's tokens are frozen in a lock-up period, etc.\",\"params\":{\"from\":\"The address sending tokens.\",\"spender\":\"The address initiating the delegated transfer.\",\"to\":\"The address receiving tokens.\",\"value\":\"amount of tokens to transfer\"},\"returns\":{\"_0\":\"uint8 restricted code, 0 means the transfer is authorized\"}},\"getRoleAdmin(bytes32)\":{\"details\":\"Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}.\"},\"getRoleMember(bytes32,uint256)\":{\"details\":\"Returns one of the accounts that have `role`. `index` must be a value between 0 and {getRoleMemberCount}, non-inclusive. Role bearers are not sorted in any particular way, and their ordering may change at any point. WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure you perform all queries on the same block. See the following https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] for more information.\"},\"getRoleMemberCount(bytes32)\":{\"details\":\"Returns the number of accounts that have `role`. Can be used together with {getRoleMember} to enumerate all bearers of a role.\"},\"getRoleMembers(bytes32)\":{\"details\":\"Return all accounts that have `role` WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that this function has an unbounded cost, and using it as part of a state-changing function may render the function uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\"},\"getTokenBound()\":{\"details\":\"If multiple tokens are supported, consider using getTokenBounds().\",\"returns\":{\"_0\":\"The address of the currently bound token.\"}},\"getTokenBounds()\":{\"details\":\"This operation copies the entire storage set to memory and is mainly intended for off-chain reads.\",\"returns\":{\"_0\":\"An array of bound token addresses.\"}},\"grantRole(bytes32,address)\":{\"details\":\"Prevents granting any role to accounts currently configured as rules. Note: this check is intentionally one-directional. {addRule} does not verify whether the rule address already holds a privileged role, and this function does not prevent adding a privileged address as a rule afterwards. Operators are responsible for keeping rule contracts and privileged accounts disjoint.\",\"params\":{\"account\":\"The account receiving the role.\",\"role\":\"The role identifier to grant.\"}},\"hasRole(bytes32,address)\":{\"details\":\"The Default Admin has all roles\",\"params\":{\"account\":\"The account to check.\",\"role\":\"The role identifier to check.\"},\"returns\":{\"_0\":\"True if the account holds the role (or is the default admin), false otherwise.\"}},\"isTokenBound(address)\":{\"details\":\"Complexity: O(1).\",\"params\":{\"token\":\"The token address to verify.\"},\"returns\":{\"_0\":\"True if the token is bound, false otherwise.\"}},\"isTokenSelfBindingApproved(address)\":{\"params\":{\"token\":\"The token address to query.\"},\"returns\":{\"_0\":\"True if self-binding is approved for `token`, false otherwise.\"}},\"maxRules()\":{\"returns\":{\"_0\":\"The maximum number of rules that can be configured.\"}},\"messageForTransferRestriction(uint8)\":{\"details\":\"See {ERC-1404} This function is effectively an accessor for the \\\"message\\\", a human-readable explanation as to why a transaction is restricted.\",\"params\":{\"restrictionCode\":\"The restriction code to translate into a message.\"},\"returns\":{\"_0\":\"The human-readable message corresponding to `restrictionCode`.\"}},\"removeRule(address)\":{\"details\":\"Reverts if the provided rule is not found or does not match the stored rule at its index. Complexity: O(1).\",\"params\":{\"rule_\":\"The IRule contract to remove.\"}},\"renounceRole(bytes32,address)\":{\"details\":\"Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). Emits a {RoleRevoked} event if the calling account had `role` and this call successfully revoked it. Requirements: - the caller must be `callerConfirmation`. May emit a {RoleRevoked} event.\"},\"revokeRole(bytes32,address)\":{\"details\":\"Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleRevoked} event.\"},\"rule(uint256)\":{\"details\":\"Reverts if `ruleId` is out of bounds. Complexity: O(1). Note that there are no guarantees on the ordering of values inside the array, and it may change when more values are added or removed.\",\"params\":{\"ruleId\":\"The index of the desired rule in the array.\"},\"returns\":{\"_0\":\"The address of the corresponding IRule contract, return the `zero address` is out of bounds.\"}},\"rules()\":{\"details\":\"This is a view-only function that does not modify state. This operation will copy the entire storage to memory, which can be quite expensive. This is designed to mostly be used by view accessors that are queried without any gas fees.\",\"returns\":{\"_0\":\"An array of all active rule contract addresses.\"}},\"rulesCount()\":{\"details\":\"Equivalent to the length of the internal rules array. Complexity: O(1)\",\"returns\":{\"_0\":\"The number of active rules.\"}},\"setMaxRules(uint256)\":{\"details\":\"Access control is implementation specific (admin/owner). Setting a very high cap re-exposes unbounded gas cost for administrative operations such as {clearRules} even though normal per-transfer cost remains bounded.\",\"params\":{\"maxRules_\":\"New maximum number of rules.\"}},\"setRules(address[])\":{\"details\":\"Replaces the entire rule set atomically. Reverts if `rules_` is empty. Use {clearRules} to remove all rules explicitly. To transition from one non-empty set to another without an enforcement gap, call this function directly with the new set. Emits {ClearRules} when the existing rule set is non-empty, then emits {AddRule} for each new rule. Off-chain indexers must handle both events to reconstruct state. Security convention: rule contracts should be treated as trusted business logic, but should not also be granted {RULES_MANAGEMENT_ROLE}.\",\"params\":{\"rules_\":\"The array of addresses representing the new rules to be set.\"}},\"setTokenSelfBindingApproval(address,bool)\":{\"details\":\"Must be restricted by implementation-specific access control. An approval stays in force until it is revoked here or until the binding manager unbinds the token ({unbindToken} or {unbindTokens}), which revokes it and emits {TokenSelfBindingApprovalSet} with `false`. A token that unbinds itself keeps its approval, so it can bind itself again later.\",\"params\":{\"approved\":\"Whether self-binding is approved for `token`.\",\"token\":\"The token address to configure.\"}},\"setTokenSelfBindingApprovalBatch(address[],bool)\":{\"details\":\"Must be restricted by implementation-specific access control. Reverts if any token in `tokens` is the zero address. Emits a single {TokenSelfBindingApprovalBatchSet} with the input array, not one {TokenSelfBindingApprovalSet} per token.\",\"params\":{\"approved\":\"Whether self-binding is approved for all provided tokens.\",\"tokens\":\"The token addresses to configure.\"}},\"supportsInterface(bytes4)\":{\"params\":{\"interfaceId\":\"The interface identifier to check.\"},\"returns\":{\"_0\":\"True if the interface is supported, false otherwise.\"}},\"transferred(address,address,address,uint256)\":{\"details\":\"Must revert if the transfer is invalid Same name as ERC-3643 but with one supplementary argument `spender` This function can be used to update state variables of the RuleEngine contract This function can be called ONLY by the token contract bound to the RuleEngine Which overload the token calls (since CMTAT v3.3.0): - this 4-argument overload for `transferFrom` (`spender` = approved spender) and for every operation initiated by an operator, with the operator as `spender`: mint (`from == address(0)`), burn (`to == address(0)`), including `burnFrom`, self-burn and cross-chain mint/burn, and the minter `batchTransfer`; - the 3-argument ERC-3643 overload `transferred(from, to, value)`, inherited from {IERC3643IComplianceContract}, only for a direct `transfer`. Up to CMTAT v3.2.0, mint, burn and the minter transfer used the 3-argument overload. WARNING - zero-value calls are permissionless. ERC-20 requires transfers of `0` to be treated as normal transfers, and OpenZeppelin's `_spendAllowance` consumes no allowance when `value == 0`. Any address can therefore call `transferFrom(victim, anyone, 0)` on the token and reach this callback for an arbitrary `from`, with itself as `spender`, without ever having been approved. The token deliberately does not suppress the notification, because doing so would make its compliance notifications inconsistent with its own ERC-20 transfer semantics. Implementations MUST therefore treat `value == 0` as carrying no economic meaning: any stateful rule (cooldown, holding period, quota, tax bucket, counter, holder tracking, ...) MUST be a no-op for a zero value, otherwise an attacker can desynchronize policy state from balances, or keep a holder permanently restricted, at no cost. The same applies to the 3-argument ERC-3643 overload, which a zero-value `transfer(to, 0)` reaches the same way.\",\"params\":{\"from\":\"token holder address\",\"spender\":\"spender address (sender)\",\"to\":\"receiver address\",\"value\":\"value of tokens involved in the transfer; MAY be `0` \\u2014 see the warning above\"}},\"transferred(address,address,uint256)\":{\"details\":\" This function can be used to update state variables of the compliance contract This function can be called ONLY by the token contract bound to the compliance\",\"params\":{\"from\":\"The address of the sender\",\"to\":\"The address of the receiver\",\"value\":\"value of tokens involved in the transfer\"}},\"unbindToken(address)\":{\"details\":\"Authorized by {_authorizeTokenBindingChange}. Operator warning: unbinding is an administrative operation and does not erase any state already stored downstream in a previously shared (\\\"multi-tenant\\\") setup.\",\"params\":{\"token\":\"The address of the token to unbind.\"}},\"unbindTokens(address[])\":{\"details\":\"Must be restricted by implementation-specific access control. Atomic: reverts if any token is not currently bound, and then unbinds none of them. Deliberately not the skip-if-already-done batch convention, for the same reason as {bindTokens}. An empty array is a no-op. Like a manager's {unbindToken}, revokes each token's self-binding approval (see {setTokenSelfBindingApproval}).\",\"params\":{\"tokens\":\"The token addresses to unbind.\"}},\"version()\":{\"details\":\"This value is useful to know which smart contract version has been used\",\"returns\":{\"version_\":\"A string representing the version of the token implementation (e.g., \\\"1.0.0\\\").\"}}},\"title\":\"Implementation of a ruleEngine as defined by the CMTAT, with RBAC access control\",\"version\":1},\"userdoc\":{\"errors\":{\"TokenBinding_InvalidTokenAddress()\":[{\"notice\":\"Thrown when the zero address is passed as a token to bind or to approve.\"}],\"TokenBinding_TokenAlreadyBound()\":[{\"notice\":\"Thrown when binding a token that is already bound.\"}],\"TokenBinding_TokenNotBound()\":[{\"notice\":\"Thrown when unbinding a token that is not currently bound.\"}],\"TokenBinding_UnauthorizedCaller()\":[{\"notice\":\"Thrown when a caller that is not a bound token calls a bound-token entry point.\"}]},\"events\":{\"AddRule(address)\":{\"notice\":\"Emitted when a new rule is added to the rule set.\"},\"ClearRules()\":{\"notice\":\"Emitted when all rules are cleared from the rule set.\"},\"RemoveRule(address)\":{\"notice\":\"Emitted when a rule is removed from the rule set.\"},\"SetMaxRules(uint256)\":{\"notice\":\"Emitted when the maximum allowed number of rules is updated.\"},\"TokenBound(address)\":{\"notice\":\"Emitted when a token is successfully bound.\"},\"TokenSelfBindingApprovalBatchSet(address[],bool)\":{\"notice\":\"Emitted once by {setTokenSelfBindingApprovalBatch}, with the input array.\"},\"TokenSelfBindingApprovalSet(address,bool)\":{\"notice\":\"Emitted by {setTokenSelfBindingApproval} when self-binding permission is set for a token.\"},\"TokenUnbound(address)\":{\"notice\":\"Emitted when a token is successfully unbound.\"}},\"kind\":\"user\",\"methods\":{\"COMPLIANCE_MANAGER_ROLE()\":{\"notice\":\"Role allowed to bind and unbind tokens on the compliance contract.\"},\"DEFAULT_MAX_RULES()\":{\"notice\":\"Default upper bound on the number of rules a RuleEngine may hold.\"},\"RULES_MANAGEMENT_ROLE()\":{\"notice\":\"Role allowed to add, remove, set and clear rules.\"},\"addRule(address)\":{\"notice\":\"Adds a new rule to the current rule set.\"},\"bindToken(address)\":{\"notice\":\"Binds a token contract, allowing it to call the bound-token entry points.\"},\"bindTokens(address[])\":{\"notice\":\"Binds several token contracts in a single call.\"},\"canTransfer(address,address,uint256)\":{\"notice\":\"Returns true if the transfer is valid, and false otherwise.\"},\"canTransferFrom(address,address,address,uint256)\":{\"notice\":\"Checks if `spender` can transfer `value` tokens from `from` to `to` under compliance rules.\"},\"clearRules()\":{\"notice\":\"Removes all configured rules.\"},\"constructor\":{\"notice\":\"Deploys the RBAC RuleEngine, grants the admin role and optionally binds an initial token.\"},\"containsRule(address)\":{\"notice\":\"Checks whether a specific rule is currently configured.\"},\"created(address,uint256)\":{\"notice\":\"Updates the compliance contract state when tokens are created (minted).\"},\"destroyed(address,uint256)\":{\"notice\":\"Updates the compliance contract state when tokens are destroyed (burned).\"},\"detectTransferRestriction(address,address,uint256)\":{\"notice\":\"Queries every rule, in order, and returns the first restriction code that is not zero\"},\"detectTransferRestrictionFrom(address,address,address,uint256)\":{\"notice\":\"Returns a uint8 code to indicate if a transfer is restricted or not\"},\"getTokenBound()\":{\"notice\":\"Returns the single token currently bound to this compliance contract.\"},\"getTokenBounds()\":{\"notice\":\"Returns all tokens currently bound.\"},\"grantRole(bytes32,address)\":{\"notice\":\"Grants `role` to `account`.\"},\"hasRole(bytes32,address)\":{\"notice\":\"Returns `true` if `account` has been granted `role`.\"},\"isTokenBound(address)\":{\"notice\":\"Checks whether a token is currently bound.\"},\"isTokenSelfBindingApproved(address)\":{\"notice\":\"Returns whether a token is approved to bind and unbind itself.\"},\"maxRules()\":{\"notice\":\"Returns the maximum number of rules allowed in the engine.\"},\"removeRule(address)\":{\"notice\":\"Removes a specific rule from the current rule set.\"},\"rule(uint256)\":{\"notice\":\"Retrieves the rule address at a specific index.\"},\"rules()\":{\"notice\":\"Returns the full list of currently configured rules.\"},\"rulesCount()\":{\"notice\":\"Returns the total number of currently configured rules.\"},\"setMaxRules(uint256)\":{\"notice\":\"Updates the maximum number of rules allowed in the engine.\"},\"setRules(address[])\":{\"notice\":\"Defines the rules for the rule engine.\"},\"setTokenSelfBindingApproval(address,bool)\":{\"notice\":\"Sets whether a token is allowed to bind and unbind itself.\"},\"setTokenSelfBindingApprovalBatch(address[],bool)\":{\"notice\":\"Sets self-binding approval for multiple tokens in one transaction.\"},\"supportsInterface(bytes4)\":{\"notice\":\"ERC-165 interface detection.\"},\"transferred(address,address,address,uint256)\":{\"notice\":\"Function called whenever tokens are transferred from one wallet to another, minted or burned, when the token knows the account that initiated the operation (`spender`).\"},\"transferred(address,address,uint256)\":{\"notice\":\"Function called whenever tokens are transferred from one wallet to another\"},\"unbindToken(address)\":{\"notice\":\"Unbinds a token contract, revoking its access to the bound-token entry points.\"},\"unbindTokens(address[])\":{\"notice\":\"Unbinds several token contracts in a single call.\"},\"version()\":{\"notice\":\"Returns the current version of the token contract.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/deployment/accessControl/RuleEngine.sol\":\"RuleEngine\"},\"evmVersion\":\"osaka\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[\":@chainlink/contracts-ccip/=lib/Rules/lib/chainlink-ace/node_modules/@chainlink/contracts-ccip/chains/evm/contracts/\",\":@chainlink/contracts/=lib/Rules/lib/chainlink-ace/node_modules/@chainlink/contracts/\",\":@chainlink/contracts@1.4.0/=lib/Rules/lib/chainlink-doc/node_modules/@chainlink/contracts-1.4.0/\",\":@chainlink/cross-chain-identity/=lib/Rules/lib/chainlink-ace/packages/cross-chain-identity/src/\",\":@chainlink/local/=lib/Rules/lib/chainlink-doc/node_modules/@chainlink/local/\",\":@chainlink/policy-management/=lib/Rules/lib/chainlink-ace/packages/policy-management/src/\",\":@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\":@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\":@openzeppelin/contracts@4.7.3/=lib/Rules/lib/chainlink-doc/node_modules/@openzeppelin/contracts-4.7.3/\",\":@openzeppelin/contracts@4.8.3/=lib/Rules/lib/chainlink-ace/node_modules/@openzeppelin/contracts-4.8.3/\",\":@openzeppelin/contracts@4.9.6/=lib/Rules/lib/chainlink-doc/node_modules/@openzeppelin/contracts-4.9.6/\",\":@openzeppelin/contracts@5.0.2/=lib/Rules/lib/chainlink-ace/node_modules/@openzeppelin/contracts/\",\":@openzeppelin/contracts@5.1.0/=lib/Rules/lib/chainlink-doc/node_modules/@openzeppelin/contracts-5.1.0/\",\":@openzeppelin/contracts@5.3.0/=lib/Rules/lib/chainlink-ace/node_modules/@openzeppelin/contracts-5.3.0/\",\":CMTAT/=lib/CMTAT/contracts/\",\":CMTATv3.0.0/=lib/CMTATv3.0.0/contracts/\",\":ERC-3643/=lib/ERC-3643/contracts/\",\":ERC3643/=lib/Rules/lib/ERC-3643/contracts/\",\":RuleEngine/=lib/Rules/lib/RuleEngine/\",\":Rules/=lib/Rules/\",\":chainlink-ace/=lib/Rules/lib/chainlink-ace/\",\":chainlink-doc/=lib/Rules/lib/\",\":erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/\",\":forge-std/=lib/forge-std/src/\",\":halmos-cheatcodes/=lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/\",\":openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\":openzeppelin-contracts/=lib/openzeppelin-contracts/\"]},\"sources\":{\"lib/CMTAT/contracts/interfaces/engine/IRuleEngine.sol\":{\"keccak256\":\"0xeda899e2e46a9b9c3516acb61a7f7e92ed098928379010655c330da721aaffa7\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://60f8555330fc531dff7d0d71a862696fb286a0ba3290e41efbbbf4dd25947a3c\",\"dweb:/ipfs/QmWvbsBGWPtNMNN2EEedwdzzvQG7NtSj9VD2fmNgqVtCXN\"]},\"lib/CMTAT/contracts/interfaces/technical/IERC5679.sol\":{\"keccak256\":\"0x5bee30750c9a65438469a6c5bd8465e1603eec3aeeb94c07bd64ba3e9ee766e1\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://ef7a5c5f0d47135c97ab5d7456d31e513a71c849ae7f2f5395f860be125c4fbc\",\"dweb:/ipfs/Qmezem3qqSjij6ggyB34wC2S15KrY9fu42oymyS9epAYCQ\"]},\"lib/CMTAT/contracts/interfaces/tokenization/IERC3643Partial.sol\":{\"keccak256\":\"0x5c84c2e2442824e98625c471482fb3c9502f43f4c345e7c0fb07fa549be02e26\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://19071f2d12fb580d37eeee07885461f193568df34f3f69d2c5d65ce655d84435\",\"dweb:/ipfs/QmRqHwC7LksE3YPohMtxFieiPerhWdoDNUUMMLbB4XYvhK\"]},\"lib/CMTAT/contracts/interfaces/tokenization/draft-IERC1404.sol\":{\"keccak256\":\"0xc27cdac182d930a94391d589bdafa15364b6f8d9bf211175781dba661f1c0336\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://b509fa7f3cfd785632569f6ae3bec846aa0beefd73c1d5bde233440cae919f0f\",\"dweb:/ipfs/QmPCAdiEun8gaMqS8KhwPpRZV2zXAPfURRaF4C2KjX5Kby\"]},\"lib/CMTAT/contracts/interfaces/tokenization/draft-IERC7551.sol\":{\"keccak256\":\"0x84b73eb77ec82d6d7b313eff2d87f58d3b795840d004aaa10c611b360b827e30\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://a5b8c99fb3600369065a422d3821ba441dc06fc64f50ce0f33950a76ad82b51b\",\"dweb:/ipfs/QmbviJsZPY3xuLU3cHUWJx11aJCPAuN4WKnCufN4kVLm2U\"]},\"lib/CMTAT/contracts/interfaces/tokenization/draft-IERC7943.sol\":{\"keccak256\":\"0xc69588a72da81057ee278e961e8e3bb61a28d64c3c6cebe494ce00809c1cef15\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://148f117d9c463de441f81e6c0a67e95f1f14a61db209492dd0a1767b5572f21a\",\"dweb:/ipfs/QmUjT5uyJfNSYgUWn5Dxhf6Sx9Y1z8CNf3PuTEaGoAx3za\"]},\"lib/CMTAT/contracts/library/ERC1404ExtendInterfaceId.sol\":{\"keccak256\":\"0xf8268f4eb3a6b2e26c32cf76c5c76b6c17df3385c150f05953538a2472149247\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://05108de7a7ba2a0a67978bdfe8e500360674db6d894f42970bb1016b36639056\",\"dweb:/ipfs/QmRux9Qj1GomATseS6Tyq9uiPPNNipuxg2HjdjnPjgSQds\"]},\"lib/CMTAT/contracts/library/RuleEngineInterfaceId.sol\":{\"keccak256\":\"0x1152a49cba4232d943e295d259eb8a1b216d815067367410a5729a256dae4051\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://470f4435a5e62b0ba0ad70f8657b2db0e4cc3b7f2561772adb944ce010551ee6\",\"dweb:/ipfs/QmXECahRr8rK9XJPZwBCnemLDVPdFvPEBusezhaBqbLBqp\"]},\"lib/openzeppelin-contracts/contracts/access/AccessControl.sol\":{\"keccak256\":\"0xf7e47e67e49ee2a94aa5c52580045b6ec2e6e402d2376c14a75a151664d7c98f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://db6acc2c30f52cb4b5561ffe1db8763200f080c6762db94e4cce0f3623db7080\",\"dweb:/ipfs/QmecnQ1xEh1XMXqVmKZLMkj29iD2y2HJPkZnaYnAe5njFF\"]},\"lib/openzeppelin-contracts/contracts/access/IAccessControl.sol\":{\"keccak256\":\"0xbff9f59c84e5337689161ce7641c0ef8e872d6a7536fbc1f5133f128887aba3c\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://b308f882e796f7b79c9502deacb0a62983035c6f6f4e962b319ba6a1f4a77d3d\",\"dweb:/ipfs/QmaWCW7ahEQqFjwhSUhV7Ae7WhfNvzSpE7DQ58hvEooqPL\"]},\"lib/openzeppelin-contracts/contracts/access/extensions/AccessControlEnumerable.sol\":{\"keccak256\":\"0x90936bbc993aa96f6431bab0e08c9fcd35b1e58e39c188d64064ada6ed1bde03\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c6192bce9a802de36f6e2d852b55d0ef47f3f0a79dbed5d7d8d9c4f28982038c\",\"dweb:/ipfs/QmTsJrPZrQ57HaZapedDBHynNUZxvgEbbddMiDxz2cauLR\"]},\"lib/openzeppelin-contracts/contracts/access/extensions/IAccessControlEnumerable.sol\":{\"keccak256\":\"0xbc97d8c0d67d4d7eba1e662f0a8671712ace9e060ab03af547c4bb321aec1d8c\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://890d156f50630d52c7be57d7e0499132d6fd92b2e1365b81531f4463b3304377\",\"dweb:/ipfs/QmUHe9uL1ciePH2pQg7wdrgTAFRZWjcpBEAg8V1UNtXutd\"]},\"lib/openzeppelin-contracts/contracts/interfaces/IERC165.sol\":{\"keccak256\":\"0x0afcb7e740d1537b252cb2676f600465ce6938398569f09ba1b9ca240dde2dfc\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://1c299900ac4ec268d4570ecef0d697a3013cd11a6eb74e295ee3fbc945056037\",\"dweb:/ipfs/Qmab9owJoxcA7vJT5XNayCMaUR1qxqj1NDzzisduwaJMcZ\"]},\"lib/openzeppelin-contracts/contracts/utils/Arrays.sol\":{\"keccak256\":\"0x772f0c778626a7bdcbcbabca74b825ae9b9dc89d2a47a98b402b1187fbaa63a4\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://eba1d46e58e8880b45c6d51245dc94585b81d6d7290ca77ef50037a6193ed301\",\"dweb:/ipfs/Qme3CWun5qQACjGEerT2MCvhs6brKGFfJirGnzV1ypKTXA\"]},\"lib/openzeppelin-contracts/contracts/utils/Comparators.sol\":{\"keccak256\":\"0x302eecd8cf323b4690e3494a7d960b3cbce077032ab8ef655b323cdd136cec58\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://49ba706f1bc476d68fe6c1fad75517acea4e9e275be0989b548e292eb3a3eacd\",\"dweb:/ipfs/QmeBpvcdGWzWMKTQESUCEhHgnEQYYATVwPxLMxa6vMT7jC\"]},\"lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"keccak256\":\"0x493033a8d1b176a037b2cc6a04dad01a5c157722049bbecf632ca876224dd4b2\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6a708e8a5bdb1011c2c381c9a5cfd8a9a956d7d0a9dc1bd8bcdaf52f76ef2f12\",\"dweb:/ipfs/Qmax9WHBnVsZP46ZxEMNRQpLQnrdE4dK8LehML1Py8FowF\"]},\"lib/openzeppelin-contracts/contracts/utils/Panic.sol\":{\"keccak256\":\"0xf7fe324703a64fc51702311dc51562d5cb1497734f074e4f483bfb6717572d7a\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c6a5ff4f9fd8649b7ee20800b7fa387d3465bd77cf20c2d1068cd5c98e1ed57a\",\"dweb:/ipfs/QmVSaVJf9FXFhdYEYeCEfjMVHrxDh5qL4CGkxdMWpQCrqG\"]},\"lib/openzeppelin-contracts/contracts/utils/SlotDerivation.sol\":{\"keccak256\":\"0x94045fd4f268edf2b2d01ef119268548c320366d6f5294ad30c1b8f9d4f5225f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://edfda81f426f8948b3834115c21e83c48180e6db0d2a8cd2debb2185ed349337\",\"dweb:/ipfs/QmdYZneFyDAux1BuWQxLAdqtABrGS2k9WYCa7C9dvpKkWv\"]},\"lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol\":{\"keccak256\":\"0xcf74f855663ce2ae00ed8352666b7935f6cddea2932fdf2c3ecd30a9b1cd0e97\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://9f660b1f351b757dfe01438e59888f31f33ded3afcf5cb5b0d9bf9aa6f320a8b\",\"dweb:/ipfs/QmarDJ5hZEgBtCmmrVzEZWjub9769eD686jmzb2XpSU1cM\"]},\"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\":{\"keccak256\":\"0x2d9dc2fe26180f74c11c13663647d38e259e45f95eb88f57b61d2160b0109d3e\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://81233d1f98060113d9922180bb0f14f8335856fe9f339134b09335e9f678c377\",\"dweb:/ipfs/QmWh6R35SarhAn4z2wH8SU456jJSYL2FgucfTFgbHJJN4E\"]},\"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165Checker.sol\":{\"keccak256\":\"0x7c7ad70641a7f8cd44def0857ec97b0e40bfd073b2d6037a5f57ce9527ee9bc5\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://e05c6572dfe769f7aea6f3a8002951cc12d143d980dad29f6c5feedf9408bc14\",\"dweb:/ipfs/QmXM7C8YEptxisZiEefXUrwdXt3zMaCobmkCchxTtDg1oK\"]},\"lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"keccak256\":\"0x8891738ffe910f0cf2da09566928589bf5d63f4524dd734fd9cedbac3274dd5c\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://971f954442df5c2ef5b5ebf1eb245d7105d9fbacc7386ee5c796df1d45b21617\",\"dweb:/ipfs/QmadRjHbkicwqwwh61raUEapaVEtaLMcYbQZWs9gUkgj3u\"]},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"keccak256\":\"0x59973a93b1f983f94e10529f46ca46544a9fec2b5f56fb1390bbe9e0dc79f857\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c55ef8f0b9719790c2ae6f81d80a59ffb89f2f0abe6bc065585bd79edce058c5\",\"dweb:/ipfs/QmNNmCbX9NjPXKqHJN8R1WC2rNeZSQrPZLd6FF6AKLyH5Y\"]},\"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\":{\"keccak256\":\"0xc8cae21c9ae4a46e5162ff9bf5b351d6fa6a6eba72d515f3bc1bdfeda7fdf083\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://ce830ebcf28e31643caba318996db3763c36d52cd0f23798ba83c135355d45e9\",\"dweb:/ipfs/QmdGPcvptHN7UBCbUYBbRX3hiRVRFLRwno8b4uga6uFNif\"]},\"lib/openzeppelin-contracts/contracts/utils/structs/EnumerableSet.sol\":{\"keccak256\":\"0xd553ff8b7d55679f0711f1598600ac292dbd8cfdf4b2419b9cabe4c931172895\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://7905ccb27e2308fd0d90dc1212161003ab6964e1c176593db1ccedef705bcc09\",\"dweb:/ipfs/QmW37vm2PcrWLKnN74sKkvAzqSwntCEfCp4EoSEvbBHWkj\"]},\"src/RuleEngineBase.sol\":{\"keccak256\":\"0xb3d832fa55b615574d80b0e0ad76620ad236aa046523617ed5daa46ae07bf853\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://7be31bf5dbd3fa1be025cdc4b7674b76bf40e1c14ce89ec78f792cb3d7ed804e\",\"dweb:/ipfs/QmPq4xBiB3XwXerWtuonZLGiWHMqvz5tKvjhTh9AiWkbww\"]},\"src/deployment/accessControl/RuleEngine.sol\":{\"keccak256\":\"0x003d3c670256396a0ec6369ff8d44ed0a8cf1e371a44494d1d59d24f82854d86\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://9aaeb4f2e3f2b4b8ecaba4adc13c113a87f4a829af47f6d1bafa77e62c27b149\",\"dweb:/ipfs/Qmaqpqc7JwPCEM9xbctor2xPYop5cSKupsbZdp94aYeKVB\"]},\"src/interfaces/IERC3643Compliance.sol\":{\"keccak256\":\"0xd0edd6697d67135853576ac6a40cadaffd787cedea98071708bbfb189c7ee5bc\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://4ed3cd3af64fccff17a1f33989cdfbdacbc0e4f32a56de11a072cf9e2277a1f6\",\"dweb:/ipfs/QmenRqRw1Yy39yDv1pJgBmnHtwuZhDdHE4omchL41CjXjb\"]},\"src/interfaces/IERC3643ComplianceExtended.sol\":{\"keccak256\":\"0x4a43bf330c7a904cba110acf52f519718d8409514c377912d5bd063c9d963729\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://c671879c591760ecbc2691e2f24adfb215a658c9fe6eb0c05dd1ca980054e585\",\"dweb:/ipfs/QmdbA19PFpJgHraF46YrcMNzUgswbTRA92atL2Lha63JLY\"]},\"src/interfaces/IRule.sol\":{\"keccak256\":\"0x81580b67f7be09049aa64d93cc1d8d691a87c639adc1cf169dc6073e1e543a5c\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://6f1808c3ed18ef1acbccdd9b30011b6e7220d388cfd66cba40b1ef0b485306a1\",\"dweb:/ipfs/QmcUCQ5MYcf7KTtoeqMKsTutPPSJhNTaK1ntHV21ioS9Fm\"]},\"src/interfaces/IRulesManagementModule.sol\":{\"keccak256\":\"0x082dd58070e83b02f275584afa872c4583ac4ca8ad12eb329fc11301470147f9\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://e2d0ad78dc323881864f406acd44976f5de39cdc97a6c99a724d8458b993e2e2\",\"dweb:/ipfs/QmRFfMbXbdiAYV3vQyNppXG7tHTji6mV1Y5Cu3ZzEQm5ng\"]},\"src/interfaces/ITokenBinding.sol\":{\"keccak256\":\"0x34dfea4e118c966adf867c0899844515566251819b4e4510fd8ee424555493fd\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://1d054ed49874816688a6e71f76d611bbdefd492d122ae386cb804c6f5af677a7\",\"dweb:/ipfs/QmRaYX4aJWYSNWNa1D4Nich3k7hkGM9rTfc9s2XaVqyRjy\"]},\"src/interfaces/ITokenBindingExtended.sol\":{\"keccak256\":\"0x01f3ab56dffce860d03e72d10e9f2d13b6bfc9004cf058c63a0b23e3b226da99\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://521e0c9651632b70d61c4c3bd0b14c6f05d818166fe65dbed8e3253158b7637e\",\"dweb:/ipfs/QmY2xEVvfV1dgtFYw6coHX3Z7Fm7yRhzPaGyt6cYBMVf76\"]},\"src/modules/ERC3643ComplianceExtendedModule.sol\":{\"keccak256\":\"0x6f808b068517e9e15f09fc6a9d4190001ec8c2314a10e27a85a2d43e44c84fb1\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://c62c0b77fdd8b6e7bf7aa5bf8134a78ff024d6489a23f746874a99df38a8a265\",\"dweb:/ipfs/QmV7PG3ZUUzwDs9tpooC3hmBu5e39buJnJ4TRditojJ3hu\"]},\"src/modules/ERC3643ComplianceModule.sol\":{\"keccak256\":\"0x7cda81af8687328ac2089f9d1d78352e0e75d0f70a4ba8e2b3ac82896f22863f\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://50711cb94d69ea63d787a8bb19c38c0b99539029ec8fb957a8eff00880fc11fc\",\"dweb:/ipfs/QmSapDWh5mpvWn1q6JteZisJfVGPrCz47WP2BBrJCccEjV\"]},\"src/modules/RulesManagementModule.sol\":{\"keccak256\":\"0xe4d9425613284e71a5e3d590d5433167a9751d9496f57efa914baa81f493e66d\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://d07a16e6869df86c526ef89e7e359e34a9553dc4288b262abd2979359ecf720e\",\"dweb:/ipfs/QmRy2JEsyhkv1mxv7eFaSbEWN4A3gtpPSUnnV48W2KiV4u\"]},\"src/modules/TokenBindingExtendedModule.sol\":{\"keccak256\":\"0x4e1ca7b2ec78608c3a7960bec7102a1780bdf3ec7ff544b612bafaf738b34d05\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://657bcdd303fd5a7fbe733b283f69d8e8aa73efeeeaf95c0ae7479769ac573693\",\"dweb:/ipfs/QmXiWPrv8pEqvBQck8jxC7NwB1MUdGQfLjihK6etYcZ54j\"]},\"src/modules/TokenBindingModule.sol\":{\"keccak256\":\"0xf65f46311d0078f60c30e3359dca988e39cba45b9eee53a09d618bfa70e6ef9b\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://e8c458ecfd41df5fb4a391e7ef837fd5ed5c999e61ccc0e6b4bd23023a739832\",\"dweb:/ipfs/Qmdsr765aw9fPFN2M9cSCP69o1o41FNCqhrXjHgEXNwbXV\"]},\"src/modules/VersionModule.sol\":{\"keccak256\":\"0x35daf007be8b9bb1cb9196ae2decb3e5ad4b574f6390f8fc010b78796ac42f73\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://b1b29d75e1c5023a0c6cb8c56638a17d855a3fdc051a60b9d2f304b99f7876d2\",\"dweb:/ipfs/QmXSCVjLuViC8916LwNpKtw8hqyH78Ptag3xH1n7F1fY4g\"]},\"src/modules/library/ComplianceInterfaceId.sol\":{\"keccak256\":\"0xd54bed5328e732f753d2886aeaa2761b2d66536d5247d4548e0ac1c83c7a0dac\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://ad695339fdfe72446a69d2dfbe39373affe2f37299ad921e57016069a7bc3592\",\"dweb:/ipfs/QmWathGt3E85hLfy5rrAYdb291W8VoTa4gpGPoxtWGvNNA\"]},\"src/modules/library/ERC1404InterfaceId.sol\":{\"keccak256\":\"0x07dc6905e137096cd0ae88be29b112d0e54a83ddf8ca527a281718010f6abcce\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://9249dce67cb59432bdbc9e49978c6cac0346cda3d3fca97c5a310e0f424e1600\",\"dweb:/ipfs/QmRi5awH3hjwvd3k3td48y5Cf64n1wvX9wCWy6fQLayuKs\"]},\"src/modules/library/ERC3643ComplianceRolesStorage.sol\":{\"keccak256\":\"0xe422d67495db0f630a49655d5354a9da89707e692824a100527842928db984b8\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://7d310a535b039f6d42e17e3b024841a28f58ca6434cc3555bd5bcbe9a3bb166b\",\"dweb:/ipfs/QmWMMoJngzay4mASYtJSRW6b8Em3bUVWgPca8PLhH9YPVH\"]},\"src/modules/library/RuleEngineInvariantStorage.sol\":{\"keccak256\":\"0x50a212f09f1695662965e5fba643b42a1978bec2a8368abbf43983489c983096\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://6137f01df7630527c985d85d2f7446359c678fcb933b66c55b51f583757b5c4a\",\"dweb:/ipfs/QmeHo47WQm1V99xZHS4soMk68UdtXtZhtWhV3dQC5BtA7u\"]},\"src/modules/library/RuleInterfaceId.sol\":{\"keccak256\":\"0x0d86820eee4c92b21d6704bea8ce7bd2cc1b35f6e4a1ceabbcf2a10f1c6b02ec\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://cfb560cb8588983b8c79a973d03c214a149bf1ac034fa9130ce93f0031a404d7\",\"dweb:/ipfs/Qmc6qt4E4BHdDyLUegCsgxqhf7ZFUiX4ahj8FjM54V7wpY\"]},\"src/modules/library/RulesManagementModuleInvariantStorage.sol\":{\"keccak256\":\"0xb81ea3a54c6e8d47b87d6c3d9fb5aae80c3430021b8cd66d9adeef7f5fc95893\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://cfcbadc2011f60de7189273c278dda1df2218aeeb153bee3b8a93447ec95df21\",\"dweb:/ipfs/Qmem5FqCLEfBJQdJzS7Xzd3zSfyL8Muf9Wv5WvCiBVsqfh\"]},\"src/modules/library/RulesManagementModuleRolesStorage.sol\":{\"keccak256\":\"0xbd4ccff01c8d3e2ffd8cd8e5b095a284ca6563785a683e07fcecd963568203b1\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://784fd4b297baaa29d06ec36bec3b4b391fac7c145840f7e29a5562ebd18374c5\",\"dweb:/ipfs/QmPaBDVnCvYVBVNGcSywdJKfD4Qo9JpGFbqwmc4RjDZy3A\"]},\"src/modules/library/TokenBindingModuleInvariantStorage.sol\":{\"keccak256\":\"0x9bab8e5b265068da356fd46e343a7c6c73776f3964fdeaeff056e8ce104d40a5\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://e2e75d2d52b1e4f5cbb832d194266de9a1b3a8cc2101e875dce43a2664c31a05\",\"dweb:/ipfs/QmUsd5cTPsE89WKm3kTUWsobR9JsBDUY8NdxDU5RPYpvP6\"]}},\"version\":1}","metadata":{"compiler":{"version":"0.8.37+commit.f401782d"},"language":"Solidity","output":{"abi":[{"inputs":[{"internalType":"address","name":"admin","type":"address"},{"internalType":"address","name":"tokenContract","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"type":"error","name":"AccessControlBadConfirmation"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"neededRole","type":"bytes32"}],"type":"error","name":"AccessControlUnauthorizedAccount"},{"inputs":[],"type":"error","name":"RuleEngine_AdminWithAddressZeroNotAllowed"},{"inputs":[],"type":"error","name":"RuleEngine_RuleInvalidInterface"},{"inputs":[],"type":"error","name":"RuleEngine_RulesManagementModule_ArrayIsEmpty"},{"inputs":[{"internalType":"uint256","name":"maxRules","type":"uint256"}],"type":"error","name":"RuleEngine_RulesManagementModule_MaxRulesExceeded"},{"inputs":[],"type":"error","name":"RuleEngine_RulesManagementModule_MaxRulesZeroNotAllowed"},{"inputs":[],"type":"error","name":"RuleEngine_RulesManagementModule_RuleAccountCannotReceivePrivileges"},{"inputs":[],"type":"error","name":"RuleEngine_RulesManagementModule_RuleAddressZeroNotAllowed"},{"inputs":[],"type":"error","name":"RuleEngine_RulesManagementModule_RuleAlreadyExists"},{"inputs":[],"type":"error","name":"RuleEngine_RulesManagementModule_RuleDoNotMatch"},{"inputs":[],"type":"error","name":"TokenBinding_InvalidTokenAddress"},{"inputs":[],"type":"error","name":"TokenBinding_TokenAlreadyBound"},{"inputs":[],"type":"error","name":"TokenBinding_TokenNotBound"},{"inputs":[],"type":"error","name":"TokenBinding_UnauthorizedCaller"},{"inputs":[{"internalType":"contract IRule","name":"rule","type":"address","indexed":true}],"type":"event","name":"AddRule","anonymous":false},{"inputs":[],"type":"event","name":"ClearRules","anonymous":false},{"inputs":[{"internalType":"contract IRule","name":"rule","type":"address","indexed":true}],"type":"event","name":"RemoveRule","anonymous":false},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32","indexed":true},{"internalType":"bytes32","name":"previousAdminRole","type":"bytes32","indexed":true},{"internalType":"bytes32","name":"newAdminRole","type":"bytes32","indexed":true}],"type":"event","name":"RoleAdminChanged","anonymous":false},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32","indexed":true},{"internalType":"address","name":"account","type":"address","indexed":true},{"internalType":"address","name":"sender","type":"address","indexed":true}],"type":"event","name":"RoleGranted","anonymous":false},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32","indexed":true},{"internalType":"address","name":"account","type":"address","indexed":true},{"internalType":"address","name":"sender","type":"address","indexed":true}],"type":"event","name":"RoleRevoked","anonymous":false},{"inputs":[{"internalType":"uint256","name":"maxRules","type":"uint256","indexed":false}],"type":"event","name":"SetMaxRules","anonymous":false},{"inputs":[{"internalType":"address","name":"token","type":"address","indexed":false}],"type":"event","name":"TokenBound","anonymous":false},{"inputs":[{"internalType":"address[]","name":"tokens","type":"address[]","indexed":false},{"internalType":"bool","name":"approved","type":"bool","indexed":false}],"type":"event","name":"TokenSelfBindingApprovalBatchSet","anonymous":false},{"inputs":[{"internalType":"address","name":"token","type":"address","indexed":true},{"internalType":"bool","name":"approved","type":"bool","indexed":false}],"type":"event","name":"TokenSelfBindingApprovalSet","anonymous":false},{"inputs":[{"internalType":"address","name":"token","type":"address","indexed":false}],"type":"event","name":"TokenUnbound","anonymous":false},{"inputs":[],"stateMutability":"view","type":"function","name":"COMPLIANCE_MANAGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"DEFAULT_MAX_RULES","outputs":[{"internalType":"uint256","name":"","type":"uint256"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"RULES_MANAGEMENT_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}]},{"inputs":[{"internalType":"contract IRule","name":"rule_","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"addRule"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"bindToken"},{"inputs":[{"internalType":"address[]","name":"tokens","type":"address[]"}],"stateMutability":"nonpayable","type":"function","name":"bindTokens"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"view","type":"function","name":"canTransfer","outputs":[{"internalType":"bool","name":"","type":"bool"}]},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"view","type":"function","name":"canTransferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}]},{"inputs":[],"stateMutability":"nonpayable","type":"function","name":"clearRules"},{"inputs":[{"internalType":"contract IRule","name":"rule_","type":"address"}],"stateMutability":"view","type":"function","name":"containsRule","outputs":[{"internalType":"bool","name":"","type":"bool"}]},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"nonpayable","type":"function","name":"created"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"nonpayable","type":"function","name":"destroyed"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"view","type":"function","name":"detectTransferRestriction","outputs":[{"internalType":"uint8","name":"","type":"uint8"}]},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"view","type":"function","name":"detectTransferRestrictionFrom","outputs":[{"internalType":"uint8","name":"","type":"uint8"}]},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"stateMutability":"view","type":"function","name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}]},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"stateMutability":"view","type":"function","name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}]},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"stateMutability":"view","type":"function","name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}]},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"stateMutability":"view","type":"function","name":"getRoleMembers","outputs":[{"internalType":"address[]","name":"","type":"address[]"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"getTokenBound","outputs":[{"internalType":"address","name":"","type":"address"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"getTokenBounds","outputs":[{"internalType":"address[]","name":"","type":"address[]"}]},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"grantRole"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"stateMutability":"view","type":"function","name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}]},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"stateMutability":"view","type":"function","name":"isTokenBound","outputs":[{"internalType":"bool","name":"","type":"bool"}]},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"stateMutability":"view","type":"function","name":"isTokenSelfBindingApproved","outputs":[{"internalType":"bool","name":"","type":"bool"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"maxRules","outputs":[{"internalType":"uint256","name":"","type":"uint256"}]},{"inputs":[{"internalType":"uint8","name":"restrictionCode","type":"uint8"}],"stateMutability":"view","type":"function","name":"messageForTransferRestriction","outputs":[{"internalType":"string","name":"","type":"string"}]},{"inputs":[{"internalType":"contract IRule","name":"rule_","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"removeRule"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"callerConfirmation","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"renounceRole"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"revokeRole"},{"inputs":[{"internalType":"uint256","name":"ruleId","type":"uint256"}],"stateMutability":"view","type":"function","name":"rule","outputs":[{"internalType":"address","name":"","type":"address"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"rules","outputs":[{"internalType":"address[]","name":"","type":"address[]"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"rulesCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}]},{"inputs":[{"internalType":"uint256","name":"maxRules_","type":"uint256"}],"stateMutability":"nonpayable","type":"function","name":"setMaxRules"},{"inputs":[{"internalType":"contract IRule[]","name":"rules_","type":"address[]"}],"stateMutability":"nonpayable","type":"function","name":"setRules"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"stateMutability":"nonpayable","type":"function","name":"setTokenSelfBindingApproval"},{"inputs":[{"internalType":"address[]","name":"tokens","type":"address[]"},{"internalType":"bool","name":"approved","type":"bool"}],"stateMutability":"nonpayable","type":"function","name":"setTokenSelfBindingApprovalBatch"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"stateMutability":"view","type":"function","name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}]},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"nonpayable","type":"function","name":"transferred"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"nonpayable","type":"function","name":"transferred"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"unbindToken"},{"inputs":[{"internalType":"address[]","name":"tokens","type":"address[]"}],"stateMutability":"nonpayable","type":"function","name":"unbindTokens"},{"inputs":[],"stateMutability":"view","type":"function","name":"version","outputs":[{"internalType":"string","name":"version_","type":"string"}]}],"devdoc":{"kind":"dev","methods":{"addRule(address)":{"details":"Reverts when the configured maximum number of rules is already reached. Security convention: do not grant {RULES_MANAGEMENT_ROLE} to rule contracts.","params":{"rule_":"The IRule contract to add."}},"bindToken(address)":{"custom:security-note":"\"Multi-tenant\" means one instance is shared by multiple token contracts. Downstream state (for the RuleEngine: the per-address accounting held by stateful rules) is shared across all bound tokens, so binding tokens from different issuers silently cross-contaminates it. Only bind tokens that are equally trusted and governed together.","details":"Authorized by {_authorizeTokenBindingChange}.","params":{"token":"The address of the token to bind."}},"bindTokens(address[])":{"custom:security-note":"See {bindToken} for multi-tenant state risks. All tokens bound in this batch share the same downstream state. Only bind tokens that are equally trusted and governed together.","details":"Must be restricted by implementation-specific access control. Atomic: reverts if any token is invalid or already bound (or listed twice), and then binds none of them. This deliberately departs from the usual batch convention of skipping elements already in the target state: a binding change is security-relevant, and a token that is already bound in the list is most likely an operator mistake that should stop the whole operation. An empty array is a no-op.","params":{"tokens":"The token addresses to bind."}},"canTransfer(address,address,uint256)":{"details":"Don't check the balance and the user's right (access control)","params":{"from":"The address sending tokens.","to":"The address receiving tokens.","value":"The amount of tokens to transfer."},"returns":{"_0":"True if the transfer is valid, false otherwise."}},"canTransferFrom(address,address,address,uint256)":{"details":"Does not check balances or access rights (Access Control).","params":{"from":"The source address.","spender":"The address performing the transfer.","to":"The destination address.","value":"The number of tokens to transfer."},"returns":{"_0":"isCompliant True if the transfer complies with policy."}},"clearRules()":{"details":"After calling this function, no rules will remain set. Cost is O(n) in the number of configured rules. With the default cap of 10 this is negligible, but a high {maxRules} setting re-exposes unbounded cost here even though per-transfer cost remains bounded."},"constructor":{"params":{"admin":"Address receiving `DEFAULT_ADMIN_ROLE`; must not be the zero address.","tokenContract":"Token to bind at deployment, or the zero address to bind none."}},"containsRule(address)":{"details":"Complexity: O(1).","params":{"rule_":"The IRule contract to check for membership."},"returns":{"_0":"True if the rule is present, false otherwise."}},"created(address,uint256)":{"details":"Called by the token contract when new tokens are issued to an account. Reverts if the minting does not comply with the rules.","params":{"to":"The address receiving the minted tokens.","value":"The number of tokens created."}},"destroyed(address,uint256)":{"details":"Called by the token contract when tokens are redeemed or burned. Reverts if the burning does not comply with the rules.","params":{"from":"The address whose tokens are being destroyed.","value":"The number of tokens destroyed."}},"detectTransferRestriction(address,address,uint256)":{"params":{"from":"the origin address","to":"the destination address","value":"to transfer"},"returns":{"_0":"The restriction code or REJECTED_CODE_BASE.TRANSFER_OK (0) if the transfer is valid"}},"detectTransferRestrictionFrom(address,address,address,uint256)":{"details":" See {ERC-1404} Add an additionnal argument `spender` This function is where an issuer enforces the restriction logic of their token transfers. Some examples of this might include: - checking if the token recipient is whitelisted, - checking if a sender's tokens are frozen in a lock-up period, etc.","params":{"from":"The address sending tokens.","spender":"The address initiating the delegated transfer.","to":"The address receiving tokens.","value":"amount of tokens to transfer"},"returns":{"_0":"uint8 restricted code, 0 means the transfer is authorized"}},"getRoleAdmin(bytes32)":{"details":"Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}."},"getRoleMember(bytes32,uint256)":{"details":"Returns one of the accounts that have `role`. `index` must be a value between 0 and {getRoleMemberCount}, non-inclusive. Role bearers are not sorted in any particular way, and their ordering may change at any point. WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure you perform all queries on the same block. See the following https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] for more information."},"getRoleMemberCount(bytes32)":{"details":"Returns the number of accounts that have `role`. Can be used together with {getRoleMember} to enumerate all bearers of a role."},"getRoleMembers(bytes32)":{"details":"Return all accounts that have `role` WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that this function has an unbounded cost, and using it as part of a state-changing function may render the function uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block."},"getTokenBound()":{"details":"If multiple tokens are supported, consider using getTokenBounds().","returns":{"_0":"The address of the currently bound token."}},"getTokenBounds()":{"details":"This operation copies the entire storage set to memory and is mainly intended for off-chain reads.","returns":{"_0":"An array of bound token addresses."}},"grantRole(bytes32,address)":{"details":"Prevents granting any role to accounts currently configured as rules. Note: this check is intentionally one-directional. {addRule} does not verify whether the rule address already holds a privileged role, and this function does not prevent adding a privileged address as a rule afterwards. Operators are responsible for keeping rule contracts and privileged accounts disjoint.","params":{"account":"The account receiving the role.","role":"The role identifier to grant."}},"hasRole(bytes32,address)":{"details":"The Default Admin has all roles","params":{"account":"The account to check.","role":"The role identifier to check."},"returns":{"_0":"True if the account holds the role (or is the default admin), false otherwise."}},"isTokenBound(address)":{"details":"Complexity: O(1).","params":{"token":"The token address to verify."},"returns":{"_0":"True if the token is bound, false otherwise."}},"isTokenSelfBindingApproved(address)":{"params":{"token":"The token address to query."},"returns":{"_0":"True if self-binding is approved for `token`, false otherwise."}},"maxRules()":{"returns":{"_0":"The maximum number of rules that can be configured."}},"messageForTransferRestriction(uint8)":{"details":"See {ERC-1404} This function is effectively an accessor for the \"message\", a human-readable explanation as to why a transaction is restricted.","params":{"restrictionCode":"The restriction code to translate into a message."},"returns":{"_0":"The human-readable message corresponding to `restrictionCode`."}},"removeRule(address)":{"details":"Reverts if the provided rule is not found or does not match the stored rule at its index. Complexity: O(1).","params":{"rule_":"The IRule contract to remove."}},"renounceRole(bytes32,address)":{"details":"Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). Emits a {RoleRevoked} event if the calling account had `role` and this call successfully revoked it. Requirements: - the caller must be `callerConfirmation`. May emit a {RoleRevoked} event."},"revokeRole(bytes32,address)":{"details":"Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleRevoked} event."},"rule(uint256)":{"details":"Reverts if `ruleId` is out of bounds. Complexity: O(1). Note that there are no guarantees on the ordering of values inside the array, and it may change when more values are added or removed.","params":{"ruleId":"The index of the desired rule in the array."},"returns":{"_0":"The address of the corresponding IRule contract, return the `zero address` is out of bounds."}},"rules()":{"details":"This is a view-only function that does not modify state. This operation will copy the entire storage to memory, which can be quite expensive. This is designed to mostly be used by view accessors that are queried without any gas fees.","returns":{"_0":"An array of all active rule contract addresses."}},"rulesCount()":{"details":"Equivalent to the length of the internal rules array. Complexity: O(1)","returns":{"_0":"The number of active rules."}},"setMaxRules(uint256)":{"details":"Access control is implementation specific (admin/owner). Setting a very high cap re-exposes unbounded gas cost for administrative operations such as {clearRules} even though normal per-transfer cost remains bounded.","params":{"maxRules_":"New maximum number of rules."}},"setRules(address[])":{"details":"Replaces the entire rule set atomically. Reverts if `rules_` is empty. Use {clearRules} to remove all rules explicitly. To transition from one non-empty set to another without an enforcement gap, call this function directly with the new set. Emits {ClearRules} when the existing rule set is non-empty, then emits {AddRule} for each new rule. Off-chain indexers must handle both events to reconstruct state. Security convention: rule contracts should be treated as trusted business logic, but should not also be granted {RULES_MANAGEMENT_ROLE}.","params":{"rules_":"The array of addresses representing the new rules to be set."}},"setTokenSelfBindingApproval(address,bool)":{"details":"Must be restricted by implementation-specific access control. An approval stays in force until it is revoked here or until the binding manager unbinds the token ({unbindToken} or {unbindTokens}), which revokes it and emits {TokenSelfBindingApprovalSet} with `false`. A token that unbinds itself keeps its approval, so it can bind itself again later.","params":{"approved":"Whether self-binding is approved for `token`.","token":"The token address to configure."}},"setTokenSelfBindingApprovalBatch(address[],bool)":{"details":"Must be restricted by implementation-specific access control. Reverts if any token in `tokens` is the zero address. Emits a single {TokenSelfBindingApprovalBatchSet} with the input array, not one {TokenSelfBindingApprovalSet} per token.","params":{"approved":"Whether self-binding is approved for all provided tokens.","tokens":"The token addresses to configure."}},"supportsInterface(bytes4)":{"params":{"interfaceId":"The interface identifier to check."},"returns":{"_0":"True if the interface is supported, false otherwise."}},"transferred(address,address,address,uint256)":{"details":"Must revert if the transfer is invalid Same name as ERC-3643 but with one supplementary argument `spender` This function can be used to update state variables of the RuleEngine contract This function can be called ONLY by the token contract bound to the RuleEngine Which overload the token calls (since CMTAT v3.3.0): - this 4-argument overload for `transferFrom` (`spender` = approved spender) and for every operation initiated by an operator, with the operator as `spender`: mint (`from == address(0)`), burn (`to == address(0)`), including `burnFrom`, self-burn and cross-chain mint/burn, and the minter `batchTransfer`; - the 3-argument ERC-3643 overload `transferred(from, to, value)`, inherited from {IERC3643IComplianceContract}, only for a direct `transfer`. Up to CMTAT v3.2.0, mint, burn and the minter transfer used the 3-argument overload. WARNING - zero-value calls are permissionless. ERC-20 requires transfers of `0` to be treated as normal transfers, and OpenZeppelin's `_spendAllowance` consumes no allowance when `value == 0`. Any address can therefore call `transferFrom(victim, anyone, 0)` on the token and reach this callback for an arbitrary `from`, with itself as `spender`, without ever having been approved. The token deliberately does not suppress the notification, because doing so would make its compliance notifications inconsistent with its own ERC-20 transfer semantics. Implementations MUST therefore treat `value == 0` as carrying no economic meaning: any stateful rule (cooldown, holding period, quota, tax bucket, counter, holder tracking, ...) MUST be a no-op for a zero value, otherwise an attacker can desynchronize policy state from balances, or keep a holder permanently restricted, at no cost. The same applies to the 3-argument ERC-3643 overload, which a zero-value `transfer(to, 0)` reaches the same way.","params":{"from":"token holder address","spender":"spender address (sender)","to":"receiver address","value":"value of tokens involved in the transfer; MAY be `0` — see the warning above"}},"transferred(address,address,uint256)":{"details":" This function can be used to update state variables of the compliance contract This function can be called ONLY by the token contract bound to the compliance","params":{"from":"The address of the sender","to":"The address of the receiver","value":"value of tokens involved in the transfer"}},"unbindToken(address)":{"details":"Authorized by {_authorizeTokenBindingChange}. Operator warning: unbinding is an administrative operation and does not erase any state already stored downstream in a previously shared (\"multi-tenant\") setup.","params":{"token":"The address of the token to unbind."}},"unbindTokens(address[])":{"details":"Must be restricted by implementation-specific access control. Atomic: reverts if any token is not currently bound, and then unbinds none of them. Deliberately not the skip-if-already-done batch convention, for the same reason as {bindTokens}. An empty array is a no-op. Like a manager's {unbindToken}, revokes each token's self-binding approval (see {setTokenSelfBindingApproval}).","params":{"tokens":"The token addresses to unbind."}},"version()":{"details":"This value is useful to know which smart contract version has been used","returns":{"version_":"A string representing the version of the token implementation (e.g., \"1.0.0\")."}}},"version":1},"userdoc":{"kind":"user","methods":{"COMPLIANCE_MANAGER_ROLE()":{"notice":"Role allowed to bind and unbind tokens on the compliance contract."},"DEFAULT_MAX_RULES()":{"notice":"Default upper bound on the number of rules a RuleEngine may hold."},"RULES_MANAGEMENT_ROLE()":{"notice":"Role allowed to add, remove, set and clear rules."},"addRule(address)":{"notice":"Adds a new rule to the current rule set."},"bindToken(address)":{"notice":"Binds a token contract, allowing it to call the bound-token entry points."},"bindTokens(address[])":{"notice":"Binds several token contracts in a single call."},"canTransfer(address,address,uint256)":{"notice":"Returns true if the transfer is valid, and false otherwise."},"canTransferFrom(address,address,address,uint256)":{"notice":"Checks if `spender` can transfer `value` tokens from `from` to `to` under compliance rules."},"clearRules()":{"notice":"Removes all configured rules."},"constructor":{"notice":"Deploys the RBAC RuleEngine, grants the admin role and optionally binds an initial token."},"containsRule(address)":{"notice":"Checks whether a specific rule is currently configured."},"created(address,uint256)":{"notice":"Updates the compliance contract state when tokens are created (minted)."},"destroyed(address,uint256)":{"notice":"Updates the compliance contract state when tokens are destroyed (burned)."},"detectTransferRestriction(address,address,uint256)":{"notice":"Queries every rule, in order, and returns the first restriction code that is not zero"},"detectTransferRestrictionFrom(address,address,address,uint256)":{"notice":"Returns a uint8 code to indicate if a transfer is restricted or not"},"getTokenBound()":{"notice":"Returns the single token currently bound to this compliance contract."},"getTokenBounds()":{"notice":"Returns all tokens currently bound."},"grantRole(bytes32,address)":{"notice":"Grants `role` to `account`."},"hasRole(bytes32,address)":{"notice":"Returns `true` if `account` has been granted `role`."},"isTokenBound(address)":{"notice":"Checks whether a token is currently bound."},"isTokenSelfBindingApproved(address)":{"notice":"Returns whether a token is approved to bind and unbind itself."},"maxRules()":{"notice":"Returns the maximum number of rules allowed in the engine."},"removeRule(address)":{"notice":"Removes a specific rule from the current rule set."},"rule(uint256)":{"notice":"Retrieves the rule address at a specific index."},"rules()":{"notice":"Returns the full list of currently configured rules."},"rulesCount()":{"notice":"Returns the total number of currently configured rules."},"setMaxRules(uint256)":{"notice":"Updates the maximum number of rules allowed in the engine."},"setRules(address[])":{"notice":"Defines the rules for the rule engine."},"setTokenSelfBindingApproval(address,bool)":{"notice":"Sets whether a token is allowed to bind and unbind itself."},"setTokenSelfBindingApprovalBatch(address[],bool)":{"notice":"Sets self-binding approval for multiple tokens in one transaction."},"supportsInterface(bytes4)":{"notice":"ERC-165 interface detection."},"transferred(address,address,address,uint256)":{"notice":"Function called whenever tokens are transferred from one wallet to another, minted or burned, when the token knows the account that initiated the operation (`spender`)."},"transferred(address,address,uint256)":{"notice":"Function called whenever tokens are transferred from one wallet to another"},"unbindToken(address)":{"notice":"Unbinds a token contract, revoking its access to the bound-token entry points."},"unbindTokens(address[])":{"notice":"Unbinds several token contracts in a single call."},"version()":{"notice":"Returns the current version of the token contract."}},"version":1}},"settings":{"remappings":["@chainlink/contracts-ccip/=lib/Rules/lib/chainlink-ace/node_modules/@chainlink/contracts-ccip/chains/evm/contracts/","@chainlink/contracts/=lib/Rules/lib/chainlink-ace/node_modules/@chainlink/contracts/","@chainlink/contracts@1.4.0/=lib/Rules/lib/chainlink-doc/node_modules/@chainlink/contracts-1.4.0/","@chainlink/cross-chain-identity/=lib/Rules/lib/chainlink-ace/packages/cross-chain-identity/src/","@chainlink/local/=lib/Rules/lib/chainlink-doc/node_modules/@chainlink/local/","@chainlink/policy-management/=lib/Rules/lib/chainlink-ace/packages/policy-management/src/","@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/","@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/","@openzeppelin/contracts@4.7.3/=lib/Rules/lib/chainlink-doc/node_modules/@openzeppelin/contracts-4.7.3/","@openzeppelin/contracts@4.8.3/=lib/Rules/lib/chainlink-ace/node_modules/@openzeppelin/contracts-4.8.3/","@openzeppelin/contracts@4.9.6/=lib/Rules/lib/chainlink-doc/node_modules/@openzeppelin/contracts-4.9.6/","@openzeppelin/contracts@5.0.2/=lib/Rules/lib/chainlink-ace/node_modules/@openzeppelin/contracts/","@openzeppelin/contracts@5.1.0/=lib/Rules/lib/chainlink-doc/node_modules/@openzeppelin/contracts-5.1.0/","@openzeppelin/contracts@5.3.0/=lib/Rules/lib/chainlink-ace/node_modules/@openzeppelin/contracts-5.3.0/","CMTAT/=lib/CMTAT/contracts/","CMTATv3.0.0/=lib/CMTATv3.0.0/contracts/","ERC-3643/=lib/ERC-3643/contracts/","ERC3643/=lib/Rules/lib/ERC-3643/contracts/","RuleEngine/=lib/Rules/lib/RuleEngine/","Rules/=lib/Rules/","chainlink-ace/=lib/Rules/lib/chainlink-ace/","chainlink-doc/=lib/Rules/lib/","erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/","forge-std/=lib/forge-std/src/","halmos-cheatcodes/=lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/","openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/","openzeppelin-contracts/=lib/openzeppelin-contracts/"],"optimizer":{"enabled":true,"runs":200},"metadata":{"bytecodeHash":"ipfs"},"compilationTarget":{"src/deployment/accessControl/RuleEngine.sol":"RuleEngine"},"evmVersion":"osaka","libraries":{}},"sources":{"lib/CMTAT/contracts/interfaces/engine/IRuleEngine.sol":{"keccak256":"0xeda899e2e46a9b9c3516acb61a7f7e92ed098928379010655c330da721aaffa7","urls":["bzz-raw://60f8555330fc531dff7d0d71a862696fb286a0ba3290e41efbbbf4dd25947a3c","dweb:/ipfs/QmWvbsBGWPtNMNN2EEedwdzzvQG7NtSj9VD2fmNgqVtCXN"],"license":"MPL-2.0"},"lib/CMTAT/contracts/interfaces/technical/IERC5679.sol":{"keccak256":"0x5bee30750c9a65438469a6c5bd8465e1603eec3aeeb94c07bd64ba3e9ee766e1","urls":["bzz-raw://ef7a5c5f0d47135c97ab5d7456d31e513a71c849ae7f2f5395f860be125c4fbc","dweb:/ipfs/Qmezem3qqSjij6ggyB34wC2S15KrY9fu42oymyS9epAYCQ"],"license":"MPL-2.0"},"lib/CMTAT/contracts/interfaces/tokenization/IERC3643Partial.sol":{"keccak256":"0x5c84c2e2442824e98625c471482fb3c9502f43f4c345e7c0fb07fa549be02e26","urls":["bzz-raw://19071f2d12fb580d37eeee07885461f193568df34f3f69d2c5d65ce655d84435","dweb:/ipfs/QmRqHwC7LksE3YPohMtxFieiPerhWdoDNUUMMLbB4XYvhK"],"license":"MPL-2.0"},"lib/CMTAT/contracts/interfaces/tokenization/draft-IERC1404.sol":{"keccak256":"0xc27cdac182d930a94391d589bdafa15364b6f8d9bf211175781dba661f1c0336","urls":["bzz-raw://b509fa7f3cfd785632569f6ae3bec846aa0beefd73c1d5bde233440cae919f0f","dweb:/ipfs/QmPCAdiEun8gaMqS8KhwPpRZV2zXAPfURRaF4C2KjX5Kby"],"license":"MPL-2.0"},"lib/CMTAT/contracts/interfaces/tokenization/draft-IERC7551.sol":{"keccak256":"0x84b73eb77ec82d6d7b313eff2d87f58d3b795840d004aaa10c611b360b827e30","urls":["bzz-raw://a5b8c99fb3600369065a422d3821ba441dc06fc64f50ce0f33950a76ad82b51b","dweb:/ipfs/QmbviJsZPY3xuLU3cHUWJx11aJCPAuN4WKnCufN4kVLm2U"],"license":"MPL-2.0"},"lib/CMTAT/contracts/interfaces/tokenization/draft-IERC7943.sol":{"keccak256":"0xc69588a72da81057ee278e961e8e3bb61a28d64c3c6cebe494ce00809c1cef15","urls":["bzz-raw://148f117d9c463de441f81e6c0a67e95f1f14a61db209492dd0a1767b5572f21a","dweb:/ipfs/QmUjT5uyJfNSYgUWn5Dxhf6Sx9Y1z8CNf3PuTEaGoAx3za"],"license":"MPL-2.0"},"lib/CMTAT/contracts/library/ERC1404ExtendInterfaceId.sol":{"keccak256":"0xf8268f4eb3a6b2e26c32cf76c5c76b6c17df3385c150f05953538a2472149247","urls":["bzz-raw://05108de7a7ba2a0a67978bdfe8e500360674db6d894f42970bb1016b36639056","dweb:/ipfs/QmRux9Qj1GomATseS6Tyq9uiPPNNipuxg2HjdjnPjgSQds"],"license":"MPL-2.0"},"lib/CMTAT/contracts/library/RuleEngineInterfaceId.sol":{"keccak256":"0x1152a49cba4232d943e295d259eb8a1b216d815067367410a5729a256dae4051","urls":["bzz-raw://470f4435a5e62b0ba0ad70f8657b2db0e4cc3b7f2561772adb944ce010551ee6","dweb:/ipfs/QmXECahRr8rK9XJPZwBCnemLDVPdFvPEBusezhaBqbLBqp"],"license":"MPL-2.0"},"lib/openzeppelin-contracts/contracts/access/AccessControl.sol":{"keccak256":"0xf7e47e67e49ee2a94aa5c52580045b6ec2e6e402d2376c14a75a151664d7c98f","urls":["bzz-raw://db6acc2c30f52cb4b5561ffe1db8763200f080c6762db94e4cce0f3623db7080","dweb:/ipfs/QmecnQ1xEh1XMXqVmKZLMkj29iD2y2HJPkZnaYnAe5njFF"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/access/IAccessControl.sol":{"keccak256":"0xbff9f59c84e5337689161ce7641c0ef8e872d6a7536fbc1f5133f128887aba3c","urls":["bzz-raw://b308f882e796f7b79c9502deacb0a62983035c6f6f4e962b319ba6a1f4a77d3d","dweb:/ipfs/QmaWCW7ahEQqFjwhSUhV7Ae7WhfNvzSpE7DQ58hvEooqPL"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/access/extensions/AccessControlEnumerable.sol":{"keccak256":"0x90936bbc993aa96f6431bab0e08c9fcd35b1e58e39c188d64064ada6ed1bde03","urls":["bzz-raw://c6192bce9a802de36f6e2d852b55d0ef47f3f0a79dbed5d7d8d9c4f28982038c","dweb:/ipfs/QmTsJrPZrQ57HaZapedDBHynNUZxvgEbbddMiDxz2cauLR"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/access/extensions/IAccessControlEnumerable.sol":{"keccak256":"0xbc97d8c0d67d4d7eba1e662f0a8671712ace9e060ab03af547c4bb321aec1d8c","urls":["bzz-raw://890d156f50630d52c7be57d7e0499132d6fd92b2e1365b81531f4463b3304377","dweb:/ipfs/QmUHe9uL1ciePH2pQg7wdrgTAFRZWjcpBEAg8V1UNtXutd"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/interfaces/IERC165.sol":{"keccak256":"0x0afcb7e740d1537b252cb2676f600465ce6938398569f09ba1b9ca240dde2dfc","urls":["bzz-raw://1c299900ac4ec268d4570ecef0d697a3013cd11a6eb74e295ee3fbc945056037","dweb:/ipfs/Qmab9owJoxcA7vJT5XNayCMaUR1qxqj1NDzzisduwaJMcZ"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/Arrays.sol":{"keccak256":"0x772f0c778626a7bdcbcbabca74b825ae9b9dc89d2a47a98b402b1187fbaa63a4","urls":["bzz-raw://eba1d46e58e8880b45c6d51245dc94585b81d6d7290ca77ef50037a6193ed301","dweb:/ipfs/Qme3CWun5qQACjGEerT2MCvhs6brKGFfJirGnzV1ypKTXA"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/Comparators.sol":{"keccak256":"0x302eecd8cf323b4690e3494a7d960b3cbce077032ab8ef655b323cdd136cec58","urls":["bzz-raw://49ba706f1bc476d68fe6c1fad75517acea4e9e275be0989b548e292eb3a3eacd","dweb:/ipfs/QmeBpvcdGWzWMKTQESUCEhHgnEQYYATVwPxLMxa6vMT7jC"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/Context.sol":{"keccak256":"0x493033a8d1b176a037b2cc6a04dad01a5c157722049bbecf632ca876224dd4b2","urls":["bzz-raw://6a708e8a5bdb1011c2c381c9a5cfd8a9a956d7d0a9dc1bd8bcdaf52f76ef2f12","dweb:/ipfs/Qmax9WHBnVsZP46ZxEMNRQpLQnrdE4dK8LehML1Py8FowF"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/Panic.sol":{"keccak256":"0xf7fe324703a64fc51702311dc51562d5cb1497734f074e4f483bfb6717572d7a","urls":["bzz-raw://c6a5ff4f9fd8649b7ee20800b7fa387d3465bd77cf20c2d1068cd5c98e1ed57a","dweb:/ipfs/QmVSaVJf9FXFhdYEYeCEfjMVHrxDh5qL4CGkxdMWpQCrqG"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/SlotDerivation.sol":{"keccak256":"0x94045fd4f268edf2b2d01ef119268548c320366d6f5294ad30c1b8f9d4f5225f","urls":["bzz-raw://edfda81f426f8948b3834115c21e83c48180e6db0d2a8cd2debb2185ed349337","dweb:/ipfs/QmdYZneFyDAux1BuWQxLAdqtABrGS2k9WYCa7C9dvpKkWv"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol":{"keccak256":"0xcf74f855663ce2ae00ed8352666b7935f6cddea2932fdf2c3ecd30a9b1cd0e97","urls":["bzz-raw://9f660b1f351b757dfe01438e59888f31f33ded3afcf5cb5b0d9bf9aa6f320a8b","dweb:/ipfs/QmarDJ5hZEgBtCmmrVzEZWjub9769eD686jmzb2XpSU1cM"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol":{"keccak256":"0x2d9dc2fe26180f74c11c13663647d38e259e45f95eb88f57b61d2160b0109d3e","urls":["bzz-raw://81233d1f98060113d9922180bb0f14f8335856fe9f339134b09335e9f678c377","dweb:/ipfs/QmWh6R35SarhAn4z2wH8SU456jJSYL2FgucfTFgbHJJN4E"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165Checker.sol":{"keccak256":"0x7c7ad70641a7f8cd44def0857ec97b0e40bfd073b2d6037a5f57ce9527ee9bc5","urls":["bzz-raw://e05c6572dfe769f7aea6f3a8002951cc12d143d980dad29f6c5feedf9408bc14","dweb:/ipfs/QmXM7C8YEptxisZiEefXUrwdXt3zMaCobmkCchxTtDg1oK"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol":{"keccak256":"0x8891738ffe910f0cf2da09566928589bf5d63f4524dd734fd9cedbac3274dd5c","urls":["bzz-raw://971f954442df5c2ef5b5ebf1eb245d7105d9fbacc7386ee5c796df1d45b21617","dweb:/ipfs/QmadRjHbkicwqwwh61raUEapaVEtaLMcYbQZWs9gUkgj3u"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/math/Math.sol":{"keccak256":"0x59973a93b1f983f94e10529f46ca46544a9fec2b5f56fb1390bbe9e0dc79f857","urls":["bzz-raw://c55ef8f0b9719790c2ae6f81d80a59ffb89f2f0abe6bc065585bd79edce058c5","dweb:/ipfs/QmNNmCbX9NjPXKqHJN8R1WC2rNeZSQrPZLd6FF6AKLyH5Y"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol":{"keccak256":"0xc8cae21c9ae4a46e5162ff9bf5b351d6fa6a6eba72d515f3bc1bdfeda7fdf083","urls":["bzz-raw://ce830ebcf28e31643caba318996db3763c36d52cd0f23798ba83c135355d45e9","dweb:/ipfs/QmdGPcvptHN7UBCbUYBbRX3hiRVRFLRwno8b4uga6uFNif"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/structs/EnumerableSet.sol":{"keccak256":"0xd553ff8b7d55679f0711f1598600ac292dbd8cfdf4b2419b9cabe4c931172895","urls":["bzz-raw://7905ccb27e2308fd0d90dc1212161003ab6964e1c176593db1ccedef705bcc09","dweb:/ipfs/QmW37vm2PcrWLKnN74sKkvAzqSwntCEfCp4EoSEvbBHWkj"],"license":"MIT"},"src/RuleEngineBase.sol":{"keccak256":"0xb3d832fa55b615574d80b0e0ad76620ad236aa046523617ed5daa46ae07bf853","urls":["bzz-raw://7be31bf5dbd3fa1be025cdc4b7674b76bf40e1c14ce89ec78f792cb3d7ed804e","dweb:/ipfs/QmPq4xBiB3XwXerWtuonZLGiWHMqvz5tKvjhTh9AiWkbww"],"license":"MPL-2.0"},"src/deployment/accessControl/RuleEngine.sol":{"keccak256":"0x003d3c670256396a0ec6369ff8d44ed0a8cf1e371a44494d1d59d24f82854d86","urls":["bzz-raw://9aaeb4f2e3f2b4b8ecaba4adc13c113a87f4a829af47f6d1bafa77e62c27b149","dweb:/ipfs/Qmaqpqc7JwPCEM9xbctor2xPYop5cSKupsbZdp94aYeKVB"],"license":"MPL-2.0"},"src/interfaces/IERC3643Compliance.sol":{"keccak256":"0xd0edd6697d67135853576ac6a40cadaffd787cedea98071708bbfb189c7ee5bc","urls":["bzz-raw://4ed3cd3af64fccff17a1f33989cdfbdacbc0e4f32a56de11a072cf9e2277a1f6","dweb:/ipfs/QmenRqRw1Yy39yDv1pJgBmnHtwuZhDdHE4omchL41CjXjb"],"license":"MPL-2.0"},"src/interfaces/IERC3643ComplianceExtended.sol":{"keccak256":"0x4a43bf330c7a904cba110acf52f519718d8409514c377912d5bd063c9d963729","urls":["bzz-raw://c671879c591760ecbc2691e2f24adfb215a658c9fe6eb0c05dd1ca980054e585","dweb:/ipfs/QmdbA19PFpJgHraF46YrcMNzUgswbTRA92atL2Lha63JLY"],"license":"MPL-2.0"},"src/interfaces/IRule.sol":{"keccak256":"0x81580b67f7be09049aa64d93cc1d8d691a87c639adc1cf169dc6073e1e543a5c","urls":["bzz-raw://6f1808c3ed18ef1acbccdd9b30011b6e7220d388cfd66cba40b1ef0b485306a1","dweb:/ipfs/QmcUCQ5MYcf7KTtoeqMKsTutPPSJhNTaK1ntHV21ioS9Fm"],"license":"MPL-2.0"},"src/interfaces/IRulesManagementModule.sol":{"keccak256":"0x082dd58070e83b02f275584afa872c4583ac4ca8ad12eb329fc11301470147f9","urls":["bzz-raw://e2d0ad78dc323881864f406acd44976f5de39cdc97a6c99a724d8458b993e2e2","dweb:/ipfs/QmRFfMbXbdiAYV3vQyNppXG7tHTji6mV1Y5Cu3ZzEQm5ng"],"license":"MPL-2.0"},"src/interfaces/ITokenBinding.sol":{"keccak256":"0x34dfea4e118c966adf867c0899844515566251819b4e4510fd8ee424555493fd","urls":["bzz-raw://1d054ed49874816688a6e71f76d611bbdefd492d122ae386cb804c6f5af677a7","dweb:/ipfs/QmRaYX4aJWYSNWNa1D4Nich3k7hkGM9rTfc9s2XaVqyRjy"],"license":"MPL-2.0"},"src/interfaces/ITokenBindingExtended.sol":{"keccak256":"0x01f3ab56dffce860d03e72d10e9f2d13b6bfc9004cf058c63a0b23e3b226da99","urls":["bzz-raw://521e0c9651632b70d61c4c3bd0b14c6f05d818166fe65dbed8e3253158b7637e","dweb:/ipfs/QmY2xEVvfV1dgtFYw6coHX3Z7Fm7yRhzPaGyt6cYBMVf76"],"license":"MPL-2.0"},"src/modules/ERC3643ComplianceExtendedModule.sol":{"keccak256":"0x6f808b068517e9e15f09fc6a9d4190001ec8c2314a10e27a85a2d43e44c84fb1","urls":["bzz-raw://c62c0b77fdd8b6e7bf7aa5bf8134a78ff024d6489a23f746874a99df38a8a265","dweb:/ipfs/QmV7PG3ZUUzwDs9tpooC3hmBu5e39buJnJ4TRditojJ3hu"],"license":"MPL-2.0"},"src/modules/ERC3643ComplianceModule.sol":{"keccak256":"0x7cda81af8687328ac2089f9d1d78352e0e75d0f70a4ba8e2b3ac82896f22863f","urls":["bzz-raw://50711cb94d69ea63d787a8bb19c38c0b99539029ec8fb957a8eff00880fc11fc","dweb:/ipfs/QmSapDWh5mpvWn1q6JteZisJfVGPrCz47WP2BBrJCccEjV"],"license":"MPL-2.0"},"src/modules/RulesManagementModule.sol":{"keccak256":"0xe4d9425613284e71a5e3d590d5433167a9751d9496f57efa914baa81f493e66d","urls":["bzz-raw://d07a16e6869df86c526ef89e7e359e34a9553dc4288b262abd2979359ecf720e","dweb:/ipfs/QmRy2JEsyhkv1mxv7eFaSbEWN4A3gtpPSUnnV48W2KiV4u"],"license":"MPL-2.0"},"src/modules/TokenBindingExtendedModule.sol":{"keccak256":"0x4e1ca7b2ec78608c3a7960bec7102a1780bdf3ec7ff544b612bafaf738b34d05","urls":["bzz-raw://657bcdd303fd5a7fbe733b283f69d8e8aa73efeeeaf95c0ae7479769ac573693","dweb:/ipfs/QmXiWPrv8pEqvBQck8jxC7NwB1MUdGQfLjihK6etYcZ54j"],"license":"MPL-2.0"},"src/modules/TokenBindingModule.sol":{"keccak256":"0xf65f46311d0078f60c30e3359dca988e39cba45b9eee53a09d618bfa70e6ef9b","urls":["bzz-raw://e8c458ecfd41df5fb4a391e7ef837fd5ed5c999e61ccc0e6b4bd23023a739832","dweb:/ipfs/Qmdsr765aw9fPFN2M9cSCP69o1o41FNCqhrXjHgEXNwbXV"],"license":"MPL-2.0"},"src/modules/VersionModule.sol":{"keccak256":"0x35daf007be8b9bb1cb9196ae2decb3e5ad4b574f6390f8fc010b78796ac42f73","urls":["bzz-raw://b1b29d75e1c5023a0c6cb8c56638a17d855a3fdc051a60b9d2f304b99f7876d2","dweb:/ipfs/QmXSCVjLuViC8916LwNpKtw8hqyH78Ptag3xH1n7F1fY4g"],"license":"MPL-2.0"},"src/modules/library/ComplianceInterfaceId.sol":{"keccak256":"0xd54bed5328e732f753d2886aeaa2761b2d66536d5247d4548e0ac1c83c7a0dac","urls":["bzz-raw://ad695339fdfe72446a69d2dfbe39373affe2f37299ad921e57016069a7bc3592","dweb:/ipfs/QmWathGt3E85hLfy5rrAYdb291W8VoTa4gpGPoxtWGvNNA"],"license":"MPL-2.0"},"src/modules/library/ERC1404InterfaceId.sol":{"keccak256":"0x07dc6905e137096cd0ae88be29b112d0e54a83ddf8ca527a281718010f6abcce","urls":["bzz-raw://9249dce67cb59432bdbc9e49978c6cac0346cda3d3fca97c5a310e0f424e1600","dweb:/ipfs/QmRi5awH3hjwvd3k3td48y5Cf64n1wvX9wCWy6fQLayuKs"],"license":"MPL-2.0"},"src/modules/library/ERC3643ComplianceRolesStorage.sol":{"keccak256":"0xe422d67495db0f630a49655d5354a9da89707e692824a100527842928db984b8","urls":["bzz-raw://7d310a535b039f6d42e17e3b024841a28f58ca6434cc3555bd5bcbe9a3bb166b","dweb:/ipfs/QmWMMoJngzay4mASYtJSRW6b8Em3bUVWgPca8PLhH9YPVH"],"license":"MPL-2.0"},"src/modules/library/RuleEngineInvariantStorage.sol":{"keccak256":"0x50a212f09f1695662965e5fba643b42a1978bec2a8368abbf43983489c983096","urls":["bzz-raw://6137f01df7630527c985d85d2f7446359c678fcb933b66c55b51f583757b5c4a","dweb:/ipfs/QmeHo47WQm1V99xZHS4soMk68UdtXtZhtWhV3dQC5BtA7u"],"license":"MPL-2.0"},"src/modules/library/RuleInterfaceId.sol":{"keccak256":"0x0d86820eee4c92b21d6704bea8ce7bd2cc1b35f6e4a1ceabbcf2a10f1c6b02ec","urls":["bzz-raw://cfb560cb8588983b8c79a973d03c214a149bf1ac034fa9130ce93f0031a404d7","dweb:/ipfs/Qmc6qt4E4BHdDyLUegCsgxqhf7ZFUiX4ahj8FjM54V7wpY"],"license":"MPL-2.0"},"src/modules/library/RulesManagementModuleInvariantStorage.sol":{"keccak256":"0xb81ea3a54c6e8d47b87d6c3d9fb5aae80c3430021b8cd66d9adeef7f5fc95893","urls":["bzz-raw://cfcbadc2011f60de7189273c278dda1df2218aeeb153bee3b8a93447ec95df21","dweb:/ipfs/Qmem5FqCLEfBJQdJzS7Xzd3zSfyL8Muf9Wv5WvCiBVsqfh"],"license":"MPL-2.0"},"src/modules/library/RulesManagementModuleRolesStorage.sol":{"keccak256":"0xbd4ccff01c8d3e2ffd8cd8e5b095a284ca6563785a683e07fcecd963568203b1","urls":["bzz-raw://784fd4b297baaa29d06ec36bec3b4b391fac7c145840f7e29a5562ebd18374c5","dweb:/ipfs/QmPaBDVnCvYVBVNGcSywdJKfD4Qo9JpGFbqwmc4RjDZy3A"],"license":"MPL-2.0"},"src/modules/library/TokenBindingModuleInvariantStorage.sol":{"keccak256":"0x9bab8e5b265068da356fd46e343a7c6c73776f3964fdeaeff056e8ce104d40a5","urls":["bzz-raw://e2e75d2d52b1e4f5cbb832d194266de9a1b3a8cc2101e875dce43a2664c31a05","dweb:/ipfs/QmUsd5cTPsE89WKm3kTUWsobR9JsBDUY8NdxDU5RPYpvP6"],"license":"MPL-2.0"}},"version":1},"ast":{"absolutePath":"src/deployment/accessControl/RuleEngine.sol","id":9870,"exportedSymbols":{"AccessControl":[913],"AccessControlEnumerable":[1390],"ERC3643ComplianceRolesStorage":[14453],"EnumerableSet":[9032],"IAccessControl":[996],"IERC165":[3800],"RuleEngine":[9869],"RuleEngineBase":[9604],"RulesManagementModuleRolesStorage":[14590]},"nodeType":"SourceUnit","src":"37:4953:30","nodes":[{"id":9691,"nodeType":"PragmaDirective","src":"37:24:30","nodes":[],"literals":["solidity","^","0.8",".27"]},{"id":9693,"nodeType":"ImportDirective","src":"91:81:30","nodes":[],"absolutePath":"lib/openzeppelin-contracts/contracts/access/IAccessControl.sol","file":"@openzeppelin/contracts/access/IAccessControl.sol","nameLocation":"-1:-1:-1","scope":9870,"sourceUnit":997,"symbolAliases":[{"foreign":{"id":9692,"name":"IAccessControl","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":996,"src":"99:14:30","typeDescriptions":{}},"nameLocation":"-1:-1:-1"}],"unitAlias":""},{"id":9695,"nodeType":"ImportDirective","src":"173:79:30","nodes":[],"absolutePath":"lib/openzeppelin-contracts/contracts/access/AccessControl.sol","file":"@openzeppelin/contracts/access/AccessControl.sol","nameLocation":"-1:-1:-1","scope":9870,"sourceUnit":914,"symbolAliases":[{"foreign":{"id":9694,"name":"AccessControl","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":913,"src":"181:13:30","typeDescriptions":{}},"nameLocation":"-1:-1:-1"}],"unitAlias":""},{"id":9697,"nodeType":"ImportDirective","src":"253:110:30","nodes":[],"absolutePath":"lib/openzeppelin-contracts/contracts/access/extensions/AccessControlEnumerable.sol","file":"@openzeppelin/contracts/access/extensions/AccessControlEnumerable.sol","nameLocation":"-1:-1:-1","scope":9870,"sourceUnit":1391,"symbolAliases":[{"foreign":{"id":9696,"name":"AccessControlEnumerable","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":1390,"src":"261:23:30","typeDescriptions":{}},"nameLocation":"-1:-1:-1"}],"unitAlias":""},{"id":9699,"nodeType":"ImportDirective","src":"364:79:30","nodes":[],"absolutePath":"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol","file":"@openzeppelin/contracts/utils/introspection/ERC165.sol","nameLocation":"-1:-1:-1","scope":9870,"sourceUnit":3579,"symbolAliases":[{"foreign":{"id":9698,"name":"IERC165","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":3800,"src":"372:7:30","typeDescriptions":{}},"nameLocation":"-1:-1:-1"}],"unitAlias":""},{"id":9701,"nodeType":"ImportDirective","src":"444:86:30","nodes":[],"absolutePath":"lib/openzeppelin-contracts/contracts/utils/structs/EnumerableSet.sol","file":"@openzeppelin/contracts/utils/structs/EnumerableSet.sol","nameLocation":"-1:-1:-1","scope":9870,"sourceUnit":9033,"symbolAliases":[{"foreign":{"id":9700,"name":"EnumerableSet","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":9032,"src":"452:13:30","typeDescriptions":{}},"nameLocation":"-1:-1:-1"}],"unitAlias":""},{"id":9703,"nodeType":"ImportDirective","src":"554:102:30","nodes":[],"absolutePath":"src/modules/library/ERC3643ComplianceRolesStorage.sol","file":"../../modules/library/ERC3643ComplianceRolesStorage.sol","nameLocation":"-1:-1:-1","scope":9870,"sourceUnit":14454,"symbolAliases":[{"foreign":{"id":9702,"name":"ERC3643ComplianceRolesStorage","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":14453,"src":"562:29:30","typeDescriptions":{}},"nameLocation":"-1:-1:-1"}],"unitAlias":""},{"id":9705,"nodeType":"ImportDirective","src":"657:110:30","nodes":[],"absolutePath":"src/modules/library/RulesManagementModuleRolesStorage.sol","file":"../../modules/library/RulesManagementModuleRolesStorage.sol","nameLocation":"-1:-1:-1","scope":9870,"sourceUnit":14591,"symbolAliases":[{"foreign":{"id":9704,"name":"RulesManagementModuleRolesStorage","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":14590,"src":"665:33:30","typeDescriptions":{}},"nameLocation":"-1:-1:-1"}],"unitAlias":""},{"id":9707,"nodeType":"ImportDirective","src":"797:56:30","nodes":[],"absolutePath":"src/RuleEngineBase.sol","file":"../../RuleEngineBase.sol","nameLocation":"-1:-1:-1","scope":9870,"sourceUnit":9605,"symbolAliases":[{"foreign":{"id":9706,"name":"RuleEngineBase","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":9604,"src":"805:14:30","typeDescriptions":{}},"nameLocation":"-1:-1:-1"}],"unitAlias":""},{"id":9869,"nodeType":"ContractDefinition","src":"1155:3834:30","nodes":[{"id":9720,"nodeType":"UsingForDirective","src":"1306:49:30","nodes":[],"global":false,"libraryName":{"id":9717,"name":"EnumerableSet","nameLocations":["1312:13:30"],"nodeType":"IdentifierPath","referencedDeclaration":9032,"src":"1312:13:30"},"typeName":{"id":9719,"nodeType":"UserDefinedTypeName","pathNode":{"id":9718,"name":"EnumerableSet.AddressSet","nameLocations":["1330:13:30","1344:10:30"],"nodeType":"IdentifierPath","referencedDeclaration":7939,"src":"1330:24:30"},"referencedDeclaration":7939,"src":"1330:24:30","typeDescriptions":{"typeIdentifier":"t_struct$_AddressSet_$7939_storage_ptr","typeString":"struct EnumerableSet.AddressSet"}}},{"id":9761,"nodeType":"FunctionDefinition","src":"1663:410:30","nodes":[],"body":{"id":9760,"nodeType":"Block","src":"1713:360:30","nodes":[],"statements":[{"expression":{"arguments":[{"commonType":{"typeIdentifier":"t_address","typeString":"address"},"id":9734,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"leftExpression":{"id":9729,"name":"admin","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":9723,"src":"1731:5:30","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"nodeType":"BinaryOperation","operator":"!=","rightExpression":{"arguments":[{"hexValue":"30","id":9732,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"1748:1:30","typeDescriptions":{"typeIdentifier":"t_rational_0_by_1","typeString":"int_const 0"},"value":"0"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_0_by_1","typeString":"int_const 0"}],"id":9731,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"1740:7:30","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":9730,"name":"address","nodeType":"ElementaryTypeName","src":"1740:7:30","typeDescriptions":{}}},"id":9733,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"nameLocations":[],"names":[],"nodeType":"FunctionCall","src":"1740:10:30","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"src":"1731:19:30","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},{"arguments":[],"expression":{"argumentTypes":[],"id":9735,"name":"RuleEngine_AdminWithAddressZeroNotAllowed","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":14474,"src":"1752:41:30","typeDescriptions":{"typeIdentifier":"t_function_error_pure$__$returns$_t_error_$","typeString":"function () pure returns (error)"}},"id":9736,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"nameLocations":[],"names":[],"nodeType":"FunctionCall","src":"1752:43:30","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_error","typeString":"error"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bool","typeString":"bool"},{"typeIdentifier":"t_error","typeString":"error"}],"id":9728,"name":"require","nodeType":"Identifier","overloadedDeclarations":[-18,-18,-18],"referencedDeclaration":-18,"src":"1723:7:30","typeDescriptions":{"typeIdentifier":"t_function_require_pure$_t_bool_$_t_error_$returns$__$","typeString":"function (bool,error) pure"}},"id":9737,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"nameLocations":[],"names":[],"nodeType":"FunctionCall","src":"1723:73:30","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":9738,"nodeType":"ExpressionStatement","src":"1723:73:30"},{"condition":{"commonType":{"typeIdentifier":"t_address","typeString":"address"},"id":9744,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"leftExpression":{"id":9739,"name":"tokenContract","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":9725,"src":"1810:13:30","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"nodeType":"BinaryOperation","operator":"!=","rightExpression":{"arguments":[{"hexValue":"30","id":9742,"isConstant":false,"isLValue":false,"isPure":true,"kind":"number","lValueRequested":false,"nodeType":"Literal","src":"1835:1:30","typeDescriptions":{"typeIdentifier":"t_rational_0_by_1","typeString":"int_const 0"},"value":"0"}],"expression":{"argumentTypes":[{"typeIdentifier":"t_rational_0_by_1","typeString":"int_const 0"}],"id":9741,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"nodeType":"ElementaryTypeNameExpression","src":"1827:7:30","typeDescriptions":{"typeIdentifier":"t_type$_t_address_$","typeString":"type(address)"},"typeName":{"id":9740,"name":"address","nodeType":"ElementaryTypeName","src":"1827:7:30","typeDescriptions":{}}},"id":9743,"isConstant":false,"isLValue":false,"isPure":true,"kind":"typeConversion","lValueRequested":false,"nameLocations":[],"names":[],"nodeType":"FunctionCall","src":"1827:10:30","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"src":"1810:27:30","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"id":9750,"nodeType":"IfStatement","src":"1806:83:30","trueBody":{"id":9749,"nodeType":"Block","src":"1839:50:30","statements":[{"expression":{"arguments":[{"id":9746,"name":"tokenContract","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":9725,"src":"1864:13:30","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"id":9745,"name":"_bindToken","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":14299,"src":"1853:10:30","typeDescriptions":{"typeIdentifier":"t_function_internal_nonpayable$_t_address_$returns$__$","typeString":"function (address)"}},"id":9747,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"nameLocations":[],"names":[],"nodeType":"FunctionCall","src":"1853:25:30","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":9748,"nodeType":"ExpressionStatement","src":"1853:25:30"}]}},{"expression":{"arguments":[{"id":9752,"name":"DEFAULT_ADMIN_ROLE","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":647,"src":"1909:18:30","typeDescriptions":{"typeIdentifier":"t_bytes32","typeString":"bytes32"}},{"id":9753,"name":"admin","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":9723,"src":"1929:5:30","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes32","typeString":"bytes32"},{"typeIdentifier":"t_address","typeString":"address"}],"id":9751,"name":"_grantRole","nodeType":"Identifier","overloadedDeclarations":[1357],"referencedDeclaration":1357,"src":"1898:10:30","typeDescriptions":{"typeIdentifier":"t_function_internal_nonpayable$_t_bytes32_$_t_address_$returns$_t_bool_$","typeString":"function (bytes32,address) returns (bool)"}},"id":9754,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"nameLocations":[],"names":[],"nodeType":"FunctionCall","src":"1898:37:30","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"id":9755,"nodeType":"ExpressionStatement","src":"1898:37:30"},{"expression":{"arguments":[{"id":9757,"name":"DEFAULT_MAX_RULES","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":14543,"src":"2048:17:30","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_uint256","typeString":"uint256"}],"id":9756,"name":"_setMaxRules","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":13746,"src":"2035:12:30","typeDescriptions":{"typeIdentifier":"t_function_internal_nonpayable$_t_uint256_$returns$__$","typeString":"function (uint256)"}},"id":9758,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"nameLocations":[],"names":[],"nodeType":"FunctionCall","src":"2035:31:30","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":9759,"nodeType":"ExpressionStatement","src":"2035:31:30"}]},"documentation":{"id":9721,"nodeType":"StructuredDocumentation","src":"1361:297:30","text":" @notice Deploys the RBAC RuleEngine, grants the admin role and optionally binds an initial token.\n @param admin Address receiving `DEFAULT_ADMIN_ROLE`; must not be the zero address.\n @param tokenContract Token to bind at deployment, or the zero address to bind none."},"implemented":true,"kind":"constructor","modifiers":[],"name":"","nameLocation":"-1:-1:-1","parameters":{"id":9726,"nodeType":"ParameterList","parameters":[{"constant":false,"id":9723,"mutability":"mutable","name":"admin","nameLocation":"1683:5:30","nodeType":"VariableDeclaration","scope":9761,"src":"1675:13:30","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":9722,"name":"address","nodeType":"ElementaryTypeName","src":"1675:7:30","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"},{"constant":false,"id":9725,"mutability":"mutable","name":"tokenContract","nameLocation":"1698:13:30","nodeType":"VariableDeclaration","scope":9761,"src":"1690:21:30","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":9724,"name":"address","nodeType":"ElementaryTypeName","src":"1690:7:30","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"src":"1674:38:30"},"returnParameters":{"id":9727,"nodeType":"ParameterList","parameters":[],"src":"1713:0:30"},"scope":9869,"stateMutability":"nonpayable","virtual":false,"visibility":"public"},{"id":9790,"nodeType":"FunctionDefinition","src":"2709:275:30","nodes":[],"body":{"id":9789,"nodeType":"Block","src":"2814:170:30","nodes":[],"statements":[{"expression":{"arguments":[{"id":9777,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"nodeType":"UnaryOperation","operator":"!","prefix":true,"src":"2832:25:30","subExpression":{"arguments":[{"id":9775,"name":"account","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":9766,"src":"2849:7:30","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":9773,"name":"_rules","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":13484,"src":"2833:6:30","typeDescriptions":{"typeIdentifier":"t_struct$_AddressSet_$7939_storage","typeString":"struct EnumerableSet.AddressSet storage ref"}},"id":9774,"isConstant":false,"isLValue":true,"isPure":false,"lValueRequested":false,"memberLocation":"2840:8:30","memberName":"contains","nodeType":"MemberAccess","referencedDeclaration":8033,"src":"2833:15:30","typeDescriptions":{"typeIdentifier":"t_function_internal_view$_t_struct$_AddressSet_$7939_storage_ptr_$_t_address_$returns$_t_bool_$attached_to$_t_struct$_AddressSet_$7939_storage_ptr_$","typeString":"function (struct EnumerableSet.AddressSet storage pointer,address) view returns (bool)"}},"id":9776,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"nameLocations":[],"names":[],"nodeType":"FunctionCall","src":"2833:24:30","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},{"arguments":[],"expression":{"argumentTypes":[],"id":9778,"name":"RuleEngine_RulesManagementModule_RuleAccountCannotReceivePrivileges","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":14559,"src":"2859:67:30","typeDescriptions":{"typeIdentifier":"t_function_error_pure$__$returns$_t_error_$","typeString":"function () pure returns (error)"}},"id":9779,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"nameLocations":[],"names":[],"nodeType":"FunctionCall","src":"2859:69:30","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_error","typeString":"error"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bool","typeString":"bool"},{"typeIdentifier":"t_error","typeString":"error"}],"id":9772,"name":"require","nodeType":"Identifier","overloadedDeclarations":[-18,-18,-18],"referencedDeclaration":-18,"src":"2824:7:30","typeDescriptions":{"typeIdentifier":"t_function_require_pure$_t_bool_$_t_error_$returns$__$","typeString":"function (bool,error) pure"}},"id":9780,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"nameLocations":[],"names":[],"nodeType":"FunctionCall","src":"2824:105:30","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":9781,"nodeType":"ExpressionStatement","src":"2824:105:30"},{"expression":{"arguments":[{"id":9785,"name":"role","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":9764,"src":"2963:4:30","typeDescriptions":{"typeIdentifier":"t_bytes32","typeString":"bytes32"}},{"id":9786,"name":"account","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":9766,"src":"2969:7:30","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes32","typeString":"bytes32"},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":9782,"name":"AccessControl","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":913,"src":"2939:13:30","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_AccessControl_$913_$","typeString":"type(contract AccessControl)"}},"id":9784,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberLocation":"2953:9:30","memberName":"grantRole","nodeType":"MemberAccess","referencedDeclaration":765,"src":"2939:23:30","typeDescriptions":{"typeIdentifier":"t_function_internal_nonpayable$_t_bytes32_$_t_address_$returns$__$","typeString":"function (bytes32,address)"}},"id":9787,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"nameLocations":[],"names":[],"nodeType":"FunctionCall","src":"2939:38:30","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":9788,"nodeType":"ExpressionStatement","src":"2939:38:30"}]},"baseFunctions":[765,979],"documentation":{"id":9762,"nodeType":"StructuredDocumentation","src":"2130:574:30","text":" @notice Grants `role` to `account`.\n @dev Prevents granting any role to accounts currently configured as rules.\n Note: this check is intentionally one-directional. {addRule} does not verify\n whether the rule address already holds a privileged role, and this function does\n not prevent adding a privileged address as a rule afterwards. Operators are\n responsible for keeping rule contracts and privileged accounts disjoint.\n @param role The role identifier to grant.\n @param account The account receiving the role."},"functionSelector":"2f2ff15d","implemented":true,"kind":"function","modifiers":[],"name":"grantRole","nameLocation":"2718:9:30","overrides":{"id":9770,"nodeType":"OverrideSpecifier","overrides":[{"id":9768,"name":"AccessControl","nameLocations":["2783:13:30"],"nodeType":"IdentifierPath","referencedDeclaration":913,"src":"2783:13:30"},{"id":9769,"name":"IAccessControl","nameLocations":["2798:14:30"],"nodeType":"IdentifierPath","referencedDeclaration":996,"src":"2798:14:30"}],"src":"2774:39:30"},"parameters":{"id":9767,"nodeType":"ParameterList","parameters":[{"constant":false,"id":9764,"mutability":"mutable","name":"role","nameLocation":"2736:4:30","nodeType":"VariableDeclaration","scope":9790,"src":"2728:12:30","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_bytes32","typeString":"bytes32"},"typeName":{"id":9763,"name":"bytes32","nodeType":"ElementaryTypeName","src":"2728:7:30","typeDescriptions":{"typeIdentifier":"t_bytes32","typeString":"bytes32"}},"visibility":"internal"},{"constant":false,"id":9766,"mutability":"mutable","name":"account","nameLocation":"2750:7:30","nodeType":"VariableDeclaration","scope":9790,"src":"2742:15:30","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":9765,"name":"address","nodeType":"ElementaryTypeName","src":"2742:7:30","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"src":"2727:31:30"},"returnParameters":{"id":9771,"nodeType":"ParameterList","parameters":[],"src":"2814:0:30"},"scope":9869,"stateMutability":"nonpayable","virtual":true,"visibility":"public"},{"id":9820,"nodeType":"FunctionDefinition","src":"3305:349:30","nodes":[],"body":{"id":9819,"nodeType":"Block","src":"3472:182:30","nodes":[],"statements":[{"condition":{"arguments":[{"id":9805,"name":"DEFAULT_ADMIN_ROLE","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":647,"src":"3508:18:30","typeDescriptions":{"typeIdentifier":"t_bytes32","typeString":"bytes32"}},{"id":9806,"name":"account","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":9795,"src":"3528:7:30","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes32","typeString":"bytes32"},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":9803,"name":"AccessControl","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":913,"src":"3486:13:30","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_AccessControl_$913_$","typeString":"type(contract AccessControl)"}},"id":9804,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberLocation":"3500:7:30","memberName":"hasRole","nodeType":"MemberAccess","referencedDeclaration":698,"src":"3486:21:30","typeDescriptions":{"typeIdentifier":"t_function_internal_view$_t_bytes32_$_t_address_$returns$_t_bool_$","typeString":"function (bytes32,address) view returns (bool)"}},"id":9807,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"nameLocations":[],"names":[],"nodeType":"FunctionCall","src":"3486:50:30","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"falseBody":{"id":9817,"nodeType":"Block","src":"3580:68:30","statements":[{"expression":{"arguments":[{"id":9813,"name":"role","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":9793,"src":"3623:4:30","typeDescriptions":{"typeIdentifier":"t_bytes32","typeString":"bytes32"}},{"id":9814,"name":"account","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":9795,"src":"3629:7:30","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes32","typeString":"bytes32"},{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":9811,"name":"AccessControl","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":913,"src":"3601:13:30","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_AccessControl_$913_$","typeString":"type(contract AccessControl)"}},"id":9812,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberLocation":"3615:7:30","memberName":"hasRole","nodeType":"MemberAccess","referencedDeclaration":698,"src":"3601:21:30","typeDescriptions":{"typeIdentifier":"t_function_internal_view$_t_bytes32_$_t_address_$returns$_t_bool_$","typeString":"function (bytes32,address) view returns (bool)"}},"id":9815,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"nameLocations":[],"names":[],"nodeType":"FunctionCall","src":"3601:36:30","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"functionReturnParameters":9802,"id":9816,"nodeType":"Return","src":"3594:43:30"}]},"id":9818,"nodeType":"IfStatement","src":"3482:166:30","trueBody":{"id":9810,"nodeType":"Block","src":"3538:36:30","statements":[{"expression":{"hexValue":"74727565","id":9808,"isConstant":false,"isLValue":false,"isPure":true,"kind":"bool","lValueRequested":false,"nodeType":"Literal","src":"3559:4:30","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"},"value":"true"},"functionReturnParameters":9802,"id":9809,"nodeType":"Return","src":"3552:11:30"}]}}]},"baseFunctions":[698,963],"documentation":{"id":9791,"nodeType":"StructuredDocumentation","src":"2990:310:30","text":" @notice Returns `true` if `account` has been granted `role`.\n @dev The Default Admin has all roles\n @param role The role identifier to check.\n @param account The account to check.\n @return True if the account holds the role (or is the default admin), false otherwise."},"functionSelector":"91d14854","implemented":true,"kind":"function","modifiers":[],"name":"hasRole","nameLocation":"3314:7:30","overrides":{"id":9799,"nodeType":"OverrideSpecifier","overrides":[{"id":9797,"name":"AccessControl","nameLocations":["3414:13:30"],"nodeType":"IdentifierPath","referencedDeclaration":913,"src":"3414:13:30"},{"id":9798,"name":"IAccessControl","nameLocations":["3429:14:30"],"nodeType":"IdentifierPath","referencedDeclaration":996,"src":"3429:14:30"}],"src":"3405:39:30"},"parameters":{"id":9796,"nodeType":"ParameterList","parameters":[{"constant":false,"id":9793,"mutability":"mutable","name":"role","nameLocation":"3330:4:30","nodeType":"VariableDeclaration","scope":9820,"src":"3322:12:30","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_bytes32","typeString":"bytes32"},"typeName":{"id":9792,"name":"bytes32","nodeType":"ElementaryTypeName","src":"3322:7:30","typeDescriptions":{"typeIdentifier":"t_bytes32","typeString":"bytes32"}},"visibility":"internal"},{"constant":false,"id":9795,"mutability":"mutable","name":"account","nameLocation":"3344:7:30","nodeType":"VariableDeclaration","scope":9820,"src":"3336:15:30","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":9794,"name":"address","nodeType":"ElementaryTypeName","src":"3336:7:30","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"src":"3321:31:30"},"returnParameters":{"id":9802,"nodeType":"ParameterList","parameters":[{"constant":false,"id":9801,"mutability":"mutable","name":"","nameLocation":"-1:-1:-1","nodeType":"VariableDeclaration","scope":9820,"src":"3462:4:30","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"},"typeName":{"id":9800,"name":"bool","nodeType":"ElementaryTypeName","src":"3462:4:30","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"visibility":"internal"}],"src":"3461:6:30"},"scope":9869,"stateMutability":"view","virtual":true,"visibility":"public"},{"id":9841,"nodeType":"FunctionDefinition","src":"3893:296:30","nodes":[],"body":{"id":9840,"nodeType":"Block","src":"4062:127:30","nodes":[],"statements":[{"expression":{"commonType":{"typeIdentifier":"t_bool","typeString":"bool"},"id":9838,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"leftExpression":{"arguments":[{"id":9832,"name":"interfaceId","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":9823,"src":"4112:11:30","typeDescriptions":{"typeIdentifier":"t_bytes4","typeString":"bytes4"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes4","typeString":"bytes4"}],"id":9831,"name":"_supportsRuleEngineBaseInterface","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":9603,"src":"4079:32:30","typeDescriptions":{"typeIdentifier":"t_function_internal_pure$_t_bytes4_$returns$_t_bool_$","typeString":"function (bytes4) pure returns (bool)"}},"id":9833,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"nameLocations":[],"names":[],"nodeType":"FunctionCall","src":"4079:45:30","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"nodeType":"BinaryOperation","operator":"||","rightExpression":{"arguments":[{"id":9836,"name":"interfaceId","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":9823,"src":"4170:11:30","typeDescriptions":{"typeIdentifier":"t_bytes4","typeString":"bytes4"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes4","typeString":"bytes4"}],"expression":{"id":9834,"name":"AccessControlEnumerable","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":1390,"src":"4128:23:30","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_AccessControlEnumerable_$1390_$","typeString":"type(contract AccessControlEnumerable)"}},"id":9835,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberLocation":"4152:17:30","memberName":"supportsInterface","nodeType":"MemberAccess","referencedDeclaration":1276,"src":"4128:41:30","typeDescriptions":{"typeIdentifier":"t_function_internal_view$_t_bytes4_$returns$_t_bool_$","typeString":"function (bytes4) view returns (bool)"}},"id":9837,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"nameLocations":[],"names":[],"nodeType":"FunctionCall","src":"4128:54:30","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"src":"4079:103:30","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"functionReturnParameters":9830,"id":9839,"nodeType":"Return","src":"4072:110:30"}]},"baseFunctions":[1276,3799],"documentation":{"id":9821,"nodeType":"StructuredDocumentation","src":"3704:184:30","text":" @notice ERC-165 interface detection.\n @param interfaceId The interface identifier to check.\n @return True if the interface is supported, false otherwise."},"functionSelector":"01ffc9a7","implemented":true,"kind":"function","modifiers":[],"name":"supportsInterface","nameLocation":"3902:17:30","overrides":{"id":9827,"nodeType":"OverrideSpecifier","overrides":[{"id":9825,"name":"AccessControlEnumerable","nameLocations":["4001:23:30"],"nodeType":"IdentifierPath","referencedDeclaration":1390,"src":"4001:23:30"},{"id":9826,"name":"IERC165","nameLocations":["4026:7:30"],"nodeType":"IdentifierPath","referencedDeclaration":3800,"src":"4026:7:30"}],"src":"3992:42:30"},"parameters":{"id":9824,"nodeType":"ParameterList","parameters":[{"constant":false,"id":9823,"mutability":"mutable","name":"interfaceId","nameLocation":"3927:11:30","nodeType":"VariableDeclaration","scope":9841,"src":"3920:18:30","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_bytes4","typeString":"bytes4"},"typeName":{"id":9822,"name":"bytes4","nodeType":"ElementaryTypeName","src":"3920:6:30","typeDescriptions":{"typeIdentifier":"t_bytes4","typeString":"bytes4"}},"visibility":"internal"}],"src":"3919:20:30"},"returnParameters":{"id":9830,"nodeType":"ParameterList","parameters":[{"constant":false,"id":9829,"mutability":"mutable","name":"","nameLocation":"-1:-1:-1","nodeType":"VariableDeclaration","scope":9841,"src":"4052:4:30","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"},"typeName":{"id":9828,"name":"bool","nodeType":"ElementaryTypeName","src":"4052:4:30","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"visibility":"internal"}],"src":"4051:6:30"},"scope":9869,"stateMutability":"view","virtual":true,"visibility":"public"},{"id":9850,"nodeType":"FunctionDefinition","src":"4492:96:30","nodes":[],"body":{"id":9849,"nodeType":"Block","src":"4586:2:30","nodes":[],"statements":[]},"baseFunctions":[13446],"documentation":{"id":9842,"nodeType":"StructuredDocumentation","src":"4381:106:30","text":" @dev Access control check restricting compliance operations to COMPLIANCE_MANAGER_ROLE."},"implemented":true,"kind":"function","modifiers":[{"arguments":[{"id":9846,"name":"COMPLIANCE_MANAGER_ROLE","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":14452,"src":"4561:23:30","typeDescriptions":{"typeIdentifier":"t_bytes32","typeString":"bytes32"}}],"id":9847,"kind":"modifierInvocation","modifierName":{"id":9845,"name":"onlyRole","nameLocations":["4552:8:30"],"nodeType":"IdentifierPath","referencedDeclaration":658,"src":"4552:8:30"},"nodeType":"ModifierInvocation","src":"4552:33:30"}],"name":"_onlyComplianceManager","nameLocation":"4501:22:30","overrides":{"id":9844,"nodeType":"OverrideSpecifier","overrides":[],"src":"4543:8:30"},"parameters":{"id":9843,"nodeType":"ParameterList","parameters":[],"src":"4523:2:30"},"returnParameters":{"id":9848,"nodeType":"ParameterList","parameters":[],"src":"4586:0:30"},"scope":9869,"stateMutability":"nonpayable","virtual":true,"visibility":"internal"},{"id":9859,"nodeType":"FunctionDefinition","src":"4697:89:30","nodes":[],"body":{"id":9858,"nodeType":"Block","src":"4784:2:30","nodes":[],"statements":[]},"baseFunctions":[13890],"documentation":{"id":9851,"nodeType":"StructuredDocumentation","src":"4594:98:30","text":" @dev Access control check restricting rule management to RULES_MANAGEMENT_ROLE."},"implemented":true,"kind":"function","modifiers":[{"arguments":[{"id":9855,"name":"RULES_MANAGEMENT_ROLE","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":14589,"src":"4761:21:30","typeDescriptions":{"typeIdentifier":"t_bytes32","typeString":"bytes32"}}],"id":9856,"kind":"modifierInvocation","modifierName":{"id":9854,"name":"onlyRole","nameLocations":["4752:8:30"],"nodeType":"IdentifierPath","referencedDeclaration":658,"src":"4752:8:30"},"nodeType":"ModifierInvocation","src":"4752:31:30"}],"name":"_onlyRulesManager","nameLocation":"4706:17:30","overrides":{"id":9853,"nodeType":"OverrideSpecifier","overrides":[],"src":"4743:8:30"},"parameters":{"id":9852,"nodeType":"ParameterList","parameters":[],"src":"4723:2:30"},"returnParameters":{"id":9857,"nodeType":"ParameterList","parameters":[],"src":"4784:0:30"},"scope":9869,"stateMutability":"nonpayable","virtual":true,"visibility":"internal"},{"id":9868,"nodeType":"FunctionDefinition","src":"4896:91:30","nodes":[],"body":{"id":9867,"nodeType":"Block","src":"4985:2:30","nodes":[],"statements":[]},"baseFunctions":[13894],"documentation":{"id":9860,"nodeType":"StructuredDocumentation","src":"4792:99:30","text":" @dev Access control check restricting the rule cap update to DEFAULT_ADMIN_ROLE."},"implemented":true,"kind":"function","modifiers":[{"arguments":[{"id":9864,"name":"DEFAULT_ADMIN_ROLE","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":647,"src":"4965:18:30","typeDescriptions":{"typeIdentifier":"t_bytes32","typeString":"bytes32"}}],"id":9865,"kind":"modifierInvocation","modifierName":{"id":9863,"name":"onlyRole","nameLocations":["4956:8:30"],"nodeType":"IdentifierPath","referencedDeclaration":658,"src":"4956:8:30"},"nodeType":"ModifierInvocation","src":"4956:28:30"}],"name":"_onlyRulesLimitManager","nameLocation":"4905:22:30","overrides":{"id":9862,"nodeType":"OverrideSpecifier","overrides":[],"src":"4947:8:30"},"parameters":{"id":9861,"nodeType":"ParameterList","parameters":[],"src":"4927:2:30"},"returnParameters":{"id":9866,"nodeType":"ParameterList","parameters":[],"src":"4985:0:30"},"scope":9869,"stateMutability":"nonpayable","virtual":true,"visibility":"internal"}],"abstract":false,"baseContracts":[{"baseName":{"id":9709,"name":"RuleEngineBase","nameLocations":["1182:14:30"],"nodeType":"IdentifierPath","referencedDeclaration":9604,"src":"1182:14:30"},"id":9710,"nodeType":"InheritanceSpecifier","src":"1182:14:30"},{"baseName":{"id":9711,"name":"AccessControlEnumerable","nameLocations":["1202:23:30"],"nodeType":"IdentifierPath","referencedDeclaration":1390,"src":"1202:23:30"},"id":9712,"nodeType":"InheritanceSpecifier","src":"1202:23:30"},{"baseName":{"id":9713,"name":"ERC3643ComplianceRolesStorage","nameLocations":["1231:29:30"],"nodeType":"IdentifierPath","referencedDeclaration":14453,"src":"1231:29:30"},"id":9714,"nodeType":"InheritanceSpecifier","src":"1231:29:30"},{"baseName":{"id":9715,"name":"RulesManagementModuleRolesStorage","nameLocations":["1266:33:30"],"nodeType":"IdentifierPath","referencedDeclaration":14590,"src":"1266:33:30"},"id":9716,"nodeType":"InheritanceSpecifier","src":"1266:33:30"}],"canonicalName":"RuleEngine","contractDependencies":[],"contractKind":"contract","documentation":{"id":9708,"nodeType":"StructuredDocumentation","src":"855:299:30","text":" @title Implementation of a ruleEngine as defined by the CMTAT, with RBAC access control\n @dev No ERC-2771 support: every caller is the raw `msg.sender`. Deploy {RuleEngine2771}, which\n extends this contract, to administer the engine through a trusted forwarder (gasless transactions)."},"fullyImplemented":true,"linearizedBaseContracts":[9869,14590,14453,1390,913,3578,9604,34,28,3800,1416,996,14477,13390,10332,13447,14176,10545,10320,14356,14606,10476,262,464,251,311,285,3248,13913,10442,14580,14379,123],"name":"RuleEngine","nameLocation":"1164:10:30","scope":9870,"usedErrors":[923,926,14474,14476,14545,14547,14549,14551,14555,14557,14559,14596,14599,14602,14605],"usedEvents":[935,944,953,10450,10455,10490,10498,14565,14571,14574,14579]}],"license":"MPL-2.0"},"id":30} \ No newline at end of file diff --git a/doc/compilation/v3.0.0-rc7/foundry/RuleEngine2771.sol/RuleEngine2771.json b/doc/compilation/v3.0.0-rc7/foundry/RuleEngine2771.sol/RuleEngine2771.json new file mode 100644 index 00000000..972e9a8f --- /dev/null +++ b/doc/compilation/v3.0.0-rc7/foundry/RuleEngine2771.sol/RuleEngine2771.json @@ -0,0 +1 @@ +{"abi":[{"type":"constructor","inputs":[{"name":"admin","type":"address","internalType":"address"},{"name":"forwarderIrrevocable","type":"address","internalType":"address"},{"name":"tokenContract","type":"address","internalType":"address"}],"stateMutability":"nonpayable"},{"type":"function","name":"COMPLIANCE_MANAGER_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"DEFAULT_ADMIN_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"DEFAULT_MAX_RULES","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"RULES_MANAGEMENT_ROLE","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"addRule","inputs":[{"name":"rule_","type":"address","internalType":"contract IRule"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"bindToken","inputs":[{"name":"token","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"bindTokens","inputs":[{"name":"tokens","type":"address[]","internalType":"address[]"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"canTransfer","inputs":[{"name":"from","type":"address","internalType":"address"},{"name":"to","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"canTransferFrom","inputs":[{"name":"spender","type":"address","internalType":"address"},{"name":"from","type":"address","internalType":"address"},{"name":"to","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"clearRules","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"containsRule","inputs":[{"name":"rule_","type":"address","internalType":"contract IRule"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"created","inputs":[{"name":"to","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"destroyed","inputs":[{"name":"from","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"detectTransferRestriction","inputs":[{"name":"from","type":"address","internalType":"address"},{"name":"to","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint8","internalType":"uint8"}],"stateMutability":"view"},{"type":"function","name":"detectTransferRestrictionFrom","inputs":[{"name":"spender","type":"address","internalType":"address"},{"name":"from","type":"address","internalType":"address"},{"name":"to","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint8","internalType":"uint8"}],"stateMutability":"view"},{"type":"function","name":"getRoleAdmin","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"getRoleMember","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"index","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"getRoleMemberCount","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"getRoleMembers","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"}],"outputs":[{"name":"","type":"address[]","internalType":"address[]"}],"stateMutability":"view"},{"type":"function","name":"getTokenBound","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"getTokenBounds","inputs":[],"outputs":[{"name":"","type":"address[]","internalType":"address[]"}],"stateMutability":"view"},{"type":"function","name":"grantRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"hasRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"isTokenBound","inputs":[{"name":"token","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"isTokenSelfBindingApproved","inputs":[{"name":"token","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"isTrustedForwarder","inputs":[{"name":"forwarder","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"maxRules","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"messageForTransferRestriction","inputs":[{"name":"restrictionCode","type":"uint8","internalType":"uint8"}],"outputs":[{"name":"","type":"string","internalType":"string"}],"stateMutability":"view"},{"type":"function","name":"removeRule","inputs":[{"name":"rule_","type":"address","internalType":"contract IRule"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"renounceRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"callerConfirmation","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"revokeRole","inputs":[{"name":"role","type":"bytes32","internalType":"bytes32"},{"name":"account","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"rule","inputs":[{"name":"ruleId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"rules","inputs":[],"outputs":[{"name":"","type":"address[]","internalType":"address[]"}],"stateMutability":"view"},{"type":"function","name":"rulesCount","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"setMaxRules","inputs":[{"name":"maxRules_","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setRules","inputs":[{"name":"rules_","type":"address[]","internalType":"contract IRule[]"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setTokenSelfBindingApproval","inputs":[{"name":"token","type":"address","internalType":"address"},{"name":"approved","type":"bool","internalType":"bool"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setTokenSelfBindingApprovalBatch","inputs":[{"name":"tokens","type":"address[]","internalType":"address[]"},{"name":"approved","type":"bool","internalType":"bool"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"supportsInterface","inputs":[{"name":"interfaceId","type":"bytes4","internalType":"bytes4"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"transferred","inputs":[{"name":"spender","type":"address","internalType":"address"},{"name":"from","type":"address","internalType":"address"},{"name":"to","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"transferred","inputs":[{"name":"from","type":"address","internalType":"address"},{"name":"to","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"trustedForwarder","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"unbindToken","inputs":[{"name":"token","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"unbindTokens","inputs":[{"name":"tokens","type":"address[]","internalType":"address[]"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"version","inputs":[],"outputs":[{"name":"version_","type":"string","internalType":"string"}],"stateMutability":"view"},{"type":"event","name":"AddRule","inputs":[{"name":"rule","type":"address","indexed":true,"internalType":"contract IRule"}],"anonymous":false},{"type":"event","name":"ClearRules","inputs":[],"anonymous":false},{"type":"event","name":"RemoveRule","inputs":[{"name":"rule","type":"address","indexed":true,"internalType":"contract IRule"}],"anonymous":false},{"type":"event","name":"RoleAdminChanged","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"previousAdminRole","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"newAdminRole","type":"bytes32","indexed":true,"internalType":"bytes32"}],"anonymous":false},{"type":"event","name":"RoleGranted","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"account","type":"address","indexed":true,"internalType":"address"},{"name":"sender","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"RoleRevoked","inputs":[{"name":"role","type":"bytes32","indexed":true,"internalType":"bytes32"},{"name":"account","type":"address","indexed":true,"internalType":"address"},{"name":"sender","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"SetMaxRules","inputs":[{"name":"maxRules","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"TokenBound","inputs":[{"name":"token","type":"address","indexed":false,"internalType":"address"}],"anonymous":false},{"type":"event","name":"TokenSelfBindingApprovalBatchSet","inputs":[{"name":"tokens","type":"address[]","indexed":false,"internalType":"address[]"},{"name":"approved","type":"bool","indexed":false,"internalType":"bool"}],"anonymous":false},{"type":"event","name":"TokenSelfBindingApprovalSet","inputs":[{"name":"token","type":"address","indexed":true,"internalType":"address"},{"name":"approved","type":"bool","indexed":false,"internalType":"bool"}],"anonymous":false},{"type":"event","name":"TokenUnbound","inputs":[{"name":"token","type":"address","indexed":false,"internalType":"address"}],"anonymous":false},{"type":"error","name":"AccessControlBadConfirmation","inputs":[]},{"type":"error","name":"AccessControlUnauthorizedAccount","inputs":[{"name":"account","type":"address","internalType":"address"},{"name":"neededRole","type":"bytes32","internalType":"bytes32"}]},{"type":"error","name":"RuleEngine_AdminWithAddressZeroNotAllowed","inputs":[]},{"type":"error","name":"RuleEngine_RuleInvalidInterface","inputs":[]},{"type":"error","name":"RuleEngine_RulesManagementModule_ArrayIsEmpty","inputs":[]},{"type":"error","name":"RuleEngine_RulesManagementModule_MaxRulesExceeded","inputs":[{"name":"maxRules","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"RuleEngine_RulesManagementModule_MaxRulesZeroNotAllowed","inputs":[]},{"type":"error","name":"RuleEngine_RulesManagementModule_RuleAccountCannotReceivePrivileges","inputs":[]},{"type":"error","name":"RuleEngine_RulesManagementModule_RuleAddressZeroNotAllowed","inputs":[]},{"type":"error","name":"RuleEngine_RulesManagementModule_RuleAlreadyExists","inputs":[]},{"type":"error","name":"RuleEngine_RulesManagementModule_RuleDoNotMatch","inputs":[]},{"type":"error","name":"TokenBinding_InvalidTokenAddress","inputs":[]},{"type":"error","name":"TokenBinding_TokenAlreadyBound","inputs":[]},{"type":"error","name":"TokenBinding_TokenNotBound","inputs":[]},{"type":"error","name":"TokenBinding_UnauthorizedCaller","inputs":[]}],"bytecode":{"object":"0x60a0604052600a600255348015610014575f5ffd5b50604051612590380380612590833981016040819052610033916103fb565b6001600160a01b0380831660805283908290821661006457604051630872273360e21b815260040160405180910390fd5b6001600160a01b0381161561007c5761007c8161009b565b6100865f83610133565b50610091600a610169565b505050505061049a565b6001600160a01b0381166100c25760405163135217db60e21b815260040160405180910390fd5b6100cb816101be565b6100d66003826101e9565b6100f3576040516371b3c56560e11b815260040160405180910390fd5b6040516001600160a01b03821681527f2de35142b19ed5a07796cf30791959c592018f70b1d2d7c460eef8ffe713692b906020015b60405180910390a150565b5f8061013f84846101fd565b90508015610160575f84815260076020526040902061015e90846101e9565b505b90505b92915050565b805f0361018957604051631e69e71760e21b815260040160405180910390fd5b60028190556040518181527f2292ad4720fff63e2bd104c6b1c0d72c2c729a6001c8ab4bb947cbcc5110986390602001610128565b6101c85f8261028f565b156101e6576040516302925f7360e11b815260040160405180910390fd5b50565b5f610160836001600160a01b0384166102b0565b5f61020883836102f5565b610288575f8381526006602090815260408083206001600160a01b03861684529091529020805460ff19166001179055610240610367565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4506001610163565b505f610163565b6001600160a01b0381165f9081526001830160205260408120541515610160565b5f81815260018301602052604081205461028857508154600181810184555f848152602080822090930184905584548482528286019093526040902091909155610163565b6001600160a01b0381165f9081527f54cdd369e4e8a8515e52ca72ec816c2101831ad1f18bf44102ed171459c9b4f8602052604081205460ff161561033c57506001610163565b505f8281526006602090815260408083206001600160a01b038516845290915290205460ff16610163565b5f610370610375565b905090565b5f36601480821080159061038d575061038d336103bb565b156103b3576103a036828403815f61043b565b6103a991610462565b60601c9250505090565b339250505090565b5f6103c560805190565b6001600160a01b0316826001600160a01b0316149050919050565b80516001600160a01b03811681146103f6575f5ffd5b919050565b5f5f5f6060848603121561040d575f5ffd5b610416846103e0565b9250610424602085016103e0565b9150610432604085016103e0565b90509250925092565b5f5f85851115610449575f5ffd5b83861115610455575f5ffd5b5050820193919092039150565b80356001600160601b03198116906014841015610493576001600160601b0319601485900360031b81901b82161691505b5092915050565b6080516120d06104c05f395f81816103f901528181610479015261156d01526120d05ff3fe608060405234801561000f575f5ffd5b5060043610610276575f3560e01c80638d2ea77211610156578063c7c24b18116100ca578063db75d01711610084578063db75d0171461060a578063df21950f14610635578063e3c4602c14610648578063e46638e61461065b578063e54621d21461066e578063f76bf55014610676575f5ffd5b8063c7c24b1814610586578063ca15c87314610599578063d32c7bb5146105ac578063d4ce1415146105d1578063d547741f146105e4578063db18af6c146105f7575f5ffd5b8063a217fddf1161011b578063a217fddf14610536578063a3246ad31461053d578063b043572e14610550578063b27aef3a14610558578063bb4b61211461056b578063bc13eacc1461057e575f5ffd5b80638d2ea772146104c35780639010d07c146104d657806391d14854146104e9578063993e8b95146104fc5780639b11c1151461050f575f5ffd5b806352f6747a116101ed5780636a3edf28116101b25780636a3edf281461043c5780636ae728c61461045c5780637157797f146104645780637da0a877146104775780637f4ab1dd1461049d5780638baf29b4146104b0575f5ffd5b806352f6747a1461039357806354e4b945146103a857806354fd4d50146103bb578063572b6c05146103e95780635f8dead314610429575f5ffd5b80633284a9a51161023e5780633284a9a51461032157806336568abe146103345780633a56d6d5146103475780633e5af4ca1461035a5780633ff5aa021461036d57806340db3b5014610380575f5ffd5b806301ffc9a71461027a57806303c26bcd146102a25780631455d0e7146102d7578063248a9ca3146102ec5780632f2ff15d1461030e575b5f5ffd5b61028d610288366004611b6a565b61067e565b60405190151581526020015b60405180910390f35b6102c97fe5c50d0927e06141e032cb9a67e1d7092dc85c0b0825191f7e1cede60002856881565b604051908152602001610299565b6102ea6102e5366004611bd9565b61069d565b005b6102c96102fa366004611c18565b5f9081526006602052604090206001015490565b6102ea61031c366004611c43565b6106eb565b6102ea61032f366004611c7e565b610721565b6102ea610342366004611c43565b61075a565b6102ea610355366004611c18565b61079d565b6102ea610368366004611caa565b6107b1565b6102ea61037b366004611cf8565b6107cb565b6102ea61038e366004611cf8565b6107dd565b61039b6107ef565b6040516102999190611d13565b61028d6103b6366004611cf8565b6107ff565b604080518082019091526009815268332e302e302d72633760b81b60208201525b6040516102999190611d5e565b61028d6103f7366004611cf8565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0390811691161490565b6102ea610437366004611d93565b61080a565b61044461081d565b6040516001600160a01b039091168152602001610299565b6002546102c9565b61028d610472366004611caa565b61083f565b7f0000000000000000000000000000000000000000000000000000000000000000610444565b6103dc6104ab366004611dcb565b61085c565b6102ea6104be366004611de6565b610867565b6102ea6104d1366004611d93565b61087a565b6104446104e4366004611e24565b61088d565b61028d6104f7366004611c43565b6108ab565b61028d61050a366004611cf8565b61091d565b6102c97fea5f4eb72290e50c32abd6c23e45de3d8300b3286e1cbc2e293114b92e034e5e81565b6102c95f81565b61039b61054b366004611c18565b610929565b6102ea610942565b6102ea610566366004611bd9565b610954565b6102ea610579366004611e44565b610a07565b6102c9610ad5565b6102ea610594366004611bd9565b610adf565b6102c96105a7366004611c18565b610b28565b6105bf6105ba366004611caa565b610b3e565b60405160ff9091168152602001610299565b6105bf6105df366004611de6565b610b54565b6102ea6105f2366004611c43565b610b60565b610444610605366004611c18565b610b84565b61028d610618366004611cf8565b6001600160a01b03165f9081526005602052604090205460ff1690565b6102ea610643366004611cf8565b610ba6565b6102ea610656366004611cf8565b610bb7565b61028d610669366004611de6565b610bf9565b61039b610c12565b6102c9600a81565b5f61068882610c1e565b80610697575061069782610cbf565b92915050565b6106a5610ce3565b5f5b818110156106e6576106de8383838181106106c4576106c4611e97565b90506020020160208101906106d99190611cf8565b610ceb565b6001016106a7565b505050565b6106f55f82610cf4565b15610713576040516302925f7360e11b815260040160405180910390fd5b61071d8282610d15565b5050565b610729610ce3565b6001600160a01b0382166107505760405163135217db60e21b815260040160405180910390fd5b61071d8282610d39565b610762610d97565b6001600160a01b0316816001600160a01b0316146107935760405163334bd91960e11b815260040160405180910390fd5b6106e68282610da0565b6107a5610dd3565b6107ae81610ddd565b50565b6107b9610e39565b6107c584848484610e61565b50505050565b6107d481610f03565b6107ae81610f0c565b6107e681610f03565b6107ae81610ceb565b60606107fa5f610f9d565b905090565b5f6106978183610cf4565b610812610e39565b61071d5f8383610fa9565b5f5f6108296003611042565b111561083a576107fa60035f61104b565b505f90565b5f8061084d86868686610b3e565b60ff161490505b949350505050565b606061069782611056565b61086f610e39565b6106e6838383610fa9565b610882610e39565b61071d825f83610fa9565b5f8281526007602052604081206108a4908361104b565b9392505050565b6001600160a01b0381165f9081527f54cdd369e4e8a8515e52ca72ec816c2101831ad1f18bf44102ed171459c9b4f8602052604081205460ff16156108f257506001610697565b505f8281526006602090815260408083206001600160a01b038516845290915290205460ff16610697565b5f610697600383610cf4565b5f81815260076020526040902060609061069790610f9d565b61094a6111cb565b6109526111f5565b565b61095c6111cb565b5f81900361097d576040516359203cb960e01b815260040160405180910390fd5b600254808211156109ad57604051630befc49d60e01b81526004016109a491815260200190565b60405180910390fd5b505f6109b85f611042565b11156109c6576109c66111f5565b5f5b818110156106e6576109ff8383838181106109e5576109e5611e97565b90506020020160208101906109fa9190611cf8565b611226565b6001016109c8565b610a0f610ce3565b5f5b82811015610a94575f848483818110610a2c57610a2c611e97565b9050602002016020810190610a419190611cf8565b90506001600160a01b038116610a6a5760405163135217db60e21b815260040160405180910390fd5b6001600160a01b03165f908152600560205260409020805460ff1916831515179055600101610a11565b507f430881f04f203566ee9b32d6444cf02e1b2a0f17ab6b4263a1ee2074d3d0f483838383604051610ac893929190611eab565b60405180910390a1505050565b5f6107fa5f611042565b610ae7610ce3565b5f5b818110156106e657610b20838383818110610b0657610b06611e97565b9050602002016020810190610b1b9190611cf8565b610f0c565b600101610ae9565b5f81815260076020526040812061069790611042565b5f610b4b8585858561128c565b95945050505050565b5f610854848484611359565b5f82815260066020526040902060010154610b7a8161141d565b6107c58383610da0565b5f610b8e5f611042565b821015610b9f576106975f8361104b565b505f919050565b610bae6111cb565b6107ae8161142e565b610bbf6111cb565b60025480610bcc5f611042565b108190610bef57604051630befc49d60e01b81526004016109a491815260200190565b5061071d82611226565b5f80610c06858585610b54565b60ff1614949350505050565b60606107fa6003610f9d565b5f6001600160e01b031982166320c49ce760e01b1480610c4e57506001600160e01b0319821663157094b960e31b145b80610c6957506001600160e01b031982166378a8de7d60e01b145b80610c8457506001600160e01b03198216630c51264760e21b145b80610c9f57506001600160e01b03198216633235d15f60e11b145b8061069757506001600160e01b03198216637157797f60e01b1492915050565b5f6001600160e01b03198216635a05180f60e01b148061069757506106978261148b565b6109526114bf565b6107ae816114e9565b6001600160a01b0381165f90815260018301602052604081205415156108a4565b5f82815260066020526040902060010154610d2f8161141d565b6107c58383611531565b6001600160a01b0382165f81815260056020908152604091829020805460ff191685151590811790915591519182527f407b412a9b6db334d48445ec9bcad46fb50bc4b2e97f73e963e397101957a729910160405180910390a25050565b5f6107fa61155c565b5f5f610dac84846115c6565b905080156108a4575f848152600760205260409020610dcb9084611656565b509392505050565b5f6107ae8161141d565b805f03610dfd57604051631e69e71760e21b815260040160405180910390fd5b60028190556040518181527f2292ad4720fff63e2bd104c6b1c0d72c2c729a6001c8ab4bb947cbcc51109863906020015b60405180910390a150565b610e44600333610cf4565b61095257604051630599c0e960e01b815260040160405180910390fd5b5f610e6b5f611042565b90505f5b81811015610efb57610e815f8261104b565b604051631f2d7a6560e11b81526001600160a01b03888116600483015287811660248301528681166044830152606482018690529190911690633e5af4ca906084015f604051808303815f87803b158015610eda575f5ffd5b505af1158015610eec573d5f5f3e3d5ffd5b50505050806001019050610e6f565b505050505050565b6107ae8161166a565b6001600160a01b038116610f335760405163135217db60e21b815260040160405180910390fd5b610f3c816116a9565b610f476003826116d1565b610f64576040516371b3c56560e11b815260040160405180910390fd5b6040516001600160a01b03821681527f2de35142b19ed5a07796cf30791959c592018f70b1d2d7c460eef8ffe713692b90602001610e2e565b60605f6108a4836116e5565b5f610fb35f611042565b90505f5b8181101561103b57610fc95f8261104b565b6040516322ebca6d60e21b81526001600160a01b0387811660048301528681166024830152604482018690529190911690638baf29b4906064015f604051808303815f87803b15801561101a575f5ffd5b505af115801561102c573d5f5f3e3d5ffd5b50505050806001019050610fb7565b5050505050565b5f610697825490565b5f6108a4838361173e565b606060ff821661108957505060408051808201909152600d81526c2737a932b9ba3934b1ba34b7b760991b602082015290565b5f6110935f611042565b90505f5b8181101561118f575f6110aa818361104b565b604051633e822efb60e11b815260ff871660048201529091506001600160a01b03821690637d045df690602401602060405180830381865afa1580156110f2573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111169190611f03565b1561118657604051637f4ab1dd60e01b815260ff861660048201526001600160a01b03821690637f4ab1dd906024015f60405180830381865afa15801561115f573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610b4b9190810190611f32565b50600101611097565b505060408051808201909152601881527f556e6b6e6f776e207265737472696374696f6e20636f64650000000000000000602082015292915050565b7fea5f4eb72290e50c32abd6c23e45de3d8300b3286e1cbc2e293114b92e034e5e6107ae8161141d565b6040517fdbf61473843cd9be1c9791ce51ef66d0da6c9026d62ba80c1ca433b13fb729b2905f90a16109525f611764565b61122f8161176d565b6112395f826116d1565b6112565760405163cc790a4b60e01b815260040160405180910390fd5b6040516001600160a01b038216907f60305ce6c9104acd0969d358f926bf391174340660aaf5e6215261fd6847bf46905f90a250565b5f5f6112975f611042565b90505f5b8181101561134d575f6112ae818361104b565b60405163d32c7bb560e01b81526001600160a01b038a811660048301528981166024830152888116604483015260648201889052919091169063d32c7bb590608401602060405180830381865afa15801561130b573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061132f9190611fe5565b905060ff811615611344579250610854915050565b5060010161129b565b505f9695505050505050565b5f5f6113645f611042565b90505f5b81811015611412575f61137b818361104b565b60405163d4ce141560e01b81526001600160a01b038981166004830152888116602483015260448201889052919091169063d4ce141590606401602060405180830381865afa1580156113d0573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906113f49190611fe5565b905060ff8116156114095792506108a4915050565b50600101611368565b505f95945050505050565b6107ae81611429610d97565b6117c5565b6114385f82611656565b61145557604051632cdc3a4160e21b815260040160405180910390fd5b6040516001600160a01b038216907f6d83315c9718799346b67584ec64301b1457e989c8e35a8e2982a7776c04bfc4905f90a250565b5f6001600160e01b03198216637965db0b60e01b148061069757506301ffc9a760e01b6001600160e01b0319831614610697565b7fe5c50d0927e06141e032cb9a67e1d7092dc85c0b0825191f7e1cede6000285686107ae8161141d565b6114f2816117fe565b336001600160a01b0382161480159061152257506001600160a01b0381165f9081526005602052604090205460ff165b156107ae576107ae815f610d39565b5f5f61153d848461185f565b905080156108a4575f848152600760205260409020610dcb90846116d1565b5f36601480821080159061159857507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031633145b156115be576115ab36828403815f612000565b6115b491612027565b60601c9250505090565b339250505090565b5f6115d183836108ab565b1561164f575f8381526006602090815260408083206001600160a01b03861684529091529020805460ff19169055611607610d97565b6001600160a01b0316826001600160a01b0316847ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a4506001610697565b505f610697565b5f6108a4836001600160a01b0384166118ea565b336001600160a01b03821614801561169957506001600160a01b0381165f9081526005602052604090205460ff165b156116a15750565b6107ae610ce3565b6116b35f82610cf4565b156107ae576040516302925f7360e11b815260040160405180910390fd5b5f6108a4836001600160a01b0384166119d4565b6060815f0180548060200260200160405190810160405280929190818152602001828054801561173257602002820191905f5260205f20905b81548152602001906001019080831161171e575b50505050509050919050565b5f825f01828154811061175357611753611e97565b905f5260205f200154905092915050565b6107ae81611a19565b61177681611a72565b611781600382610cf4565b1561179f576040516302925f7360e11b815260040160405180910390fd5b6117a881611a99565b6107ae57604051639952e34360e01b815260040160405180910390fd5b6117cf82826108ab565b61071d5760405163e2517d3f60e01b81526001600160a01b0382166004820152602481018390526044016109a4565b611809600382611656565b61182657604051633477dd1760e01b815260040160405180910390fd5b6040516001600160a01b03821681527f28a4ca7134a3b3f9aff286e79ad3daadb4a06d1b43d037a3a98bdc074edd9b7a90602001610e2e565b5f61186a83836108ab565b61164f575f8381526006602090815260408083206001600160a01b03861684529091529020805460ff191660011790556118a2610d97565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4506001610697565b5f81815260018301602052604081205480156119c4575f61190c600183612067565b85549091505f9061191f90600190612067565b905080821461197e575f865f01828154811061193d5761193d611e97565b905f5260205f200154905080875f01848154811061195d5761195d611e97565b5f918252602080832090910192909255918252600188019052604090208390555b855486908061198f5761198f612086565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f905560019350505050610697565b5f915050610697565b5092915050565b5f81815260018301602052604081205461164f57508154600181810184555f848152602080822090930184905584548482528286019093526040902091909155610697565b5f611a22825490565b90505f5b81811015611a6b57826001015f845f018381548110611a4757611a47611e97565b905f5260205f20015481526020019081526020015f205f9055806001019050611a26565b50505f9055565b6001600160a01b0381166107ae5760405163f9d152fb60e01b815260040160405180910390fd5b5f611aa382611ad6565b611aae57505f919050565b611abf826358d34ba960e11b611b15565b80610697575061069782632497d6cb60e01b611b15565b5f611ae8826301ffc9a760e01b611b15565b15610b9f575f80611b01846001600160e01b0319611b36565b915091508180156108545750159392505050565b5f5f5f611b228585611b36565b91509150818015610b4b5750949350505050565b6301ffc9a760e01b5f818152600483905290819060208260248188617530fa92505f511515601f3d11169150509250929050565b5f60208284031215611b7a575f5ffd5b81356001600160e01b0319811681146108a4575f5ffd5b5f5f83601f840112611ba1575f5ffd5b50813567ffffffffffffffff811115611bb8575f5ffd5b6020830191508360208260051b8501011115611bd2575f5ffd5b9250929050565b5f5f60208385031215611bea575f5ffd5b823567ffffffffffffffff811115611c00575f5ffd5b611c0c85828601611b91565b90969095509350505050565b5f60208284031215611c28575f5ffd5b5035919050565b6001600160a01b03811681146107ae575f5ffd5b5f5f60408385031215611c54575f5ffd5b823591506020830135611c6681611c2f565b809150509250929050565b80151581146107ae575f5ffd5b5f5f60408385031215611c8f575f5ffd5b8235611c9a81611c2f565b91506020830135611c6681611c71565b5f5f5f5f60808587031215611cbd575f5ffd5b8435611cc881611c2f565b93506020850135611cd881611c2f565b92506040850135611ce881611c2f565b9396929550929360600135925050565b5f60208284031215611d08575f5ffd5b81356108a481611c2f565b602080825282518282018190525f918401906040840190835b81811015611d535783516001600160a01b0316835260209384019390920191600101611d2c565b509095945050505050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b5f5f60408385031215611da4575f5ffd5b8235611daf81611c2f565b946020939093013593505050565b60ff811681146107ae575f5ffd5b5f60208284031215611ddb575f5ffd5b81356108a481611dbd565b5f5f5f60608486031215611df8575f5ffd5b8335611e0381611c2f565b92506020840135611e1381611c2f565b929592945050506040919091013590565b5f5f60408385031215611e35575f5ffd5b50508035926020909101359150565b5f5f5f60408486031215611e56575f5ffd5b833567ffffffffffffffff811115611e6c575f5ffd5b611e7886828701611b91565b9094509250506020840135611e8c81611c71565b809150509250925092565b634e487b7160e01b5f52603260045260245ffd5b604080825281018390525f8460608301825b86811015611eed578235611ed081611c2f565b6001600160a01b0316825260209283019290910190600101611ebd565b5080925050508215156020830152949350505050565b5f60208284031215611f13575f5ffd5b81516108a481611c71565b634e487b7160e01b5f52604160045260245ffd5b5f60208284031215611f42575f5ffd5b815167ffffffffffffffff811115611f58575f5ffd5b8201601f81018413611f68575f5ffd5b805167ffffffffffffffff811115611f8257611f82611f1e565b604051601f8201601f19908116603f0116810167ffffffffffffffff81118282101715611fb157611fb1611f1e565b604052818152828201602001861015611fc8575f5ffd5b8160208401602083015e5f91810160200191909152949350505050565b5f60208284031215611ff5575f5ffd5b81516108a481611dbd565b5f5f8585111561200e575f5ffd5b8386111561201a575f5ffd5b5050820193919092039150565b80356bffffffffffffffffffffffff1981169060148410156119cd576bffffffffffffffffffffffff1960149490940360031b84901b1690921692915050565b8181038181111561069757634e487b7160e01b5f52601160045260245ffd5b634e487b7160e01b5f52603160045260245ffdfea2646970667358221220ca066bd06391178820f904abd451b4458561d4bb3c3a2ac24532536ab10ec97c64736f6c63430008250033","sourceMap":"706:1854:31:-:0;;;537:2:80;1188:46:69;;1149:181:31;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;1542:37:15;;;;;1302:5:31;;1309:13;;1731:19:30;;1723:73;;;;-1:-1:-1;;;1723:73:30;;;;;;;;;;;;-1:-1:-1;;;;;1810:27:30;;;1806:83;;1853:25;1864:13;1853:10;:25::i;:::-;1898:37;2232:4:8;1929:5:30;1898:10;:37::i;:::-;-1:-1:-1;2035:31:30;537:2:80;2035:12:30;:31::i;:::-;1663:410;;1149:181:31;;;706:1854;;4440:400:71;-1:-1:-1;;;;;4510:19:71;;4502:64;;;;-1:-1:-1;;;4502:64:71;;;;;;;;;;;;4576:26;4596:5;4576:19;:26::i;:::-;4743:23;:12;4760:5;4743:16;:23::i;:::-;4735:66;;;;-1:-1:-1;;;4735:66:71;;;;;;;;;;;;4816:17;;-1:-1:-1;;;;;743:32:83;;725:51;;4816:17:71;;713:2:83;698:18;4816:17:71;;;;;;;;4440:400;:::o;2778:257:12:-;2864:4;;2895:31;2912:4;2918:7;2895:16;:31::i;:::-;2880:46;;2940:7;2936:69;;;2963:18;;;;:12;:18;;;;;:31;;2986:7;2963:22;:31::i;:::-;;2936:69;3021:7;-1:-1:-1;2778:257:12;;;;;:::o;6050:225:69:-;6126:9;6139:1;6126:14;6118:82;;;;-1:-1:-1;;;6118:82:69;;;;;;;;;;;;6210:9;:21;;;6246:22;;933:25:83;;;6246:22:69;;921:2:83;906:18;6246:22:69;787:177:83;9793:195:28;9887:22;:6;9903:5;9887:15;:22::i;:::-;9886:23;9878:103;;;;-1:-1:-1;;;9878:103:28;;;;;;;;;;;;9793:195;:::o;16462:150:27:-;16532:4;16555:50;16560:3;-1:-1:-1;;;;;16580:23:27;;16555:4;:50::i;6162:316:8:-;6239:4;6260:22;6268:4;6274:7;6260;:22::i;:::-;6255:217;;6298:12;;;;:6;:12;;;;;;;;-1:-1:-1;;;;;6298:29:8;;;;;;;;;:36;;-1:-1:-1;;6298:36:8;6330:4;6298:36;;;6380:12;:10;:12::i;:::-;-1:-1:-1;;;;;6353:40:8;6371:7;-1:-1:-1;;;;;6353:40:8;6365:4;6353:40;;;;;;;;;;-1:-1:-1;6414:4:8;6407:11;;6255:217;-1:-1:-1;6456:5:8;6449:12;;17414:165:27;-1:-1:-1;;;;;17547:23:27;;17494:4;5238:21;;;:14;;;:21;;;;;;:26;;17517:55;5142:129;2538:406;2601:4;5238:21;;;:14;;;:21;;;;;;2617:321;;-1:-1:-1;2659:23:27;;;;;;;;:11;:23;;;;;;;;;;;;;2841:18;;2817:21;;;:14;;;:21;;;;;;:42;;;;2873:11;;3305:349:30;-1:-1:-1;;;;;2920:29:8;;3462:4:30;2920:29:8;;;:12;;:29;:12;:29;;;;;3482:166:30;;;-1:-1:-1;3559:4:30;3552:11;;3482:166;-1:-1:-1;2897:4:8;2920:12;;;:6;:12;;;;;;;;-1:-1:-1;;;;;2920:29:8;;;;;;;;;;;;3594:43:30;;1721:154:31;1808:14;1841:27;:25;:27::i;:::-;1834:34;;1721:154;:::o;2248:471:15:-;2310:7;2354:8;3609:2;2445:37;;;;;;:71;;-1:-1:-1;2486:30:15;2505:10;2486:18;:30::i;:::-;2441:272;;;2583:47;:8;2592:36;;;2583:8;;:47;:::i;:::-;2575:56;;;:::i;:::-;2567:65;;2560:72;;;;2248:471;:::o;2441:272::-;735:10:18;2677:25:15;;;;2248:471;:::o;1874:137::-;1950:4;1986:18;1749:17;;;1666:107;1986:18;-1:-1:-1;;;;;1973:31:15;:9;-1:-1:-1;;;;;1973:31:15;;1966:38;;1874:137;;;:::o;14:177:83:-;93:13;;-1:-1:-1;;;;;135:31:83;;125:42;;115:70;;181:1;178;171:12;115:70;14:177;;;:::o;196:378::-;284:6;292;300;353:2;341:9;332:7;328:23;324:32;321:52;;;369:1;366;359:12;321:52;392:40;422:9;392:40;:::i;:::-;382:50;;451:49;496:2;485:9;481:18;451:49;:::i;:::-;441:59;;519:49;564:2;553:9;549:18;519:49;:::i;:::-;509:59;;196:378;;;;;:::o;969:331::-;1074:9;1085;1127:8;1115:10;1112:24;1109:44;;;1149:1;1146;1139:12;1109:44;1178:6;1168:8;1165:20;1162:40;;;1198:1;1195;1188:12;1162:40;-1:-1:-1;;1224:23:83;;;1269:25;;;;;-1:-1:-1;969:331:83:o;1305:350::-;1426:19;;-1:-1:-1;;;;;;1463:32:83;;;1515:2;1507:11;;1504:145;;;-1:-1:-1;;;;;;1577:2:83;1573:12;;;1570:1;1566:20;1562:50;;;1554:59;;1550:89;;-1:-1:-1;1504:145:83;;1305:350;;;;:::o;:::-;706:1854:31;;;;;;;;;;;;;;;;;;;;;;","linkReferences":{}},"deployedBytecode":{"object":"0x608060405234801561000f575f5ffd5b5060043610610276575f3560e01c80638d2ea77211610156578063c7c24b18116100ca578063db75d01711610084578063db75d0171461060a578063df21950f14610635578063e3c4602c14610648578063e46638e61461065b578063e54621d21461066e578063f76bf55014610676575f5ffd5b8063c7c24b1814610586578063ca15c87314610599578063d32c7bb5146105ac578063d4ce1415146105d1578063d547741f146105e4578063db18af6c146105f7575f5ffd5b8063a217fddf1161011b578063a217fddf14610536578063a3246ad31461053d578063b043572e14610550578063b27aef3a14610558578063bb4b61211461056b578063bc13eacc1461057e575f5ffd5b80638d2ea772146104c35780639010d07c146104d657806391d14854146104e9578063993e8b95146104fc5780639b11c1151461050f575f5ffd5b806352f6747a116101ed5780636a3edf28116101b25780636a3edf281461043c5780636ae728c61461045c5780637157797f146104645780637da0a877146104775780637f4ab1dd1461049d5780638baf29b4146104b0575f5ffd5b806352f6747a1461039357806354e4b945146103a857806354fd4d50146103bb578063572b6c05146103e95780635f8dead314610429575f5ffd5b80633284a9a51161023e5780633284a9a51461032157806336568abe146103345780633a56d6d5146103475780633e5af4ca1461035a5780633ff5aa021461036d57806340db3b5014610380575f5ffd5b806301ffc9a71461027a57806303c26bcd146102a25780631455d0e7146102d7578063248a9ca3146102ec5780632f2ff15d1461030e575b5f5ffd5b61028d610288366004611b6a565b61067e565b60405190151581526020015b60405180910390f35b6102c97fe5c50d0927e06141e032cb9a67e1d7092dc85c0b0825191f7e1cede60002856881565b604051908152602001610299565b6102ea6102e5366004611bd9565b61069d565b005b6102c96102fa366004611c18565b5f9081526006602052604090206001015490565b6102ea61031c366004611c43565b6106eb565b6102ea61032f366004611c7e565b610721565b6102ea610342366004611c43565b61075a565b6102ea610355366004611c18565b61079d565b6102ea610368366004611caa565b6107b1565b6102ea61037b366004611cf8565b6107cb565b6102ea61038e366004611cf8565b6107dd565b61039b6107ef565b6040516102999190611d13565b61028d6103b6366004611cf8565b6107ff565b604080518082019091526009815268332e302e302d72633760b81b60208201525b6040516102999190611d5e565b61028d6103f7366004611cf8565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0390811691161490565b6102ea610437366004611d93565b61080a565b61044461081d565b6040516001600160a01b039091168152602001610299565b6002546102c9565b61028d610472366004611caa565b61083f565b7f0000000000000000000000000000000000000000000000000000000000000000610444565b6103dc6104ab366004611dcb565b61085c565b6102ea6104be366004611de6565b610867565b6102ea6104d1366004611d93565b61087a565b6104446104e4366004611e24565b61088d565b61028d6104f7366004611c43565b6108ab565b61028d61050a366004611cf8565b61091d565b6102c97fea5f4eb72290e50c32abd6c23e45de3d8300b3286e1cbc2e293114b92e034e5e81565b6102c95f81565b61039b61054b366004611c18565b610929565b6102ea610942565b6102ea610566366004611bd9565b610954565b6102ea610579366004611e44565b610a07565b6102c9610ad5565b6102ea610594366004611bd9565b610adf565b6102c96105a7366004611c18565b610b28565b6105bf6105ba366004611caa565b610b3e565b60405160ff9091168152602001610299565b6105bf6105df366004611de6565b610b54565b6102ea6105f2366004611c43565b610b60565b610444610605366004611c18565b610b84565b61028d610618366004611cf8565b6001600160a01b03165f9081526005602052604090205460ff1690565b6102ea610643366004611cf8565b610ba6565b6102ea610656366004611cf8565b610bb7565b61028d610669366004611de6565b610bf9565b61039b610c12565b6102c9600a81565b5f61068882610c1e565b80610697575061069782610cbf565b92915050565b6106a5610ce3565b5f5b818110156106e6576106de8383838181106106c4576106c4611e97565b90506020020160208101906106d99190611cf8565b610ceb565b6001016106a7565b505050565b6106f55f82610cf4565b15610713576040516302925f7360e11b815260040160405180910390fd5b61071d8282610d15565b5050565b610729610ce3565b6001600160a01b0382166107505760405163135217db60e21b815260040160405180910390fd5b61071d8282610d39565b610762610d97565b6001600160a01b0316816001600160a01b0316146107935760405163334bd91960e11b815260040160405180910390fd5b6106e68282610da0565b6107a5610dd3565b6107ae81610ddd565b50565b6107b9610e39565b6107c584848484610e61565b50505050565b6107d481610f03565b6107ae81610f0c565b6107e681610f03565b6107ae81610ceb565b60606107fa5f610f9d565b905090565b5f6106978183610cf4565b610812610e39565b61071d5f8383610fa9565b5f5f6108296003611042565b111561083a576107fa60035f61104b565b505f90565b5f8061084d86868686610b3e565b60ff161490505b949350505050565b606061069782611056565b61086f610e39565b6106e6838383610fa9565b610882610e39565b61071d825f83610fa9565b5f8281526007602052604081206108a4908361104b565b9392505050565b6001600160a01b0381165f9081527f54cdd369e4e8a8515e52ca72ec816c2101831ad1f18bf44102ed171459c9b4f8602052604081205460ff16156108f257506001610697565b505f8281526006602090815260408083206001600160a01b038516845290915290205460ff16610697565b5f610697600383610cf4565b5f81815260076020526040902060609061069790610f9d565b61094a6111cb565b6109526111f5565b565b61095c6111cb565b5f81900361097d576040516359203cb960e01b815260040160405180910390fd5b600254808211156109ad57604051630befc49d60e01b81526004016109a491815260200190565b60405180910390fd5b505f6109b85f611042565b11156109c6576109c66111f5565b5f5b818110156106e6576109ff8383838181106109e5576109e5611e97565b90506020020160208101906109fa9190611cf8565b611226565b6001016109c8565b610a0f610ce3565b5f5b82811015610a94575f848483818110610a2c57610a2c611e97565b9050602002016020810190610a419190611cf8565b90506001600160a01b038116610a6a5760405163135217db60e21b815260040160405180910390fd5b6001600160a01b03165f908152600560205260409020805460ff1916831515179055600101610a11565b507f430881f04f203566ee9b32d6444cf02e1b2a0f17ab6b4263a1ee2074d3d0f483838383604051610ac893929190611eab565b60405180910390a1505050565b5f6107fa5f611042565b610ae7610ce3565b5f5b818110156106e657610b20838383818110610b0657610b06611e97565b9050602002016020810190610b1b9190611cf8565b610f0c565b600101610ae9565b5f81815260076020526040812061069790611042565b5f610b4b8585858561128c565b95945050505050565b5f610854848484611359565b5f82815260066020526040902060010154610b7a8161141d565b6107c58383610da0565b5f610b8e5f611042565b821015610b9f576106975f8361104b565b505f919050565b610bae6111cb565b6107ae8161142e565b610bbf6111cb565b60025480610bcc5f611042565b108190610bef57604051630befc49d60e01b81526004016109a491815260200190565b5061071d82611226565b5f80610c06858585610b54565b60ff1614949350505050565b60606107fa6003610f9d565b5f6001600160e01b031982166320c49ce760e01b1480610c4e57506001600160e01b0319821663157094b960e31b145b80610c6957506001600160e01b031982166378a8de7d60e01b145b80610c8457506001600160e01b03198216630c51264760e21b145b80610c9f57506001600160e01b03198216633235d15f60e11b145b8061069757506001600160e01b03198216637157797f60e01b1492915050565b5f6001600160e01b03198216635a05180f60e01b148061069757506106978261148b565b6109526114bf565b6107ae816114e9565b6001600160a01b0381165f90815260018301602052604081205415156108a4565b5f82815260066020526040902060010154610d2f8161141d565b6107c58383611531565b6001600160a01b0382165f81815260056020908152604091829020805460ff191685151590811790915591519182527f407b412a9b6db334d48445ec9bcad46fb50bc4b2e97f73e963e397101957a729910160405180910390a25050565b5f6107fa61155c565b5f5f610dac84846115c6565b905080156108a4575f848152600760205260409020610dcb9084611656565b509392505050565b5f6107ae8161141d565b805f03610dfd57604051631e69e71760e21b815260040160405180910390fd5b60028190556040518181527f2292ad4720fff63e2bd104c6b1c0d72c2c729a6001c8ab4bb947cbcc51109863906020015b60405180910390a150565b610e44600333610cf4565b61095257604051630599c0e960e01b815260040160405180910390fd5b5f610e6b5f611042565b90505f5b81811015610efb57610e815f8261104b565b604051631f2d7a6560e11b81526001600160a01b03888116600483015287811660248301528681166044830152606482018690529190911690633e5af4ca906084015f604051808303815f87803b158015610eda575f5ffd5b505af1158015610eec573d5f5f3e3d5ffd5b50505050806001019050610e6f565b505050505050565b6107ae8161166a565b6001600160a01b038116610f335760405163135217db60e21b815260040160405180910390fd5b610f3c816116a9565b610f476003826116d1565b610f64576040516371b3c56560e11b815260040160405180910390fd5b6040516001600160a01b03821681527f2de35142b19ed5a07796cf30791959c592018f70b1d2d7c460eef8ffe713692b90602001610e2e565b60605f6108a4836116e5565b5f610fb35f611042565b90505f5b8181101561103b57610fc95f8261104b565b6040516322ebca6d60e21b81526001600160a01b0387811660048301528681166024830152604482018690529190911690638baf29b4906064015f604051808303815f87803b15801561101a575f5ffd5b505af115801561102c573d5f5f3e3d5ffd5b50505050806001019050610fb7565b5050505050565b5f610697825490565b5f6108a4838361173e565b606060ff821661108957505060408051808201909152600d81526c2737a932b9ba3934b1ba34b7b760991b602082015290565b5f6110935f611042565b90505f5b8181101561118f575f6110aa818361104b565b604051633e822efb60e11b815260ff871660048201529091506001600160a01b03821690637d045df690602401602060405180830381865afa1580156110f2573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111169190611f03565b1561118657604051637f4ab1dd60e01b815260ff861660048201526001600160a01b03821690637f4ab1dd906024015f60405180830381865afa15801561115f573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610b4b9190810190611f32565b50600101611097565b505060408051808201909152601881527f556e6b6e6f776e207265737472696374696f6e20636f64650000000000000000602082015292915050565b7fea5f4eb72290e50c32abd6c23e45de3d8300b3286e1cbc2e293114b92e034e5e6107ae8161141d565b6040517fdbf61473843cd9be1c9791ce51ef66d0da6c9026d62ba80c1ca433b13fb729b2905f90a16109525f611764565b61122f8161176d565b6112395f826116d1565b6112565760405163cc790a4b60e01b815260040160405180910390fd5b6040516001600160a01b038216907f60305ce6c9104acd0969d358f926bf391174340660aaf5e6215261fd6847bf46905f90a250565b5f5f6112975f611042565b90505f5b8181101561134d575f6112ae818361104b565b60405163d32c7bb560e01b81526001600160a01b038a811660048301528981166024830152888116604483015260648201889052919091169063d32c7bb590608401602060405180830381865afa15801561130b573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061132f9190611fe5565b905060ff811615611344579250610854915050565b5060010161129b565b505f9695505050505050565b5f5f6113645f611042565b90505f5b81811015611412575f61137b818361104b565b60405163d4ce141560e01b81526001600160a01b038981166004830152888116602483015260448201889052919091169063d4ce141590606401602060405180830381865afa1580156113d0573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906113f49190611fe5565b905060ff8116156114095792506108a4915050565b50600101611368565b505f95945050505050565b6107ae81611429610d97565b6117c5565b6114385f82611656565b61145557604051632cdc3a4160e21b815260040160405180910390fd5b6040516001600160a01b038216907f6d83315c9718799346b67584ec64301b1457e989c8e35a8e2982a7776c04bfc4905f90a250565b5f6001600160e01b03198216637965db0b60e01b148061069757506301ffc9a760e01b6001600160e01b0319831614610697565b7fe5c50d0927e06141e032cb9a67e1d7092dc85c0b0825191f7e1cede6000285686107ae8161141d565b6114f2816117fe565b336001600160a01b0382161480159061152257506001600160a01b0381165f9081526005602052604090205460ff165b156107ae576107ae815f610d39565b5f5f61153d848461185f565b905080156108a4575f848152600760205260409020610dcb90846116d1565b5f36601480821080159061159857507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031633145b156115be576115ab36828403815f612000565b6115b491612027565b60601c9250505090565b339250505090565b5f6115d183836108ab565b1561164f575f8381526006602090815260408083206001600160a01b03861684529091529020805460ff19169055611607610d97565b6001600160a01b0316826001600160a01b0316847ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a4506001610697565b505f610697565b5f6108a4836001600160a01b0384166118ea565b336001600160a01b03821614801561169957506001600160a01b0381165f9081526005602052604090205460ff165b156116a15750565b6107ae610ce3565b6116b35f82610cf4565b156107ae576040516302925f7360e11b815260040160405180910390fd5b5f6108a4836001600160a01b0384166119d4565b6060815f0180548060200260200160405190810160405280929190818152602001828054801561173257602002820191905f5260205f20905b81548152602001906001019080831161171e575b50505050509050919050565b5f825f01828154811061175357611753611e97565b905f5260205f200154905092915050565b6107ae81611a19565b61177681611a72565b611781600382610cf4565b1561179f576040516302925f7360e11b815260040160405180910390fd5b6117a881611a99565b6107ae57604051639952e34360e01b815260040160405180910390fd5b6117cf82826108ab565b61071d5760405163e2517d3f60e01b81526001600160a01b0382166004820152602481018390526044016109a4565b611809600382611656565b61182657604051633477dd1760e01b815260040160405180910390fd5b6040516001600160a01b03821681527f28a4ca7134a3b3f9aff286e79ad3daadb4a06d1b43d037a3a98bdc074edd9b7a90602001610e2e565b5f61186a83836108ab565b61164f575f8381526006602090815260408083206001600160a01b03861684529091529020805460ff191660011790556118a2610d97565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4506001610697565b5f81815260018301602052604081205480156119c4575f61190c600183612067565b85549091505f9061191f90600190612067565b905080821461197e575f865f01828154811061193d5761193d611e97565b905f5260205f200154905080875f01848154811061195d5761195d611e97565b5f918252602080832090910192909255918252600188019052604090208390555b855486908061198f5761198f612086565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f905560019350505050610697565b5f915050610697565b5092915050565b5f81815260018301602052604081205461164f57508154600181810184555f848152602080822090930184905584548482528286019093526040902091909155610697565b5f611a22825490565b90505f5b81811015611a6b57826001015f845f018381548110611a4757611a47611e97565b905f5260205f20015481526020019081526020015f205f9055806001019050611a26565b50505f9055565b6001600160a01b0381166107ae5760405163f9d152fb60e01b815260040160405180910390fd5b5f611aa382611ad6565b611aae57505f919050565b611abf826358d34ba960e11b611b15565b80610697575061069782632497d6cb60e01b611b15565b5f611ae8826301ffc9a760e01b611b15565b15610b9f575f80611b01846001600160e01b0319611b36565b915091508180156108545750159392505050565b5f5f5f611b228585611b36565b91509150818015610b4b5750949350505050565b6301ffc9a760e01b5f818152600483905290819060208260248188617530fa92505f511515601f3d11169150509250929050565b5f60208284031215611b7a575f5ffd5b81356001600160e01b0319811681146108a4575f5ffd5b5f5f83601f840112611ba1575f5ffd5b50813567ffffffffffffffff811115611bb8575f5ffd5b6020830191508360208260051b8501011115611bd2575f5ffd5b9250929050565b5f5f60208385031215611bea575f5ffd5b823567ffffffffffffffff811115611c00575f5ffd5b611c0c85828601611b91565b90969095509350505050565b5f60208284031215611c28575f5ffd5b5035919050565b6001600160a01b03811681146107ae575f5ffd5b5f5f60408385031215611c54575f5ffd5b823591506020830135611c6681611c2f565b809150509250929050565b80151581146107ae575f5ffd5b5f5f60408385031215611c8f575f5ffd5b8235611c9a81611c2f565b91506020830135611c6681611c71565b5f5f5f5f60808587031215611cbd575f5ffd5b8435611cc881611c2f565b93506020850135611cd881611c2f565b92506040850135611ce881611c2f565b9396929550929360600135925050565b5f60208284031215611d08575f5ffd5b81356108a481611c2f565b602080825282518282018190525f918401906040840190835b81811015611d535783516001600160a01b0316835260209384019390920191600101611d2c565b509095945050505050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b5f5f60408385031215611da4575f5ffd5b8235611daf81611c2f565b946020939093013593505050565b60ff811681146107ae575f5ffd5b5f60208284031215611ddb575f5ffd5b81356108a481611dbd565b5f5f5f60608486031215611df8575f5ffd5b8335611e0381611c2f565b92506020840135611e1381611c2f565b929592945050506040919091013590565b5f5f60408385031215611e35575f5ffd5b50508035926020909101359150565b5f5f5f60408486031215611e56575f5ffd5b833567ffffffffffffffff811115611e6c575f5ffd5b611e7886828701611b91565b9094509250506020840135611e8c81611c71565b809150509250925092565b634e487b7160e01b5f52603260045260245ffd5b604080825281018390525f8460608301825b86811015611eed578235611ed081611c2f565b6001600160a01b0316825260209283019290910190600101611ebd565b5080925050508215156020830152949350505050565b5f60208284031215611f13575f5ffd5b81516108a481611c71565b634e487b7160e01b5f52604160045260245ffd5b5f60208284031215611f42575f5ffd5b815167ffffffffffffffff811115611f58575f5ffd5b8201601f81018413611f68575f5ffd5b805167ffffffffffffffff811115611f8257611f82611f1e565b604051601f8201601f19908116603f0116810167ffffffffffffffff81118282101715611fb157611fb1611f1e565b604052818152828201602001861015611fc8575f5ffd5b8160208401602083015e5f91810160200191909152949350505050565b5f60208284031215611ff5575f5ffd5b81516108a481611dbd565b5f5f8585111561200e575f5ffd5b8386111561201a575f5ffd5b5050820193919092039150565b80356bffffffffffffffffffffffff1981169060148410156119cd576bffffffffffffffffffffffff1960149490940360031b84901b1690921692915050565b8181038181111561069757634e487b7160e01b5f52601160045260245ffd5b634e487b7160e01b5f52603160045260245ffdfea2646970667358221220ca066bd06391178820f904abd451b4458561d4bb3c3a2ac24532536ab10ec97c64736f6c63430008250033","sourceMap":"706:1854:31:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;3893:296:30;;;;;;:::i;:::-;;:::i;:::-;;;470:14:83;;463:22;445:41;;433:2;418:18;3893:296:30;;;;;;;;369:86:75;;419:36;369:86;;;;;643:25:83;;;631:2;616:18;369:86:75;497:177:83;1872:205:70;;;;;;:::i;:::-;;:::i;:::-;;3776:120:8;;;;;;:::i;:::-;3841:7;3867:12;;;:6;:12;;;;;:22;;;;3776:120;2709:275:30;;;;;;:::i;:::-;;:::i;2125:251:70:-;;;;;;:::i;:::-;;:::i;5311:245:8:-;;;;;;:::i;:::-;;:::i;3487:150:69:-;;;;;;:::i;:::-;;:::i;2583:330:28:-;;;;;;:::i;:::-;;:::i;2979:137:71:-;;;;;;:::i;:::-;;:::i;3404:141::-;;;;;;:::i;:::-;;:::i;5029:136:69:-;;;:::i;:::-;;;;;;;:::i;4333:158::-;;;;;;:::i;:::-;;:::i;737:129:72:-;852:7;;;;;;;;;;;;-1:-1:-1;;;852:7:72;;;;737:129;;;;;;;:::i;1874:137:15:-;;;;;;:::i;:::-;1749:17;-1:-1:-1;;;;;1973:31:15;;;;;;;1874:137;3239:155:28;;;;;;:::i;:::-;;:::i;2211:383:68:-;;;:::i;:::-;;;-1:-1:-1;;;;;5748:32:83;;;5730:51;;5718:2;5703:18;2211:383:68;5584:203:83;3949:124:69;4057:9;;3949:124;;5266:311:28;;;;;;:::i;:::-;;:::i;1666:107:15:-;1749:17;1666:107;;4621:240:28;;;;;;:::i;:::-;;:::i;2982:212::-;;;;;;:::i;:::-;;:::i;3439:161::-;;;;;;:::i;:::-;;:::i;1555:143:12:-;;;;;;:::i;:::-;;:::i;3305:349:30:-;;;;;;:::i;:::-;;:::i;3636:133:71:-;;;;;;:::i;:::-;;:::i;357:82:81:-;;405:34;357:82;;2187:49:8;;2232:4;2187:49;;2540:136:12;;;;;;:::i;:::-;;:::i;2691:117:69:-;;;:::i;2150:477::-;;;;;;:::i;:::-;;:::i;2424:478:70:-;;;;;;:::i;:::-;;:::i;4137:132:69:-;;;:::i;1623:201:70:-;;;;;;:::i;:::-;;:::i;1866:131:12:-;;;;;;:::i;:::-;;:::i;4289:282:28:-;;;;;;:::i;:::-;;:::i;:::-;;;8405:4:83;8393:17;;;8375:36;;8363:2;8348:18;4289:282:28;8233:184:83;3991:242:28;;;;;;:::i;:::-;;:::i;4608:138:8:-;;;;;;:::i;:::-;;:::i;4555:410:69:-;;;;;;:::i;:::-;;:::i;3001:151:70:-;;;;;;:::i;:::-;-1:-1:-1;;;;;3113:32:70;3090:4;3113:32;;;:25;:32;;;;;;;;;3001:151;3701:133:69;;;;;;:::i;:::-;;:::i;3040:383::-;;;;;;:::i;:::-;;:::i;4925:281:28:-;;;;;;:::i;:::-;;:::i;3200:127:70:-;;;:::i;493:46:80:-;;537:2;493:46;;3893:296:30;4052:4;4079:45;4112:11;4079:32;:45::i;:::-;:103;;;;4128:54;4170:11;4128:41;:54::i;:::-;4072:110;3893:296;-1:-1:-1;;3893:296:30:o;1872:205:70:-;2185:26:71;:24;:26::i;:::-;1984:9:70::1;1979:92;1999:17:::0;;::::1;1979:92;;;2037:23;2050:6;;2057:1;2050:9;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;2037:12;:23::i;:::-;2018:3;;1979:92;;;;1872:205:::0;;:::o;2709:275:30:-;2833:24;:6;2849:7;2833:15;:24::i;:::-;2832:25;2824:105;;;;-1:-1:-1;;;2824:105:30;;;;;;;;;;;;2939:38;2963:4;2969:7;2939:23;:38::i;:::-;2709:275;;:::o;2125:251:70:-;2185:26:71;:24;:26::i;:::-;-1:-1:-1;;;;;2258:19:70;::::1;2250:64;;;;-1:-1:-1::0;;;2250:64:70::1;;;;;;;;;;;;2324:45;2353:5;2360:8;2324:28;:45::i;5311:245:8:-:0;5426:12;:10;:12::i;:::-;-1:-1:-1;;;;;5404:34:8;:18;-1:-1:-1;;;;;5404:34:8;;5400:102;;5461:30;;-1:-1:-1;;;5461:30:8;;;;;;;;;;;5400:102;5512:37;5524:4;5530:18;5512:11;:37::i;3487:150:69:-;880:24;:22;:24::i;:::-;3607:23:::1;3620:9;3607:12;:23::i;:::-;3487:150:::0;:::o;2583:330:28:-;2002:18:71;:16;:18::i;:::-;2846:60:28::1;2881:7;2890:4;2896:2;2900:5;2846:34;:60::i;:::-;2583:330:::0;;;;:::o;2979:137:71:-;3047:35;3076:5;3047:28;:35::i;:::-;3092:17;3103:5;3092:10;:17::i;3404:141::-;3474:35;3503:5;3474:28;:35::i;:::-;3519:19;3532:5;3519:12;:19::i;5029:136:69:-;5108:16;5143:15;:6;:13;:15::i;:::-;5136:22;;5029:136;:::o;4333:158::-;4430:4;4453:31;4430:4;4477:5;4453:15;:31::i;3239:155:28:-;2002:18:71;:16;:18::i;:::-;3352:35:28::1;3373:1;3377:2;3381:5;3352:12;:35::i;2211:383:68:-:0;2274:7;2321:1;2297:21;:12;:19;:21::i;:::-;:25;2293:295;;;2510:19;:12;2527:1;2510:16;:19::i;2293:295::-;-1:-1:-1;2575:1:68;;2211:383::o;5266:311:28:-;5447:4;;5474:55;5504:7;5513:4;5519:2;5523:5;5474:29;:55::i;:::-;:96;;;5467:103;;5266:311;;;;;;;:::o;4621:240::-;4771:13;4807:47;4838:15;4807:30;:47::i;2982:212::-;2002:18:71;:16;:18::i;:::-;3158:29:28::1;3171:4;3177:2;3181:5;3158:12;:29::i;3439:161::-:0;2002:18:71;:16;:18::i;:::-;3556:37:28::1;3569:4;3583:1;3587:5;3556:12;:37::i;1555:143:12:-:0;1636:7;1662:18;;;:12;:18;;;;;:29;;1685:5;1662:22;:29::i;:::-;1655:36;1555:143;-1:-1:-1;;;1555:143:12:o;3305:349:30:-;-1:-1:-1;;;;;2920:29:8;;3462:4:30;2920:29:8;;;:12;;:29;:12;:29;;;;;3482:166:30;;;-1:-1:-1;3559:4:30;3552:11;;3482:166;-1:-1:-1;2897:4:8;2920:12;;;:6;:12;;;;;;;;-1:-1:-1;;;;;2920:29:8;;;;;;;;;;;;3594:43:30;;3636:133:71;3711:4;3734:28;:12;3756:5;3734:21;:28::i;2540:136:12:-;2642:18;;;;:12;:18;;;;;2607:16;;2642:27;;:25;:27::i;2691:117:69:-;794:19;:17;:19::i;:::-;2788:13:::1;:11;:13::i;:::-;2691:117::o:0;2150:477::-;794:19;:17;:19::i;:::-;2293:1:::1;2276:18:::0;;;2268:76:::1;;;;-1:-1:-1::0;;;2268:76:69::1;;;;;;;;;;;;2379:9;::::0;2362:26;;::::1;;2354:97;;;;-1:-1:-1::0;;;2354:97:69::1;;;;;;643:25:83::0;;631:2;616:18;;497:177;2354:97:69::1;;;;;;;;;;2483:1;2465:15;:6;:13;:15::i;:::-;:19;2461:63;;;2500:13;:11;:13::i;:::-;2538:9;2533:88;2553:17:::0;;::::1;2533:88;;;2591:19;2600:6;;2607:1;2600:9;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;2591:8;:19::i;:::-;2572:3;;2533:88;;2424:478:70::0;2185:26:71;:24;:26::i;:::-;2607:9:70::1;2602:229;2622:17:::0;;::::1;2602:229;;;2660:13;2676:6;;2683:1;2676:9;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;2660:25:::0;-1:-1:-1;;;;;;2707:19:70;::::1;2699:64;;;;-1:-1:-1::0;;;2699:64:70::1;;;;;;;;;;;;-1:-1:-1::0;;;;;2777:32:70::1;;::::0;;;:25:::1;:32;::::0;;;;:43;;-1:-1:-1;;2777:43:70::1;::::0;::::1;;;::::0;;-1:-1:-1;2641:3:70::1;2602:229;;;;2845:50;2878:6;;2886:8;2845:50;;;;;;;;:::i;:::-;;;;;;;;2424:478:::0;;;:::o;4137:132:69:-;4221:7;4247:15;:6;:13;:15::i;1623:201:70:-;2185:26:71;:24;:26::i;:::-;1733:9:70::1;1728:90;1748:17:::0;;::::1;1728:90;;;1786:21;1797:6;;1804:1;1797:9;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;1786:10;:21::i;:::-;1767:3;;1728:90;;1866:131:12::0;1937:7;1963:18;;;:12;:18;;;;;:27;;:25;:27::i;4289:282:28:-;4480:5;4508:56;4539:7;4548:4;4554:2;4558:5;4508:30;:56::i;:::-;4501:63;4289:282;-1:-1:-1;;;;;4289:282:28:o;3991:242::-;4155:5;4183:43;4210:4;4216:2;4220:5;4183:26;:43::i;4608:138:8:-;3841:7;3867:12;;;:6;:12;;;;;:22;;;2464:16;2475:4;2464:10;:16::i;:::-;4713:26:::1;4725:4;4731:7;4713:11;:26::i;4555:410:69:-:0;4647:7;4679:15;:6;:13;:15::i;:::-;4670:6;:24;4666:293;;;4882:18;:6;4893;4882:10;:18::i;4666:293::-;-1:-1:-1;4946:1:69;;4555:410;-1:-1:-1;4555:410:69:o;3701:133::-;794:19;:17;:19::i;:::-;3809:18:::1;3821:5;3809:11;:18::i;3040:383::-:0;794:19;:17;:19::i;:::-;3274:9:::1;::::0;;3301:15:::1;3254:17;3301:13;:15::i;:::-;:27;3380:9;3293:98;;;;;-1:-1:-1::0;;;3293:98:69::1;;;;;;643:25:83::0;;631:2;616:18;;497:177;3293:98:69::1;;3401:15;3410:5;3401:8;:15::i;4925:281:28:-:0;5089:4;;5116:42;5142:4;5148:2;5152:5;5116:25;:42::i;:::-;:83;;;;4925:281;-1:-1:-1;;;;4925:281:28:o;3200:127:70:-;3264:16;3299:21;:12;:19;:21::i;11440:599:28:-;11533:4;-1:-1:-1;;;;;;11556:61:28;;-1:-1:-1;;;11556:61:28;;:132;;-1:-1:-1;;;;;;;11633:55:28;;-1:-1:-1;;;11633:55:28;11556:132;:214;;;-1:-1:-1;;;;;;;11704:66:28;;-1:-1:-1;;;11704:66:28;11556:214;:298;;;-1:-1:-1;;;;;;;11786:68:28;;-1:-1:-1;;;11786:68:28;11556:298;:391;;;-1:-1:-1;;;;;;;11870:77:28;;-1:-1:-1;;;11870:77:28;11556:391;:476;;;-1:-1:-1;;;;;;;11963:69:28;;-1:-1:-1;;;11963:69:28;11549:483;11440:599;-1:-1:-1;;11440:599:28:o;758:212:12:-;843:4;-1:-1:-1;;;;;;866:57:12;;-1:-1:-1;;;866:57:12;;:97;;;927:36;951:11;927:23;:36::i;2998:103:68:-;3070:24;:22;:24::i;2008:174:67:-;2129:46;2169:5;2129:39;:46::i;17414:165:27:-;-1:-1:-1;;;;;17547:23:27;;17494:4;5238:21;;;:14;;;:21;;;;;;:26;;17517:55;5142:129;4192:136:8;3841:7;3867:12;;;:6;:12;;;;;:22;;;2464:16;2475:4;2464:10;:16::i;:::-;4296:25:::1;4307:4;4313:7;4296:10;:25::i;4883:204:70:-:0;-1:-1:-1;;;;;4978:32:70;;;;;;:25;:32;;;;;;;;;:43;;-1:-1:-1;;4978:43:70;;;;;;;;;;5036:44;;445:41:83;;;5036:44:70;;418:18:83;5036:44:70;;;;;;;4883:204;;:::o;1721:154:31:-;1808:14;1841:27;:25;:27::i;3138:262:12:-;3225:4;3241:12;3256:32;3274:4;3280:7;3256:17;:32::i;:::-;3241:47;;3302:7;3298:72;;;3325:18;;;;:12;:18;;;;;:34;;3351:7;3325:25;:34::i;:::-;;3386:7;3138:262;-1:-1:-1;;;3138:262:12:o;4896:91:30:-;2232:4:8;2464:16;2232:4;2464:10;:16::i;6050:225:69:-;6126:9;6139:1;6126:14;6118:82;;;;-1:-1:-1;;;6118:82:69;;;;;;;;;;;;6210:9;:21;;;6246:22;;643:25:83;;;6246:22:69;;631:2:83;616:18;6246:22:69;;;;;;;;6050:225;:::o;6902:144:71:-;6970:33;:12;6992:10;6970:21;:33::i;:::-;6962:77;;;;-1:-1:-1;;;6962:77:71;;;;;;;;;;;9164:285:69;9271:19;9293:15;:6;:13;:15::i;:::-;9271:37;-1:-1:-1;9323:9:69;9318:125;9342:11;9338:1;:15;9318:125;;;9380:13;:6;9391:1;9380:10;:13::i;:::-;9374:58;;-1:-1:-1;;;9374:58:69;;-1:-1:-1;;;;;9711:32:83;;;9374:58:69;;;9693:51:83;9780:32;;;9760:18;;;9753:60;9849:32;;;9829:18;;;9822:60;9898:18;;;9891:34;;;9374:32:69;;;;;;;9665:19:83;;9374:58:69;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;9355:3;;;;;9318:125;;;;9261:188;9164:285;;;;:::o;1475:234:67:-;1640:62;1696:5;1640:55;:62::i;4440:400:71:-;-1:-1:-1;;;;;4510:19:71;;4502:64;;;;-1:-1:-1;;;4502:64:71;;;;;;;;;;;;4576:26;4596:5;4576:19;:26::i;:::-;4743:23;:12;4760:5;4743:16;:23::i;:::-;4735:66;;;;-1:-1:-1;;;4735:66:71;;;;;;;;;;;;4816:17;;-1:-1:-1;;;;;5748:32:83;;5730:51;;4816:17:71;;5718:2:83;5703:18;4816:17:71;5584:203:83;19500:273:27;19563:16;19591:22;19616:19;19624:3;19616:7;:19::i;8250:259:69:-;8340:19;8362:15;:6;:13;:15::i;:::-;8340:37;-1:-1:-1;8392:9:69;8387:116;8411:11;8407:1;:15;8387:116;;;8449:13;:6;8460:1;8449:10;:13::i;:::-;8443:49;;-1:-1:-1;;;8443:49:69;;-1:-1:-1;;;;;10156:32:83;;;8443:49:69;;;10138:51:83;10225:32;;;10205:18;;;10198:60;10274:18;;;10267:34;;;8443:32:69;;;;;;;10111:18:83;;8443:49:69;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8424:3;;;;;8387:116;;;;8330:179;8250:259;;;:::o;17660:115:27:-;17723:7;17749:19;17757:3;5434:18;;5352:107;18802:158;18877:7;18927:23;18932:3;18944:5;18927:4;:23::i;8179:594:28:-;8273:13;8302:56;;;8298:110;;-1:-1:-1;;8381:16:28;;;;;;;;;;;;-1:-1:-1;;;8381:16:28;;;;;8179:594::o;8298:110::-;8417:19;8439:15;:6;:13;:15::i;:::-;8417:37;-1:-1:-1;8469:9:28;8464:267;8488:11;8484:1;:15;8464:267;;;8520:11;8540:13;8520:11;8551:1;8540:10;:13::i;:::-;8572:55;;-1:-1:-1;;;8572:55:28;;8405:4:83;8393:17;;8572:55:28;;;8375:36:83;8520:34:28;;-1:-1:-1;;;;;;8572:38:28;;;;;8348:18:83;;8572:55:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;8568:153;;;8654:52;;-1:-1:-1;;;8654:52:28;;8405:4:83;8393:17;;8654:52:28;;;8375:36:83;-1:-1:-1;;;;;8654:35:28;;;;;8348:18:83;;8654:52:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;8654:52:28;;;;;;;;;;;;:::i;8568:153::-;-1:-1:-1;8501:3:28;;8464:267;;;-1:-1:-1;;8747:19:28;;;;;;;;;;;;;;;;;;8179:594;-1:-1:-1;;8179:594:28:o;4697:89:30:-;405:34:81;2464:16:8;2475:4;2464:10;:16::i;5444:98:69:-;5499:12;;;;;;;5521:14;:6;:12;:14::i;6762:312::-;6820:26;6839:5;6820:10;:26::i;:::-;6957;:6;6976:5;6957:10;:26::i;:::-;6949:89;;;;-1:-1:-1;;;6949:89:69;;;;;;;;;;;;7053:14;;-1:-1:-1;;;;;7053:14:69;;;;;;;;6762:312;:::o;6974:537:28:-;7135:5;7156:19;7178:15;:6;:13;:15::i;:::-;7156:37;-1:-1:-1;7208:9:28;7203:248;7227:11;7223:1;:15;7203:248;;;7259:17;7285:13;7259:17;7296:1;7285:10;:13::i;:::-;7279:76;;-1:-1:-1;;;7279:76:28;;-1:-1:-1;;;;;9711:32:83;;;7279:76:28;;;9693:51:83;9780:32;;;9760:18;;;9753:60;9849:32;;;9829:18;;;9822:60;9898:18;;;9891:34;;;7279:50:28;;;;;;;9665:19:83;;7279:76:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;7259:96;-1:-1:-1;7373:15:28;;;;7369:72;;7415:11;-1:-1:-1;7408:18:28;;-1:-1:-1;;7408:18:28;7369:72;-1:-1:-1;7240:3:28;;7203:248;;;-1:-1:-1;7473:30:28;7460:44;6974:537;-1:-1:-1;;;;;;6974:537:28:o;6110:467::-;6218:5;6235:19;6257:15;:6;:13;:15::i;:::-;6235:37;-1:-1:-1;6287:9:28;6282:235;6306:11;6302:1;:15;6282:235;;;6338:17;6364:13;6338:17;6375:1;6364:10;:13::i;:::-;6358:63;;-1:-1:-1;;;6358:63:28;;-1:-1:-1;;;;;10156:32:83;;;6358:63:28;;;10138:51:83;10225:32;;;10205:18;;;10198:60;10274:18;;;10267:34;;;6358:46:28;;;;;;;10111:18:83;;6358:63:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;6338:83;-1:-1:-1;6439:15:28;;;;6435:72;;6481:11;-1:-1:-1;6474:18:28;;-1:-1:-1;;6474:18:28;6435:72;-1:-1:-1;6319:3:28;;6282:235;;;-1:-1:-1;6539:30:28;6526:44;6110:467;-1:-1:-1;;;;;6110:467:28:o;3165:103:8:-;3231:30;3242:4;3248:12;:10;:12::i;:::-;3231:10;:30::i;7335:255:69:-;7470:29;:6;7492:5;7470:13;:29::i;:::-;7462:89;;;;-1:-1:-1;;;7462:89:69;;;;;;;;;;;;7566:17;;-1:-1:-1;;;;;7566:17:69;;;;;;;;7335:255;:::o;2531:202:8:-;2616:4;-1:-1:-1;;;;;;2639:47:8;;-1:-1:-1;;;2639:47:8;;:87;;-1:-1:-1;;;;;;;;;;829:40:22;;;2690:36:8;730:146:22;4492:96:30;419:36:75;2464:16:8;2475:4;2464:10;:16::i;4275:255:70:-;4348:38;4380:5;4348:31;:38::i;:::-;4400:10;-1:-1:-1;;;;;4400:19:70;;;;;;:55;;-1:-1:-1;;;;;;4423:32:70;;;;;;:25;:32;;;;;;;;4400:55;4396:128;;;4471:42;4500:5;4507;4471:28;:42::i;2778:257:12:-;2864:4;2880:12;2895:31;2912:4;2918:7;2895:16;:31::i;:::-;2880:46;;2940:7;2936:69;;;2963:18;;;;:12;:18;;;;;:31;;2986:7;2963:22;:31::i;2248:471:15:-;2310:7;2354:8;3609:2;2445:37;;;;;;:71;;-1:-1:-1;1749:17:15;-1:-1:-1;;;;;1973:31:15;2505:10;1973:31;2486:30;2441:272;;;2583:47;:8;2592:36;;;2583:8;;:47;:::i;:::-;2575:56;;;:::i;:::-;2567:65;;2560:72;;;;2248:471;:::o;2441:272::-;735:10:18;2677:25:15;;;;2248:471;:::o;6715:317:8:-;6793:4;6813:22;6821:4;6827:7;6813;:22::i;:::-;6809:217;;;6883:5;6851:12;;;:6;:12;;;;;;;;-1:-1:-1;;;;;6851:29:8;;;;;;;;;:37;;-1:-1:-1;;6851:37:8;;;6934:12;:10;:12::i;:::-;-1:-1:-1;;;;;6907:40:8;6925:7;-1:-1:-1;;;;;6907:40:8;6919:4;6907:40;;;;;;;;;;-1:-1:-1;6968:4:8;6961:11;;6809:217;-1:-1:-1;7010:5:8;7003:12;;16780:156:27;16853:4;16876:53;16884:3;-1:-1:-1;;;;;16904:23:27;;16876:7;:53::i;5759:223:70:-;5852:10;-1:-1:-1;;;;;5852:19:70;;;:55;;;;-1:-1:-1;;;;;;5875:32:70;;;;;;:25;:32;;;;;;;;5852:55;5848:92;;;5759:223;:::o;5848:92::-;5949:26;:24;:26::i;9793:195:28:-;9887:22;:6;9903:5;9887:15;:22::i;:::-;9886:23;9878:103;;;;-1:-1:-1;;;9878:103:28;;;;;;;;;;;16462:150:27;16532:4;16555:50;16560:3;-1:-1:-1;;;;;16580:23:27;;16555:4;:50::i;6460:109::-;6516:16;6551:3;:11;;6544:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6460:109;;;:::o;5801:119::-;5869:7;5895:3;:11;;5907:5;5895:18;;;;;;;;:::i;:::-;;;;;;;;;5888:25;;5801:119;;;;:::o;17250:83::-;17308:18;17315:3;17308:6;:18::i;9061:324:28:-;9137:39;9170:5;9137:32;:39::i;:::-;9195:28;:12;9217:5;9195:21;:28::i;:::-;9194:29;9186:109;;;;-1:-1:-1;;;9186:109:28;;;;;;;;;;;;9313:29;9336:5;9313:22;:29::i;:::-;9305:73;;;;-1:-1:-1;;;9305:73:28;;;;;;;;;;;3398:197:8;3486:22;3494:4;3500:7;3486;:22::i;:::-;3481:108;;3531:47;;-1:-1:-1;;;3531:47:8;;-1:-1:-1;;;;;12793:32:83;;3531:47:8;;;12775:51:83;12842:18;;;12835:34;;;12748:18;;3531:47:8;12601:274:83;5410:294:71;5605:26;:12;5625:5;5605:19;:26::i;:::-;5597:65;;;;-1:-1:-1;;;5597:65:71;;;;;;;;;;;;5678:19;;-1:-1:-1;;;;;5748:32:83;;5730:51;;5678:19:71;;5718:2:83;5703:18;5678:19:71;5584:203:83;6162:316:8;6239:4;6260:22;6268:4;6274:7;6260;:22::i;:::-;6255:217;;6298:12;;;;:6;:12;;;;;;;;-1:-1:-1;;;;;6298:29:8;;;;;;;;;:36;;-1:-1:-1;;6298:36:8;6330:4;6298:36;;;6380:12;:10;:12::i;:::-;-1:-1:-1;;;;;6353:40:8;6371:7;-1:-1:-1;;;;;6353:40:8;6365:4;6353:40;;;;;;;;;;-1:-1:-1;6414:4:8;6407:11;;3112:1368:27;3178:4;3307:21;;;:14;;;:21;;;;;;3343:13;;3339:1135;;3710:18;3731:12;3742:1;3731:8;:12;:::i;:::-;3777:18;;3710:33;;-1:-1:-1;3757:17:27;;3777:22;;3798:1;;3777:22;:::i;:::-;3757:42;;3832:9;3818:10;:23;3814:378;;3861:17;3881:3;:11;;3893:9;3881:22;;;;;;;;:::i;:::-;;;;;;;;;3861:42;;4028:9;4002:3;:11;;4014:10;4002:23;;;;;;;;:::i;:::-;;;;;;;;;;;;:35;;;;4141:25;;;:14;;;:25;;;;;:36;;;3814:378;4270:17;;:3;;:17;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;4373:3;:14;;:21;4388:5;4373:21;;;;;;;;;;;4366:28;;;4416:4;4409:11;;;;;;;3339:1135;4458:5;4451:12;;;;;3339:1135;3184:1296;3112:1368;;;;:::o;2538:406::-;2601:4;5238:21;;;:14;;;:21;;;;;;2617:321;;-1:-1:-1;2659:23:27;;;;;;;;:11;:23;;;;;;;;;;;;;2841:18;;2817:21;;;:14;;;:21;;;;;;:42;;;;2873:11;;4824:237;4875:11;4889:12;4897:3;5434:18;;5352:107;4889:12;4875:26;-1:-1:-1;4916:9:27;4911:96;4935:3;4931:1;:7;4911:96;;;4966:3;:14;;:30;4981:3;:11;;4993:1;4981:14;;;;;;;;:::i;:::-;;;;;;;;;4966:30;;;;;;;;;;;4959:37;;;4940:3;;;;;4911:96;;;-1:-1:-1;;5039:11:27;34209:23:16;;2709:275:30:o;9974:164:69:-;-1:-1:-1;;;;;10049:19:69;;10041:90;;;;-1:-1:-1;;;10041:90:69;;;;;;;;;;;10702:397:28;10780:4;10801:35;10830:5;10801:28;:35::i;:::-;10796:79;;-1:-1:-1;10859:5:28;;10702:397;-1:-1:-1;10702:397:28:o;10796:79::-;10891:89;10938:5;-1:-1:-1;;;10891:46:28;:89::i;:::-;:201;;;-1:-1:-1;10996:96:28;11043:5;-1:-1:-1;;;10996:46:28;:96::i;719:528:23:-;783:4;976:68;1009:7;-1:-1:-1;;;976:32:23;:68::i;:::-;972:269;;;1061:12;;1093:52;1115:7;-1:-1:-1;;;;;;1093:21:23;:52::i;:::-;1060:85;;;;1166:7;:21;;;;-1:-1:-1;1177:10:23;;1159:28;-1:-1:-1;;;719:528:23:o;4504:238::-;4606:4;4623:12;4637:14;4655:43;4677:7;4686:11;4655:21;:43::i;:::-;4622:76;;;;4715:7;:20;;;;-1:-1:-1;4726:9:23;4708:27;-1:-1:-1;;;;4504:238:23:o;5198:628::-;-1:-1:-1;;;5310:12:23;5452:22;;;5494:4;5487:25;;;5310:12;;;5581:4;5310:12;5569:4;5310:12;5554:7;5547:5;5536:50;5525:61;;5740:4;5734:11;5727:19;5720:27;5654:4;5636:16;5633:26;5612:198;5599:211;;5438:382;5198:628;;;;;:::o;14:286:83:-;72:6;125:2;113:9;104:7;100:23;96:32;93:52;;;141:1;138;131:12;93:52;167:23;;-1:-1:-1;;;;;;219:32:83;;209:43;;199:71;;266:1;263;256:12;679:367;742:8;752:6;806:3;799:4;791:6;787:17;783:27;773:55;;824:1;821;814:12;773:55;-1:-1:-1;847:20:83;;890:18;879:30;;876:50;;;922:1;919;912:12;876:50;959:4;951:6;947:17;935:29;;1019:3;1012:4;1002:6;999:1;995:14;987:6;983:27;979:38;976:47;973:67;;;1036:1;1033;1026:12;973:67;679:367;;;;;:::o;1051:437::-;1137:6;1145;1198:2;1186:9;1177:7;1173:23;1169:32;1166:52;;;1214:1;1211;1204:12;1166:52;1254:9;1241:23;1287:18;1279:6;1276:30;1273:50;;;1319:1;1316;1309:12;1273:50;1358:70;1420:7;1411:6;1400:9;1396:22;1358:70;:::i;:::-;1447:8;;1332:96;;-1:-1:-1;1051:437:83;-1:-1:-1;;;;1051:437:83:o;1493:226::-;1552:6;1605:2;1593:9;1584:7;1580:23;1576:32;1573:52;;;1621:1;1618;1611:12;1573:52;-1:-1:-1;1666:23:83;;1493:226;-1:-1:-1;1493:226:83:o;1724:131::-;-1:-1:-1;;;;;1799:31:83;;1789:42;;1779:70;;1845:1;1842;1835:12;1860:367;1928:6;1936;1989:2;1977:9;1968:7;1964:23;1960:32;1957:52;;;2005:1;2002;1995:12;1957:52;2050:23;;;-1:-1:-1;2149:2:83;2134:18;;2121:32;2162:33;2121:32;2162:33;:::i;:::-;2214:7;2204:17;;;1860:367;;;;;:::o;2232:118::-;2318:5;2311:13;2304:21;2297:5;2294:32;2284:60;;2340:1;2337;2330:12;2355:382;2420:6;2428;2481:2;2469:9;2460:7;2456:23;2452:32;2449:52;;;2497:1;2494;2487:12;2449:52;2536:9;2523:23;2555:31;2580:5;2555:31;:::i;:::-;2605:5;-1:-1:-1;2662:2:83;2647:18;;2634:32;2675:30;2634:32;2675:30;:::i;2973:650::-;3059:6;3067;3075;3083;3136:3;3124:9;3115:7;3111:23;3107:33;3104:53;;;3153:1;3150;3143:12;3104:53;3192:9;3179:23;3211:31;3236:5;3211:31;:::i;:::-;3261:5;-1:-1:-1;3318:2:83;3303:18;;3290:32;3331:33;3290:32;3331:33;:::i;:::-;3383:7;-1:-1:-1;3442:2:83;3427:18;;3414:32;3455:33;3414:32;3455:33;:::i;:::-;2973:650;;;;-1:-1:-1;3507:7:83;;3587:2;3572:18;3559:32;;-1:-1:-1;;2973:650:83:o;3628:247::-;3687:6;3740:2;3728:9;3719:7;3715:23;3711:32;3708:52;;;3756:1;3753;3746:12;3708:52;3795:9;3782:23;3814:31;3839:5;3814:31;:::i;3880:637::-;4070:2;4082:21;;;4152:13;;4055:18;;;4174:22;;;4022:4;;4253:15;;;4227:2;4212:18;;;4022:4;4296:195;4310:6;4307:1;4304:13;4296:195;;;4375:13;;-1:-1:-1;;;;;4371:39:83;4359:52;;4440:2;4466:15;;;;4431:12;;;;4407:1;4325:9;4296:195;;;-1:-1:-1;4508:3:83;;3880:637;-1:-1:-1;;;;;3880:637:83:o;4789:418::-;4938:2;4927:9;4920:21;4901:4;4970:6;4964:13;5013:6;5008:2;4997:9;4993:18;4986:34;5072:6;5067:2;5059:6;5055:15;5050:2;5039:9;5035:18;5029:50;5128:1;5123:2;5114:6;5103:9;5099:22;5095:31;5088:42;5198:2;5191;5187:7;5182:2;5174:6;5170:15;5166:29;5155:9;5151:45;5147:54;5139:62;;;4789:418;;;;:::o;5212:367::-;5280:6;5288;5341:2;5329:9;5320:7;5316:23;5312:32;5309:52;;;5357:1;5354;5347:12;5309:52;5396:9;5383:23;5415:31;5440:5;5415:31;:::i;:::-;5465:5;5543:2;5528:18;;;;5515:32;;-1:-1:-1;;;5212:367:83:o;5974:114::-;6058:4;6051:5;6047:16;6040:5;6037:27;6027:55;;6078:1;6075;6068:12;6093:243;6150:6;6203:2;6191:9;6182:7;6178:23;6174:32;6171:52;;;6219:1;6216;6209:12;6171:52;6258:9;6245:23;6277:29;6300:5;6277:29;:::i;6341:508::-;6418:6;6426;6434;6487:2;6475:9;6466:7;6462:23;6458:32;6455:52;;;6503:1;6500;6493:12;6455:52;6542:9;6529:23;6561:31;6586:5;6561:31;:::i;:::-;6611:5;-1:-1:-1;6668:2:83;6653:18;;6640:32;6681:33;6640:32;6681:33;:::i;:::-;6341:508;;6733:7;;-1:-1:-1;;;6813:2:83;6798:18;;;;6785:32;;6341:508::o;6854:346::-;6922:6;6930;6983:2;6971:9;6962:7;6958:23;6954:32;6951:52;;;6999:1;6996;6989:12;6951:52;-1:-1:-1;;7044:23:83;;;7164:2;7149:18;;;7136:32;;-1:-1:-1;6854:346:83:o;7662:566::-;7754:6;7762;7770;7823:2;7811:9;7802:7;7798:23;7794:32;7791:52;;;7839:1;7836;7829:12;7791:52;7879:9;7866:23;7912:18;7904:6;7901:30;7898:50;;;7944:1;7941;7934:12;7898:50;7983:70;8045:7;8036:6;8025:9;8021:22;7983:70;:::i;:::-;8072:8;;-1:-1:-1;7957:96:83;-1:-1:-1;;8157:2:83;8142:18;;8129:32;8170:28;8129:32;8170:28;:::i;:::-;8217:5;8207:15;;;7662:566;;;;;:::o;8422:127::-;8483:10;8478:3;8474:20;8471:1;8464:31;8514:4;8511:1;8504:15;8538:4;8535:1;8528:15;8686:771;8908:2;8920:21;;;8893:18;;8976:22;;;8860:4;9055:6;9029:2;9014:18;;8860:4;9089:281;9103:6;9100:1;9097:13;9089:281;;;9178:6;9165:20;9198:31;9223:5;9198:31;:::i;:::-;-1:-1:-1;;;;;9254:31:83;9242:44;;9315:4;9343:17;;;;9306:14;;;;9282:1;9118:9;9089:281;;;9093:3;9387;9379:11;;;;9442:6;9435:14;9428:22;9421:4;9410:9;9406:20;9399:52;8686:771;;;;;;:::o;10312:245::-;10379:6;10432:2;10420:9;10411:7;10407:23;10403:32;10400:52;;;10448:1;10445;10438:12;10400:52;10480:9;10474:16;10499:28;10521:5;10499:28;:::i;10562:127::-;10623:10;10618:3;10614:20;10611:1;10604:31;10654:4;10651:1;10644:15;10678:4;10675:1;10668:15;10694:935;10774:6;10827:2;10815:9;10806:7;10802:23;10798:32;10795:52;;;10843:1;10840;10833:12;10795:52;10876:9;10870:16;10909:18;10901:6;10898:30;10895:50;;;10941:1;10938;10931:12;10895:50;10964:22;;11017:4;11009:13;;11005:27;-1:-1:-1;10995:55:83;;11046:1;11043;11036:12;10995:55;11079:2;11073:9;11105:18;11097:6;11094:30;11091:56;;;11127:18;;:::i;:::-;11176:2;11170:9;11268:2;11230:17;;-1:-1:-1;;11226:31:83;;;11259:2;11222:40;11218:54;11206:67;;11303:18;11288:34;;11324:22;;;11285:62;11282:88;;;11350:18;;:::i;:::-;11386:2;11379:22;11410;;;11451:15;;;11468:2;11447:24;11444:37;-1:-1:-1;11441:57:83;;;11494:1;11491;11484:12;11441:57;11543:6;11538:2;11534;11530:11;11525:2;11517:6;11513:15;11507:43;11596:1;11570:19;;;11591:2;11566:28;11559:39;;;;11574:6;10694:935;-1:-1:-1;;;;10694:935:83:o;11634:247::-;11702:6;11755:2;11743:9;11734:7;11730:23;11726:32;11723:52;;;11771:1;11768;11761:12;11723:52;11803:9;11797:16;11822:29;11845:5;11822:29;:::i;11886:331::-;11991:9;12002;12044:8;12032:10;12029:24;12026:44;;;12066:1;12063;12056:12;12026:44;12095:6;12085:8;12082:20;12079:40;;;12115:1;12112;12105:12;12079:40;-1:-1:-1;;12141:23:83;;;12186:25;;;;;-1:-1:-1;11886:331:83:o;12222:374::-;12343:19;;-1:-1:-1;;12380:40:83;;;12440:2;12432:11;;12429:161;;;-1:-1:-1;;12502:2:83;12498:12;;;;12495:1;12491:20;12487:58;;;12479:67;12475:105;;;;12222:374;-1:-1:-1;;12222:374:83:o;12880:225::-;12947:9;;;12968:11;;;12965:134;;;13021:10;13016:3;13012:20;13009:1;13002:31;13056:4;13053:1;13046:15;13084:4;13081:1;13074:15;13110:127;13171:10;13166:3;13162:20;13159:1;13152:31;13202:4;13199:1;13192:15;13226:4;13223:1;13216:15","linkReferences":{},"immutableReferences":{"1430":[{"start":1017,"length":32},{"start":1145,"length":32},{"start":5485,"length":32}]}},"methodIdentifiers":{"COMPLIANCE_MANAGER_ROLE()":"03c26bcd","DEFAULT_ADMIN_ROLE()":"a217fddf","DEFAULT_MAX_RULES()":"f76bf550","RULES_MANAGEMENT_ROLE()":"9b11c115","addRule(address)":"e3c4602c","bindToken(address)":"3ff5aa02","bindTokens(address[])":"c7c24b18","canTransfer(address,address,uint256)":"e46638e6","canTransferFrom(address,address,address,uint256)":"7157797f","clearRules()":"b043572e","containsRule(address)":"54e4b945","created(address,uint256)":"5f8dead3","destroyed(address,uint256)":"8d2ea772","detectTransferRestriction(address,address,uint256)":"d4ce1415","detectTransferRestrictionFrom(address,address,address,uint256)":"d32c7bb5","getRoleAdmin(bytes32)":"248a9ca3","getRoleMember(bytes32,uint256)":"9010d07c","getRoleMemberCount(bytes32)":"ca15c873","getRoleMembers(bytes32)":"a3246ad3","getTokenBound()":"6a3edf28","getTokenBounds()":"e54621d2","grantRole(bytes32,address)":"2f2ff15d","hasRole(bytes32,address)":"91d14854","isTokenBound(address)":"993e8b95","isTokenSelfBindingApproved(address)":"db75d017","isTrustedForwarder(address)":"572b6c05","maxRules()":"6ae728c6","messageForTransferRestriction(uint8)":"7f4ab1dd","removeRule(address)":"df21950f","renounceRole(bytes32,address)":"36568abe","revokeRole(bytes32,address)":"d547741f","rule(uint256)":"db18af6c","rules()":"52f6747a","rulesCount()":"bc13eacc","setMaxRules(uint256)":"3a56d6d5","setRules(address[])":"b27aef3a","setTokenSelfBindingApproval(address,bool)":"3284a9a5","setTokenSelfBindingApprovalBatch(address[],bool)":"bb4b6121","supportsInterface(bytes4)":"01ffc9a7","transferred(address,address,address,uint256)":"3e5af4ca","transferred(address,address,uint256)":"8baf29b4","trustedForwarder()":"7da0a877","unbindToken(address)":"40db3b50","unbindTokens(address[])":"1455d0e7","version()":"54fd4d50"},"rawMetadata":"{\"compiler\":{\"version\":\"0.8.37+commit.f401782d\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"admin\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"forwarderIrrevocable\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenContract\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[],\"name\":\"AccessControlBadConfirmation\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"internalType\":\"bytes32\",\"name\":\"neededRole\",\"type\":\"bytes32\"}],\"name\":\"AccessControlUnauthorizedAccount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_AdminWithAddressZeroNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_RuleInvalidInterface\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_RulesManagementModule_ArrayIsEmpty\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"maxRules\",\"type\":\"uint256\"}],\"name\":\"RuleEngine_RulesManagementModule_MaxRulesExceeded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_RulesManagementModule_MaxRulesZeroNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_RulesManagementModule_RuleAccountCannotReceivePrivileges\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_RulesManagementModule_RuleAddressZeroNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_RulesManagementModule_RuleAlreadyExists\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_RulesManagementModule_RuleDoNotMatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TokenBinding_InvalidTokenAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TokenBinding_TokenAlreadyBound\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TokenBinding_TokenNotBound\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TokenBinding_UnauthorizedCaller\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract IRule\",\"name\":\"rule\",\"type\":\"address\"}],\"name\":\"AddRule\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"ClearRules\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract IRule\",\"name\":\"rule\",\"type\":\"address\"}],\"name\":\"RemoveRule\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"previousAdminRole\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"newAdminRole\",\"type\":\"bytes32\"}],\"name\":\"RoleAdminChanged\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleGranted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"sender\",\"type\":\"address\"}],\"name\":\"RoleRevoked\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"maxRules\",\"type\":\"uint256\"}],\"name\":\"SetMaxRules\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"TokenBound\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"tokens\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"TokenSelfBindingApprovalBatchSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"TokenSelfBindingApprovalSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"TokenUnbound\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"COMPLIANCE_MANAGER_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"DEFAULT_ADMIN_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"DEFAULT_MAX_RULES\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"RULES_MANAGEMENT_ROLE\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IRule\",\"name\":\"rule_\",\"type\":\"address\"}],\"name\":\"addRule\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"bindToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"tokens\",\"type\":\"address[]\"}],\"name\":\"bindTokens\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"canTransfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"canTransferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"clearRules\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IRule\",\"name\":\"rule_\",\"type\":\"address\"}],\"name\":\"containsRule\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"created\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"destroyed\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"detectTransferRestriction\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"detectTransferRestrictionFrom\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleAdmin\",\"outputs\":[{\"internalType\":\"bytes32\",\"name\":\"\",\"type\":\"bytes32\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"uint256\",\"name\":\"index\",\"type\":\"uint256\"}],\"name\":\"getRoleMember\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleMemberCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"}],\"name\":\"getRoleMembers\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTokenBound\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTokenBounds\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"grantRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"hasRole\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"isTokenBound\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"isTokenSelfBindingApproved\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"}],\"name\":\"isTrustedForwarder\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"maxRules\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"restrictionCode\",\"type\":\"uint8\"}],\"name\":\"messageForTransferRestriction\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IRule\",\"name\":\"rule_\",\"type\":\"address\"}],\"name\":\"removeRule\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"callerConfirmation\",\"type\":\"address\"}],\"name\":\"renounceRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes32\",\"name\":\"role\",\"type\":\"bytes32\"},{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"revokeRole\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"ruleId\",\"type\":\"uint256\"}],\"name\":\"rule\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"rules\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"rulesCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"maxRules_\",\"type\":\"uint256\"}],\"name\":\"setMaxRules\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IRule[]\",\"name\":\"rules_\",\"type\":\"address[]\"}],\"name\":\"setRules\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"setTokenSelfBindingApproval\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"tokens\",\"type\":\"address[]\"},{\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"setTokenSelfBindingApprovalBatch\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"transferred\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"transferred\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"trustedForwarder\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"unbindToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"tokens\",\"type\":\"address[]\"}],\"name\":\"unbindTokens\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"version_\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"Administrative calls may be relayed by the immutable trusted forwarder (gasless transactions). Token identity is never resolved through the forwarder: the bound-token gate and token self-binding compare the raw `msg.sender`.\",\"errors\":{\"AccessControlBadConfirmation()\":[{\"details\":\"The caller of a function is not the expected one. NOTE: Don't confuse with {AccessControlUnauthorizedAccount}.\"}],\"AccessControlUnauthorizedAccount(address,bytes32)\":[{\"details\":\"The `account` is missing a role.\"}]},\"events\":{\"AddRule(address)\":{\"params\":{\"rule\":\"The address of the rule contract that was added.\"}},\"RemoveRule(address)\":{\"params\":{\"rule\":\"The address of the rule contract that was removed.\"}},\"RoleAdminChanged(bytes32,bytes32,bytes32)\":{\"details\":\"Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole` `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite {RoleAdminChanged} not being emitted to signal this.\"},\"RoleGranted(bytes32,address,address)\":{\"details\":\"Emitted when `account` is granted `role`. `sender` is the account that originated the contract call. This account bears the admin role (for the granted role). Expected in cases where the role was granted using the internal {AccessControl-_grantRole}.\"},\"RoleRevoked(bytes32,address,address)\":{\"details\":\"Emitted when `account` is revoked `role`. `sender` is the account that originated the contract call: - if using `revokeRole`, it is the admin role bearer - if using `renounceRole`, it is the role bearer (i.e. `account`)\"},\"SetMaxRules(uint256)\":{\"params\":{\"maxRules\":\"The new rule cap.\"}},\"TokenBound(address)\":{\"details\":\"Same declaration as ERC-3643 `TokenBound(address _token)`, which does not index the token. Keep it non-indexed: `indexed` would move `token` from the data to a topic and break consumers decoding with the standard ERC-3643 ABI.\",\"params\":{\"token\":\"The address of the token that was bound.\"}},\"TokenSelfBindingApprovalBatchSet(address[],bool)\":{\"details\":\"`tokens` is the array as passed: it may contain tokens already at `approved` and duplicates, and is empty for an empty batch, so it lists the tokens that were set, not only those that changed. No {TokenSelfBindingApprovalSet} is emitted per token, so a filter on that event's indexed `token` does not see batch updates. `tokens` is not indexed: an indexed array is stored as a hash and cannot be filtered per token.\",\"params\":{\"approved\":\"True if token self-bind/unbind is allowed, false otherwise.\",\"tokens\":\"The token addresses whose self-binding permission was set, as passed to the call.\"}},\"TokenSelfBindingApprovalSet(address,bool)\":{\"details\":\"Emitted on every call, also when `approved` equals the current value. Not emitted by {setTokenSelfBindingApprovalBatch}, which emits {TokenSelfBindingApprovalBatchSet} instead: a consumer reconstructing the approvals, or filtering on `token`, must handle both events, or read {isTokenSelfBindingApproved}, which is authoritative.\",\"params\":{\"approved\":\"True if token self-bind/unbind is allowed, false otherwise.\",\"token\":\"The token address whose self-binding permission was set.\"}},\"TokenUnbound(address)\":{\"details\":\"Same declaration as ERC-3643 `TokenUnbound(address _token)`; kept non-indexed for the same reason as {TokenBound}.\",\"params\":{\"token\":\"The address of the token that was unbound.\"}}},\"kind\":\"dev\",\"methods\":{\"addRule(address)\":{\"details\":\"Reverts when the configured maximum number of rules is already reached. Security convention: do not grant {RULES_MANAGEMENT_ROLE} to rule contracts.\",\"params\":{\"rule_\":\"The IRule contract to add.\"}},\"bindToken(address)\":{\"custom:security-note\":\"\\\"Multi-tenant\\\" means one instance is shared by multiple token contracts. Downstream state (for the RuleEngine: the per-address accounting held by stateful rules) is shared across all bound tokens, so binding tokens from different issuers silently cross-contaminates it. Only bind tokens that are equally trusted and governed together.\",\"details\":\"Authorized by {_authorizeTokenBindingChange}.\",\"params\":{\"token\":\"The address of the token to bind.\"}},\"bindTokens(address[])\":{\"custom:security-note\":\"See {bindToken} for multi-tenant state risks. All tokens bound in this batch share the same downstream state. Only bind tokens that are equally trusted and governed together.\",\"details\":\"Must be restricted by implementation-specific access control. Atomic: reverts if any token is invalid or already bound (or listed twice), and then binds none of them. This deliberately departs from the usual batch convention of skipping elements already in the target state: a binding change is security-relevant, and a token that is already bound in the list is most likely an operator mistake that should stop the whole operation. An empty array is a no-op.\",\"params\":{\"tokens\":\"The token addresses to bind.\"}},\"canTransfer(address,address,uint256)\":{\"details\":\"Don't check the balance and the user's right (access control)\",\"params\":{\"from\":\"The address sending tokens.\",\"to\":\"The address receiving tokens.\",\"value\":\"The amount of tokens to transfer.\"},\"returns\":{\"_0\":\"True if the transfer is valid, false otherwise.\"}},\"canTransferFrom(address,address,address,uint256)\":{\"details\":\"Does not check balances or access rights (Access Control).\",\"params\":{\"from\":\"The source address.\",\"spender\":\"The address performing the transfer.\",\"to\":\"The destination address.\",\"value\":\"The number of tokens to transfer.\"},\"returns\":{\"_0\":\"isCompliant True if the transfer complies with policy.\"}},\"clearRules()\":{\"details\":\"After calling this function, no rules will remain set. Cost is O(n) in the number of configured rules. With the default cap of 10 this is negligible, but a high {maxRules} setting re-exposes unbounded cost here even though per-transfer cost remains bounded.\"},\"constructor\":{\"params\":{\"admin\":\"Address receiving `DEFAULT_ADMIN_ROLE`; must not be the zero address.\",\"forwarderIrrevocable\":\"Address of the trusted ERC-2771 forwarder, immutable after construction.\",\"tokenContract\":\"Token to bind at deployment, or the zero address to bind none.\"}},\"containsRule(address)\":{\"details\":\"Complexity: O(1).\",\"params\":{\"rule_\":\"The IRule contract to check for membership.\"},\"returns\":{\"_0\":\"True if the rule is present, false otherwise.\"}},\"created(address,uint256)\":{\"details\":\"Called by the token contract when new tokens are issued to an account. Reverts if the minting does not comply with the rules.\",\"params\":{\"to\":\"The address receiving the minted tokens.\",\"value\":\"The number of tokens created.\"}},\"destroyed(address,uint256)\":{\"details\":\"Called by the token contract when tokens are redeemed or burned. Reverts if the burning does not comply with the rules.\",\"params\":{\"from\":\"The address whose tokens are being destroyed.\",\"value\":\"The number of tokens destroyed.\"}},\"detectTransferRestriction(address,address,uint256)\":{\"params\":{\"from\":\"the origin address\",\"to\":\"the destination address\",\"value\":\"to transfer\"},\"returns\":{\"_0\":\"The restriction code or REJECTED_CODE_BASE.TRANSFER_OK (0) if the transfer is valid\"}},\"detectTransferRestrictionFrom(address,address,address,uint256)\":{\"details\":\" See {ERC-1404} Add an additionnal argument `spender` This function is where an issuer enforces the restriction logic of their token transfers. Some examples of this might include: - checking if the token recipient is whitelisted, - checking if a sender's tokens are frozen in a lock-up period, etc.\",\"params\":{\"from\":\"The address sending tokens.\",\"spender\":\"The address initiating the delegated transfer.\",\"to\":\"The address receiving tokens.\",\"value\":\"amount of tokens to transfer\"},\"returns\":{\"_0\":\"uint8 restricted code, 0 means the transfer is authorized\"}},\"getRoleAdmin(bytes32)\":{\"details\":\"Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}.\"},\"getRoleMember(bytes32,uint256)\":{\"details\":\"Returns one of the accounts that have `role`. `index` must be a value between 0 and {getRoleMemberCount}, non-inclusive. Role bearers are not sorted in any particular way, and their ordering may change at any point. WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure you perform all queries on the same block. See the following https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] for more information.\"},\"getRoleMemberCount(bytes32)\":{\"details\":\"Returns the number of accounts that have `role`. Can be used together with {getRoleMember} to enumerate all bearers of a role.\"},\"getRoleMembers(bytes32)\":{\"details\":\"Return all accounts that have `role` WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that this function has an unbounded cost, and using it as part of a state-changing function may render the function uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.\"},\"getTokenBound()\":{\"details\":\"If multiple tokens are supported, consider using getTokenBounds().\",\"returns\":{\"_0\":\"The address of the currently bound token.\"}},\"getTokenBounds()\":{\"details\":\"This operation copies the entire storage set to memory and is mainly intended for off-chain reads.\",\"returns\":{\"_0\":\"An array of bound token addresses.\"}},\"grantRole(bytes32,address)\":{\"details\":\"Prevents granting any role to accounts currently configured as rules. Note: this check is intentionally one-directional. {addRule} does not verify whether the rule address already holds a privileged role, and this function does not prevent adding a privileged address as a rule afterwards. Operators are responsible for keeping rule contracts and privileged accounts disjoint.\",\"params\":{\"account\":\"The account receiving the role.\",\"role\":\"The role identifier to grant.\"}},\"hasRole(bytes32,address)\":{\"details\":\"The Default Admin has all roles\",\"params\":{\"account\":\"The account to check.\",\"role\":\"The role identifier to check.\"},\"returns\":{\"_0\":\"True if the account holds the role (or is the default admin), false otherwise.\"}},\"isTokenBound(address)\":{\"details\":\"Complexity: O(1).\",\"params\":{\"token\":\"The token address to verify.\"},\"returns\":{\"_0\":\"True if the token is bound, false otherwise.\"}},\"isTokenSelfBindingApproved(address)\":{\"params\":{\"token\":\"The token address to query.\"},\"returns\":{\"_0\":\"True if self-binding is approved for `token`, false otherwise.\"}},\"isTrustedForwarder(address)\":{\"details\":\"Indicates whether any particular address is the trusted forwarder.\"},\"maxRules()\":{\"returns\":{\"_0\":\"The maximum number of rules that can be configured.\"}},\"messageForTransferRestriction(uint8)\":{\"details\":\"See {ERC-1404} This function is effectively an accessor for the \\\"message\\\", a human-readable explanation as to why a transaction is restricted.\",\"params\":{\"restrictionCode\":\"The restriction code to translate into a message.\"},\"returns\":{\"_0\":\"The human-readable message corresponding to `restrictionCode`.\"}},\"removeRule(address)\":{\"details\":\"Reverts if the provided rule is not found or does not match the stored rule at its index. Complexity: O(1).\",\"params\":{\"rule_\":\"The IRule contract to remove.\"}},\"renounceRole(bytes32,address)\":{\"details\":\"Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). Emits a {RoleRevoked} event if the calling account had `role` and this call successfully revoked it. Requirements: - the caller must be `callerConfirmation`. May emit a {RoleRevoked} event.\"},\"revokeRole(bytes32,address)\":{\"details\":\"Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleRevoked} event.\"},\"rule(uint256)\":{\"details\":\"Reverts if `ruleId` is out of bounds. Complexity: O(1). Note that there are no guarantees on the ordering of values inside the array, and it may change when more values are added or removed.\",\"params\":{\"ruleId\":\"The index of the desired rule in the array.\"},\"returns\":{\"_0\":\"The address of the corresponding IRule contract, return the `zero address` is out of bounds.\"}},\"rules()\":{\"details\":\"This is a view-only function that does not modify state. This operation will copy the entire storage to memory, which can be quite expensive. This is designed to mostly be used by view accessors that are queried without any gas fees.\",\"returns\":{\"_0\":\"An array of all active rule contract addresses.\"}},\"rulesCount()\":{\"details\":\"Equivalent to the length of the internal rules array. Complexity: O(1)\",\"returns\":{\"_0\":\"The number of active rules.\"}},\"setMaxRules(uint256)\":{\"details\":\"Access control is implementation specific (admin/owner). Setting a very high cap re-exposes unbounded gas cost for administrative operations such as {clearRules} even though normal per-transfer cost remains bounded.\",\"params\":{\"maxRules_\":\"New maximum number of rules.\"}},\"setRules(address[])\":{\"details\":\"Replaces the entire rule set atomically. Reverts if `rules_` is empty. Use {clearRules} to remove all rules explicitly. To transition from one non-empty set to another without an enforcement gap, call this function directly with the new set. Emits {ClearRules} when the existing rule set is non-empty, then emits {AddRule} for each new rule. Off-chain indexers must handle both events to reconstruct state. Security convention: rule contracts should be treated as trusted business logic, but should not also be granted {RULES_MANAGEMENT_ROLE}.\",\"params\":{\"rules_\":\"The array of addresses representing the new rules to be set.\"}},\"setTokenSelfBindingApproval(address,bool)\":{\"details\":\"Must be restricted by implementation-specific access control. An approval stays in force until it is revoked here or until the binding manager unbinds the token ({unbindToken} or {unbindTokens}), which revokes it and emits {TokenSelfBindingApprovalSet} with `false`. A token that unbinds itself keeps its approval, so it can bind itself again later.\",\"params\":{\"approved\":\"Whether self-binding is approved for `token`.\",\"token\":\"The token address to configure.\"}},\"setTokenSelfBindingApprovalBatch(address[],bool)\":{\"details\":\"Must be restricted by implementation-specific access control. Reverts if any token in `tokens` is the zero address. Emits a single {TokenSelfBindingApprovalBatchSet} with the input array, not one {TokenSelfBindingApprovalSet} per token.\",\"params\":{\"approved\":\"Whether self-binding is approved for all provided tokens.\",\"tokens\":\"The token addresses to configure.\"}},\"supportsInterface(bytes4)\":{\"params\":{\"interfaceId\":\"The interface identifier to check.\"},\"returns\":{\"_0\":\"True if the interface is supported, false otherwise.\"}},\"transferred(address,address,address,uint256)\":{\"details\":\"Must revert if the transfer is invalid Same name as ERC-3643 but with one supplementary argument `spender` This function can be used to update state variables of the RuleEngine contract This function can be called ONLY by the token contract bound to the RuleEngine Which overload the token calls (since CMTAT v3.3.0): - this 4-argument overload for `transferFrom` (`spender` = approved spender) and for every operation initiated by an operator, with the operator as `spender`: mint (`from == address(0)`), burn (`to == address(0)`), including `burnFrom`, self-burn and cross-chain mint/burn, and the minter `batchTransfer`; - the 3-argument ERC-3643 overload `transferred(from, to, value)`, inherited from {IERC3643IComplianceContract}, only for a direct `transfer`. Up to CMTAT v3.2.0, mint, burn and the minter transfer used the 3-argument overload. WARNING - zero-value calls are permissionless. ERC-20 requires transfers of `0` to be treated as normal transfers, and OpenZeppelin's `_spendAllowance` consumes no allowance when `value == 0`. Any address can therefore call `transferFrom(victim, anyone, 0)` on the token and reach this callback for an arbitrary `from`, with itself as `spender`, without ever having been approved. The token deliberately does not suppress the notification, because doing so would make its compliance notifications inconsistent with its own ERC-20 transfer semantics. Implementations MUST therefore treat `value == 0` as carrying no economic meaning: any stateful rule (cooldown, holding period, quota, tax bucket, counter, holder tracking, ...) MUST be a no-op for a zero value, otherwise an attacker can desynchronize policy state from balances, or keep a holder permanently restricted, at no cost. The same applies to the 3-argument ERC-3643 overload, which a zero-value `transfer(to, 0)` reaches the same way.\",\"params\":{\"from\":\"token holder address\",\"spender\":\"spender address (sender)\",\"to\":\"receiver address\",\"value\":\"value of tokens involved in the transfer; MAY be `0` \\u2014 see the warning above\"}},\"transferred(address,address,uint256)\":{\"details\":\" This function can be used to update state variables of the compliance contract This function can be called ONLY by the token contract bound to the compliance\",\"params\":{\"from\":\"The address of the sender\",\"to\":\"The address of the receiver\",\"value\":\"value of tokens involved in the transfer\"}},\"trustedForwarder()\":{\"details\":\"Returns the address of the trusted forwarder.\"},\"unbindToken(address)\":{\"details\":\"Authorized by {_authorizeTokenBindingChange}. Operator warning: unbinding is an administrative operation and does not erase any state already stored downstream in a previously shared (\\\"multi-tenant\\\") setup.\",\"params\":{\"token\":\"The address of the token to unbind.\"}},\"unbindTokens(address[])\":{\"details\":\"Must be restricted by implementation-specific access control. Atomic: reverts if any token is not currently bound, and then unbinds none of them. Deliberately not the skip-if-already-done batch convention, for the same reason as {bindTokens}. An empty array is a no-op. Like a manager's {unbindToken}, revokes each token's self-binding approval (see {setTokenSelfBindingApproval}).\",\"params\":{\"tokens\":\"The token addresses to unbind.\"}},\"version()\":{\"details\":\"This value is useful to know which smart contract version has been used\",\"returns\":{\"version_\":\"A string representing the version of the token implementation (e.g., \\\"1.0.0\\\").\"}}},\"title\":\"Implementation of a ruleEngine as defined by the CMTAT, with RBAC access control and ERC-2771\",\"version\":1},\"userdoc\":{\"errors\":{\"TokenBinding_InvalidTokenAddress()\":[{\"notice\":\"Thrown when the zero address is passed as a token to bind or to approve.\"}],\"TokenBinding_TokenAlreadyBound()\":[{\"notice\":\"Thrown when binding a token that is already bound.\"}],\"TokenBinding_TokenNotBound()\":[{\"notice\":\"Thrown when unbinding a token that is not currently bound.\"}],\"TokenBinding_UnauthorizedCaller()\":[{\"notice\":\"Thrown when a caller that is not a bound token calls a bound-token entry point.\"}]},\"events\":{\"AddRule(address)\":{\"notice\":\"Emitted when a new rule is added to the rule set.\"},\"ClearRules()\":{\"notice\":\"Emitted when all rules are cleared from the rule set.\"},\"RemoveRule(address)\":{\"notice\":\"Emitted when a rule is removed from the rule set.\"},\"SetMaxRules(uint256)\":{\"notice\":\"Emitted when the maximum allowed number of rules is updated.\"},\"TokenBound(address)\":{\"notice\":\"Emitted when a token is successfully bound.\"},\"TokenSelfBindingApprovalBatchSet(address[],bool)\":{\"notice\":\"Emitted once by {setTokenSelfBindingApprovalBatch}, with the input array.\"},\"TokenSelfBindingApprovalSet(address,bool)\":{\"notice\":\"Emitted by {setTokenSelfBindingApproval} when self-binding permission is set for a token.\"},\"TokenUnbound(address)\":{\"notice\":\"Emitted when a token is successfully unbound.\"}},\"kind\":\"user\",\"methods\":{\"COMPLIANCE_MANAGER_ROLE()\":{\"notice\":\"Role allowed to bind and unbind tokens on the compliance contract.\"},\"DEFAULT_MAX_RULES()\":{\"notice\":\"Default upper bound on the number of rules a RuleEngine may hold.\"},\"RULES_MANAGEMENT_ROLE()\":{\"notice\":\"Role allowed to add, remove, set and clear rules.\"},\"addRule(address)\":{\"notice\":\"Adds a new rule to the current rule set.\"},\"bindToken(address)\":{\"notice\":\"Binds a token contract, allowing it to call the bound-token entry points.\"},\"bindTokens(address[])\":{\"notice\":\"Binds several token contracts in a single call.\"},\"canTransfer(address,address,uint256)\":{\"notice\":\"Returns true if the transfer is valid, and false otherwise.\"},\"canTransferFrom(address,address,address,uint256)\":{\"notice\":\"Checks if `spender` can transfer `value` tokens from `from` to `to` under compliance rules.\"},\"clearRules()\":{\"notice\":\"Removes all configured rules.\"},\"constructor\":{\"notice\":\"Deploys the RBAC RuleEngine with a trusted forwarder.\"},\"containsRule(address)\":{\"notice\":\"Checks whether a specific rule is currently configured.\"},\"created(address,uint256)\":{\"notice\":\"Updates the compliance contract state when tokens are created (minted).\"},\"destroyed(address,uint256)\":{\"notice\":\"Updates the compliance contract state when tokens are destroyed (burned).\"},\"detectTransferRestriction(address,address,uint256)\":{\"notice\":\"Queries every rule, in order, and returns the first restriction code that is not zero\"},\"detectTransferRestrictionFrom(address,address,address,uint256)\":{\"notice\":\"Returns a uint8 code to indicate if a transfer is restricted or not\"},\"getTokenBound()\":{\"notice\":\"Returns the single token currently bound to this compliance contract.\"},\"getTokenBounds()\":{\"notice\":\"Returns all tokens currently bound.\"},\"grantRole(bytes32,address)\":{\"notice\":\"Grants `role` to `account`.\"},\"hasRole(bytes32,address)\":{\"notice\":\"Returns `true` if `account` has been granted `role`.\"},\"isTokenBound(address)\":{\"notice\":\"Checks whether a token is currently bound.\"},\"isTokenSelfBindingApproved(address)\":{\"notice\":\"Returns whether a token is approved to bind and unbind itself.\"},\"maxRules()\":{\"notice\":\"Returns the maximum number of rules allowed in the engine.\"},\"removeRule(address)\":{\"notice\":\"Removes a specific rule from the current rule set.\"},\"rule(uint256)\":{\"notice\":\"Retrieves the rule address at a specific index.\"},\"rules()\":{\"notice\":\"Returns the full list of currently configured rules.\"},\"rulesCount()\":{\"notice\":\"Returns the total number of currently configured rules.\"},\"setMaxRules(uint256)\":{\"notice\":\"Updates the maximum number of rules allowed in the engine.\"},\"setRules(address[])\":{\"notice\":\"Defines the rules for the rule engine.\"},\"setTokenSelfBindingApproval(address,bool)\":{\"notice\":\"Sets whether a token is allowed to bind and unbind itself.\"},\"setTokenSelfBindingApprovalBatch(address[],bool)\":{\"notice\":\"Sets self-binding approval for multiple tokens in one transaction.\"},\"supportsInterface(bytes4)\":{\"notice\":\"ERC-165 interface detection.\"},\"transferred(address,address,address,uint256)\":{\"notice\":\"Function called whenever tokens are transferred from one wallet to another, minted or burned, when the token knows the account that initiated the operation (`spender`).\"},\"transferred(address,address,uint256)\":{\"notice\":\"Function called whenever tokens are transferred from one wallet to another\"},\"unbindToken(address)\":{\"notice\":\"Unbinds a token contract, revoking its access to the bound-token entry points.\"},\"unbindTokens(address[])\":{\"notice\":\"Unbinds several token contracts in a single call.\"},\"version()\":{\"notice\":\"Returns the current version of the token contract.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/deployment/accessControl/RuleEngine2771.sol\":\"RuleEngine2771\"},\"evmVersion\":\"osaka\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[\":@chainlink/contracts-ccip/=lib/Rules/lib/chainlink-ace/node_modules/@chainlink/contracts-ccip/chains/evm/contracts/\",\":@chainlink/contracts/=lib/Rules/lib/chainlink-ace/node_modules/@chainlink/contracts/\",\":@chainlink/contracts@1.4.0/=lib/Rules/lib/chainlink-doc/node_modules/@chainlink/contracts-1.4.0/\",\":@chainlink/cross-chain-identity/=lib/Rules/lib/chainlink-ace/packages/cross-chain-identity/src/\",\":@chainlink/local/=lib/Rules/lib/chainlink-doc/node_modules/@chainlink/local/\",\":@chainlink/policy-management/=lib/Rules/lib/chainlink-ace/packages/policy-management/src/\",\":@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\":@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\":@openzeppelin/contracts@4.7.3/=lib/Rules/lib/chainlink-doc/node_modules/@openzeppelin/contracts-4.7.3/\",\":@openzeppelin/contracts@4.8.3/=lib/Rules/lib/chainlink-ace/node_modules/@openzeppelin/contracts-4.8.3/\",\":@openzeppelin/contracts@4.9.6/=lib/Rules/lib/chainlink-doc/node_modules/@openzeppelin/contracts-4.9.6/\",\":@openzeppelin/contracts@5.0.2/=lib/Rules/lib/chainlink-ace/node_modules/@openzeppelin/contracts/\",\":@openzeppelin/contracts@5.1.0/=lib/Rules/lib/chainlink-doc/node_modules/@openzeppelin/contracts-5.1.0/\",\":@openzeppelin/contracts@5.3.0/=lib/Rules/lib/chainlink-ace/node_modules/@openzeppelin/contracts-5.3.0/\",\":CMTAT/=lib/CMTAT/contracts/\",\":CMTATv3.0.0/=lib/CMTATv3.0.0/contracts/\",\":ERC-3643/=lib/ERC-3643/contracts/\",\":ERC3643/=lib/Rules/lib/ERC-3643/contracts/\",\":RuleEngine/=lib/Rules/lib/RuleEngine/\",\":Rules/=lib/Rules/\",\":chainlink-ace/=lib/Rules/lib/chainlink-ace/\",\":chainlink-doc/=lib/Rules/lib/\",\":erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/\",\":forge-std/=lib/forge-std/src/\",\":halmos-cheatcodes/=lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/\",\":openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\":openzeppelin-contracts/=lib/openzeppelin-contracts/\"]},\"sources\":{\"lib/CMTAT/contracts/interfaces/engine/IRuleEngine.sol\":{\"keccak256\":\"0xeda899e2e46a9b9c3516acb61a7f7e92ed098928379010655c330da721aaffa7\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://60f8555330fc531dff7d0d71a862696fb286a0ba3290e41efbbbf4dd25947a3c\",\"dweb:/ipfs/QmWvbsBGWPtNMNN2EEedwdzzvQG7NtSj9VD2fmNgqVtCXN\"]},\"lib/CMTAT/contracts/interfaces/technical/IERC5679.sol\":{\"keccak256\":\"0x5bee30750c9a65438469a6c5bd8465e1603eec3aeeb94c07bd64ba3e9ee766e1\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://ef7a5c5f0d47135c97ab5d7456d31e513a71c849ae7f2f5395f860be125c4fbc\",\"dweb:/ipfs/Qmezem3qqSjij6ggyB34wC2S15KrY9fu42oymyS9epAYCQ\"]},\"lib/CMTAT/contracts/interfaces/tokenization/IERC3643Partial.sol\":{\"keccak256\":\"0x5c84c2e2442824e98625c471482fb3c9502f43f4c345e7c0fb07fa549be02e26\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://19071f2d12fb580d37eeee07885461f193568df34f3f69d2c5d65ce655d84435\",\"dweb:/ipfs/QmRqHwC7LksE3YPohMtxFieiPerhWdoDNUUMMLbB4XYvhK\"]},\"lib/CMTAT/contracts/interfaces/tokenization/draft-IERC1404.sol\":{\"keccak256\":\"0xc27cdac182d930a94391d589bdafa15364b6f8d9bf211175781dba661f1c0336\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://b509fa7f3cfd785632569f6ae3bec846aa0beefd73c1d5bde233440cae919f0f\",\"dweb:/ipfs/QmPCAdiEun8gaMqS8KhwPpRZV2zXAPfURRaF4C2KjX5Kby\"]},\"lib/CMTAT/contracts/interfaces/tokenization/draft-IERC7551.sol\":{\"keccak256\":\"0x84b73eb77ec82d6d7b313eff2d87f58d3b795840d004aaa10c611b360b827e30\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://a5b8c99fb3600369065a422d3821ba441dc06fc64f50ce0f33950a76ad82b51b\",\"dweb:/ipfs/QmbviJsZPY3xuLU3cHUWJx11aJCPAuN4WKnCufN4kVLm2U\"]},\"lib/CMTAT/contracts/interfaces/tokenization/draft-IERC7943.sol\":{\"keccak256\":\"0xc69588a72da81057ee278e961e8e3bb61a28d64c3c6cebe494ce00809c1cef15\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://148f117d9c463de441f81e6c0a67e95f1f14a61db209492dd0a1767b5572f21a\",\"dweb:/ipfs/QmUjT5uyJfNSYgUWn5Dxhf6Sx9Y1z8CNf3PuTEaGoAx3za\"]},\"lib/CMTAT/contracts/library/ERC1404ExtendInterfaceId.sol\":{\"keccak256\":\"0xf8268f4eb3a6b2e26c32cf76c5c76b6c17df3385c150f05953538a2472149247\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://05108de7a7ba2a0a67978bdfe8e500360674db6d894f42970bb1016b36639056\",\"dweb:/ipfs/QmRux9Qj1GomATseS6Tyq9uiPPNNipuxg2HjdjnPjgSQds\"]},\"lib/CMTAT/contracts/library/RuleEngineInterfaceId.sol\":{\"keccak256\":\"0x1152a49cba4232d943e295d259eb8a1b216d815067367410a5729a256dae4051\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://470f4435a5e62b0ba0ad70f8657b2db0e4cc3b7f2561772adb944ce010551ee6\",\"dweb:/ipfs/QmXECahRr8rK9XJPZwBCnemLDVPdFvPEBusezhaBqbLBqp\"]},\"lib/openzeppelin-contracts/contracts/access/AccessControl.sol\":{\"keccak256\":\"0xf7e47e67e49ee2a94aa5c52580045b6ec2e6e402d2376c14a75a151664d7c98f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://db6acc2c30f52cb4b5561ffe1db8763200f080c6762db94e4cce0f3623db7080\",\"dweb:/ipfs/QmecnQ1xEh1XMXqVmKZLMkj29iD2y2HJPkZnaYnAe5njFF\"]},\"lib/openzeppelin-contracts/contracts/access/IAccessControl.sol\":{\"keccak256\":\"0xbff9f59c84e5337689161ce7641c0ef8e872d6a7536fbc1f5133f128887aba3c\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://b308f882e796f7b79c9502deacb0a62983035c6f6f4e962b319ba6a1f4a77d3d\",\"dweb:/ipfs/QmaWCW7ahEQqFjwhSUhV7Ae7WhfNvzSpE7DQ58hvEooqPL\"]},\"lib/openzeppelin-contracts/contracts/access/extensions/AccessControlEnumerable.sol\":{\"keccak256\":\"0x90936bbc993aa96f6431bab0e08c9fcd35b1e58e39c188d64064ada6ed1bde03\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c6192bce9a802de36f6e2d852b55d0ef47f3f0a79dbed5d7d8d9c4f28982038c\",\"dweb:/ipfs/QmTsJrPZrQ57HaZapedDBHynNUZxvgEbbddMiDxz2cauLR\"]},\"lib/openzeppelin-contracts/contracts/access/extensions/IAccessControlEnumerable.sol\":{\"keccak256\":\"0xbc97d8c0d67d4d7eba1e662f0a8671712ace9e060ab03af547c4bb321aec1d8c\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://890d156f50630d52c7be57d7e0499132d6fd92b2e1365b81531f4463b3304377\",\"dweb:/ipfs/QmUHe9uL1ciePH2pQg7wdrgTAFRZWjcpBEAg8V1UNtXutd\"]},\"lib/openzeppelin-contracts/contracts/interfaces/IERC165.sol\":{\"keccak256\":\"0x0afcb7e740d1537b252cb2676f600465ce6938398569f09ba1b9ca240dde2dfc\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://1c299900ac4ec268d4570ecef0d697a3013cd11a6eb74e295ee3fbc945056037\",\"dweb:/ipfs/Qmab9owJoxcA7vJT5XNayCMaUR1qxqj1NDzzisduwaJMcZ\"]},\"lib/openzeppelin-contracts/contracts/metatx/ERC2771Context.sol\":{\"keccak256\":\"0x9695d220b99dcf62910533bdf5d40d4cf6a4e04d5b106b6803a80586486dc7f7\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://83b7aecd65882d8953643dce144efe91367082cc01830c9c4ed3c8a4837fb558\",\"dweb:/ipfs/QmQ5HxGavcCKjuhd8buv177qjG6A4kvxx4pZviceKdspdM\"]},\"lib/openzeppelin-contracts/contracts/utils/Arrays.sol\":{\"keccak256\":\"0x772f0c778626a7bdcbcbabca74b825ae9b9dc89d2a47a98b402b1187fbaa63a4\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://eba1d46e58e8880b45c6d51245dc94585b81d6d7290ca77ef50037a6193ed301\",\"dweb:/ipfs/Qme3CWun5qQACjGEerT2MCvhs6brKGFfJirGnzV1ypKTXA\"]},\"lib/openzeppelin-contracts/contracts/utils/Comparators.sol\":{\"keccak256\":\"0x302eecd8cf323b4690e3494a7d960b3cbce077032ab8ef655b323cdd136cec58\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://49ba706f1bc476d68fe6c1fad75517acea4e9e275be0989b548e292eb3a3eacd\",\"dweb:/ipfs/QmeBpvcdGWzWMKTQESUCEhHgnEQYYATVwPxLMxa6vMT7jC\"]},\"lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"keccak256\":\"0x493033a8d1b176a037b2cc6a04dad01a5c157722049bbecf632ca876224dd4b2\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6a708e8a5bdb1011c2c381c9a5cfd8a9a956d7d0a9dc1bd8bcdaf52f76ef2f12\",\"dweb:/ipfs/Qmax9WHBnVsZP46ZxEMNRQpLQnrdE4dK8LehML1Py8FowF\"]},\"lib/openzeppelin-contracts/contracts/utils/Panic.sol\":{\"keccak256\":\"0xf7fe324703a64fc51702311dc51562d5cb1497734f074e4f483bfb6717572d7a\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c6a5ff4f9fd8649b7ee20800b7fa387d3465bd77cf20c2d1068cd5c98e1ed57a\",\"dweb:/ipfs/QmVSaVJf9FXFhdYEYeCEfjMVHrxDh5qL4CGkxdMWpQCrqG\"]},\"lib/openzeppelin-contracts/contracts/utils/SlotDerivation.sol\":{\"keccak256\":\"0x94045fd4f268edf2b2d01ef119268548c320366d6f5294ad30c1b8f9d4f5225f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://edfda81f426f8948b3834115c21e83c48180e6db0d2a8cd2debb2185ed349337\",\"dweb:/ipfs/QmdYZneFyDAux1BuWQxLAdqtABrGS2k9WYCa7C9dvpKkWv\"]},\"lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol\":{\"keccak256\":\"0xcf74f855663ce2ae00ed8352666b7935f6cddea2932fdf2c3ecd30a9b1cd0e97\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://9f660b1f351b757dfe01438e59888f31f33ded3afcf5cb5b0d9bf9aa6f320a8b\",\"dweb:/ipfs/QmarDJ5hZEgBtCmmrVzEZWjub9769eD686jmzb2XpSU1cM\"]},\"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\":{\"keccak256\":\"0x2d9dc2fe26180f74c11c13663647d38e259e45f95eb88f57b61d2160b0109d3e\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://81233d1f98060113d9922180bb0f14f8335856fe9f339134b09335e9f678c377\",\"dweb:/ipfs/QmWh6R35SarhAn4z2wH8SU456jJSYL2FgucfTFgbHJJN4E\"]},\"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165Checker.sol\":{\"keccak256\":\"0x7c7ad70641a7f8cd44def0857ec97b0e40bfd073b2d6037a5f57ce9527ee9bc5\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://e05c6572dfe769f7aea6f3a8002951cc12d143d980dad29f6c5feedf9408bc14\",\"dweb:/ipfs/QmXM7C8YEptxisZiEefXUrwdXt3zMaCobmkCchxTtDg1oK\"]},\"lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"keccak256\":\"0x8891738ffe910f0cf2da09566928589bf5d63f4524dd734fd9cedbac3274dd5c\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://971f954442df5c2ef5b5ebf1eb245d7105d9fbacc7386ee5c796df1d45b21617\",\"dweb:/ipfs/QmadRjHbkicwqwwh61raUEapaVEtaLMcYbQZWs9gUkgj3u\"]},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"keccak256\":\"0x59973a93b1f983f94e10529f46ca46544a9fec2b5f56fb1390bbe9e0dc79f857\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c55ef8f0b9719790c2ae6f81d80a59ffb89f2f0abe6bc065585bd79edce058c5\",\"dweb:/ipfs/QmNNmCbX9NjPXKqHJN8R1WC2rNeZSQrPZLd6FF6AKLyH5Y\"]},\"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\":{\"keccak256\":\"0xc8cae21c9ae4a46e5162ff9bf5b351d6fa6a6eba72d515f3bc1bdfeda7fdf083\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://ce830ebcf28e31643caba318996db3763c36d52cd0f23798ba83c135355d45e9\",\"dweb:/ipfs/QmdGPcvptHN7UBCbUYBbRX3hiRVRFLRwno8b4uga6uFNif\"]},\"lib/openzeppelin-contracts/contracts/utils/structs/EnumerableSet.sol\":{\"keccak256\":\"0xd553ff8b7d55679f0711f1598600ac292dbd8cfdf4b2419b9cabe4c931172895\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://7905ccb27e2308fd0d90dc1212161003ab6964e1c176593db1ccedef705bcc09\",\"dweb:/ipfs/QmW37vm2PcrWLKnN74sKkvAzqSwntCEfCp4EoSEvbBHWkj\"]},\"src/RuleEngineBase.sol\":{\"keccak256\":\"0xb3d832fa55b615574d80b0e0ad76620ad236aa046523617ed5daa46ae07bf853\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://7be31bf5dbd3fa1be025cdc4b7674b76bf40e1c14ce89ec78f792cb3d7ed804e\",\"dweb:/ipfs/QmPq4xBiB3XwXerWtuonZLGiWHMqvz5tKvjhTh9AiWkbww\"]},\"src/deployment/accessControl/RuleEngine.sol\":{\"keccak256\":\"0x003d3c670256396a0ec6369ff8d44ed0a8cf1e371a44494d1d59d24f82854d86\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://9aaeb4f2e3f2b4b8ecaba4adc13c113a87f4a829af47f6d1bafa77e62c27b149\",\"dweb:/ipfs/Qmaqpqc7JwPCEM9xbctor2xPYop5cSKupsbZdp94aYeKVB\"]},\"src/deployment/accessControl/RuleEngine2771.sol\":{\"keccak256\":\"0xc85b8537e37942a7c107a28e250b4bd0287f59184af4623828b6b755958f282c\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://97a77f3219d65550e2ee092d8e2fd02358a69860a2a11b0f317fcfa325eb4fee\",\"dweb:/ipfs/QmSx6DGkoSQarfuWHG7ef1BX1gRqe1dowF5bTuecUA3uK8\"]},\"src/interfaces/IERC3643Compliance.sol\":{\"keccak256\":\"0xd0edd6697d67135853576ac6a40cadaffd787cedea98071708bbfb189c7ee5bc\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://4ed3cd3af64fccff17a1f33989cdfbdacbc0e4f32a56de11a072cf9e2277a1f6\",\"dweb:/ipfs/QmenRqRw1Yy39yDv1pJgBmnHtwuZhDdHE4omchL41CjXjb\"]},\"src/interfaces/IERC3643ComplianceExtended.sol\":{\"keccak256\":\"0x4a43bf330c7a904cba110acf52f519718d8409514c377912d5bd063c9d963729\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://c671879c591760ecbc2691e2f24adfb215a658c9fe6eb0c05dd1ca980054e585\",\"dweb:/ipfs/QmdbA19PFpJgHraF46YrcMNzUgswbTRA92atL2Lha63JLY\"]},\"src/interfaces/IRule.sol\":{\"keccak256\":\"0x81580b67f7be09049aa64d93cc1d8d691a87c639adc1cf169dc6073e1e543a5c\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://6f1808c3ed18ef1acbccdd9b30011b6e7220d388cfd66cba40b1ef0b485306a1\",\"dweb:/ipfs/QmcUCQ5MYcf7KTtoeqMKsTutPPSJhNTaK1ntHV21ioS9Fm\"]},\"src/interfaces/IRulesManagementModule.sol\":{\"keccak256\":\"0x082dd58070e83b02f275584afa872c4583ac4ca8ad12eb329fc11301470147f9\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://e2d0ad78dc323881864f406acd44976f5de39cdc97a6c99a724d8458b993e2e2\",\"dweb:/ipfs/QmRFfMbXbdiAYV3vQyNppXG7tHTji6mV1Y5Cu3ZzEQm5ng\"]},\"src/interfaces/ITokenBinding.sol\":{\"keccak256\":\"0x34dfea4e118c966adf867c0899844515566251819b4e4510fd8ee424555493fd\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://1d054ed49874816688a6e71f76d611bbdefd492d122ae386cb804c6f5af677a7\",\"dweb:/ipfs/QmRaYX4aJWYSNWNa1D4Nich3k7hkGM9rTfc9s2XaVqyRjy\"]},\"src/interfaces/ITokenBindingExtended.sol\":{\"keccak256\":\"0x01f3ab56dffce860d03e72d10e9f2d13b6bfc9004cf058c63a0b23e3b226da99\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://521e0c9651632b70d61c4c3bd0b14c6f05d818166fe65dbed8e3253158b7637e\",\"dweb:/ipfs/QmY2xEVvfV1dgtFYw6coHX3Z7Fm7yRhzPaGyt6cYBMVf76\"]},\"src/modules/ERC2771ModuleStandalone.sol\":{\"keccak256\":\"0x2135408cd37646f3a27b4a2cdb6f1b9b622541fed4f4b6311a06f986f6eb75d1\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://82229782c9664a8c039fd5a3ecedca8a827fcec190be6c527c1236c864c0418f\",\"dweb:/ipfs/QmXQmX1BFFupTPB27uJweT1tSc6nce3JXDSDa9Ztpf6cKk\"]},\"src/modules/ERC3643ComplianceExtendedModule.sol\":{\"keccak256\":\"0x6f808b068517e9e15f09fc6a9d4190001ec8c2314a10e27a85a2d43e44c84fb1\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://c62c0b77fdd8b6e7bf7aa5bf8134a78ff024d6489a23f746874a99df38a8a265\",\"dweb:/ipfs/QmV7PG3ZUUzwDs9tpooC3hmBu5e39buJnJ4TRditojJ3hu\"]},\"src/modules/ERC3643ComplianceModule.sol\":{\"keccak256\":\"0x7cda81af8687328ac2089f9d1d78352e0e75d0f70a4ba8e2b3ac82896f22863f\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://50711cb94d69ea63d787a8bb19c38c0b99539029ec8fb957a8eff00880fc11fc\",\"dweb:/ipfs/QmSapDWh5mpvWn1q6JteZisJfVGPrCz47WP2BBrJCccEjV\"]},\"src/modules/RulesManagementModule.sol\":{\"keccak256\":\"0xe4d9425613284e71a5e3d590d5433167a9751d9496f57efa914baa81f493e66d\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://d07a16e6869df86c526ef89e7e359e34a9553dc4288b262abd2979359ecf720e\",\"dweb:/ipfs/QmRy2JEsyhkv1mxv7eFaSbEWN4A3gtpPSUnnV48W2KiV4u\"]},\"src/modules/TokenBindingExtendedModule.sol\":{\"keccak256\":\"0x4e1ca7b2ec78608c3a7960bec7102a1780bdf3ec7ff544b612bafaf738b34d05\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://657bcdd303fd5a7fbe733b283f69d8e8aa73efeeeaf95c0ae7479769ac573693\",\"dweb:/ipfs/QmXiWPrv8pEqvBQck8jxC7NwB1MUdGQfLjihK6etYcZ54j\"]},\"src/modules/TokenBindingModule.sol\":{\"keccak256\":\"0xf65f46311d0078f60c30e3359dca988e39cba45b9eee53a09d618bfa70e6ef9b\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://e8c458ecfd41df5fb4a391e7ef837fd5ed5c999e61ccc0e6b4bd23023a739832\",\"dweb:/ipfs/Qmdsr765aw9fPFN2M9cSCP69o1o41FNCqhrXjHgEXNwbXV\"]},\"src/modules/VersionModule.sol\":{\"keccak256\":\"0x35daf007be8b9bb1cb9196ae2decb3e5ad4b574f6390f8fc010b78796ac42f73\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://b1b29d75e1c5023a0c6cb8c56638a17d855a3fdc051a60b9d2f304b99f7876d2\",\"dweb:/ipfs/QmXSCVjLuViC8916LwNpKtw8hqyH78Ptag3xH1n7F1fY4g\"]},\"src/modules/library/ComplianceInterfaceId.sol\":{\"keccak256\":\"0xd54bed5328e732f753d2886aeaa2761b2d66536d5247d4548e0ac1c83c7a0dac\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://ad695339fdfe72446a69d2dfbe39373affe2f37299ad921e57016069a7bc3592\",\"dweb:/ipfs/QmWathGt3E85hLfy5rrAYdb291W8VoTa4gpGPoxtWGvNNA\"]},\"src/modules/library/ERC1404InterfaceId.sol\":{\"keccak256\":\"0x07dc6905e137096cd0ae88be29b112d0e54a83ddf8ca527a281718010f6abcce\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://9249dce67cb59432bdbc9e49978c6cac0346cda3d3fca97c5a310e0f424e1600\",\"dweb:/ipfs/QmRi5awH3hjwvd3k3td48y5Cf64n1wvX9wCWy6fQLayuKs\"]},\"src/modules/library/ERC3643ComplianceRolesStorage.sol\":{\"keccak256\":\"0xe422d67495db0f630a49655d5354a9da89707e692824a100527842928db984b8\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://7d310a535b039f6d42e17e3b024841a28f58ca6434cc3555bd5bcbe9a3bb166b\",\"dweb:/ipfs/QmWMMoJngzay4mASYtJSRW6b8Em3bUVWgPca8PLhH9YPVH\"]},\"src/modules/library/RuleEngineInvariantStorage.sol\":{\"keccak256\":\"0x50a212f09f1695662965e5fba643b42a1978bec2a8368abbf43983489c983096\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://6137f01df7630527c985d85d2f7446359c678fcb933b66c55b51f583757b5c4a\",\"dweb:/ipfs/QmeHo47WQm1V99xZHS4soMk68UdtXtZhtWhV3dQC5BtA7u\"]},\"src/modules/library/RuleInterfaceId.sol\":{\"keccak256\":\"0x0d86820eee4c92b21d6704bea8ce7bd2cc1b35f6e4a1ceabbcf2a10f1c6b02ec\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://cfb560cb8588983b8c79a973d03c214a149bf1ac034fa9130ce93f0031a404d7\",\"dweb:/ipfs/Qmc6qt4E4BHdDyLUegCsgxqhf7ZFUiX4ahj8FjM54V7wpY\"]},\"src/modules/library/RulesManagementModuleInvariantStorage.sol\":{\"keccak256\":\"0xb81ea3a54c6e8d47b87d6c3d9fb5aae80c3430021b8cd66d9adeef7f5fc95893\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://cfcbadc2011f60de7189273c278dda1df2218aeeb153bee3b8a93447ec95df21\",\"dweb:/ipfs/Qmem5FqCLEfBJQdJzS7Xzd3zSfyL8Muf9Wv5WvCiBVsqfh\"]},\"src/modules/library/RulesManagementModuleRolesStorage.sol\":{\"keccak256\":\"0xbd4ccff01c8d3e2ffd8cd8e5b095a284ca6563785a683e07fcecd963568203b1\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://784fd4b297baaa29d06ec36bec3b4b391fac7c145840f7e29a5562ebd18374c5\",\"dweb:/ipfs/QmPaBDVnCvYVBVNGcSywdJKfD4Qo9JpGFbqwmc4RjDZy3A\"]},\"src/modules/library/TokenBindingModuleInvariantStorage.sol\":{\"keccak256\":\"0x9bab8e5b265068da356fd46e343a7c6c73776f3964fdeaeff056e8ce104d40a5\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://e2e75d2d52b1e4f5cbb832d194266de9a1b3a8cc2101e875dce43a2664c31a05\",\"dweb:/ipfs/QmUsd5cTPsE89WKm3kTUWsobR9JsBDUY8NdxDU5RPYpvP6\"]}},\"version\":1}","metadata":{"compiler":{"version":"0.8.37+commit.f401782d"},"language":"Solidity","output":{"abi":[{"inputs":[{"internalType":"address","name":"admin","type":"address"},{"internalType":"address","name":"forwarderIrrevocable","type":"address"},{"internalType":"address","name":"tokenContract","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"type":"error","name":"AccessControlBadConfirmation"},{"inputs":[{"internalType":"address","name":"account","type":"address"},{"internalType":"bytes32","name":"neededRole","type":"bytes32"}],"type":"error","name":"AccessControlUnauthorizedAccount"},{"inputs":[],"type":"error","name":"RuleEngine_AdminWithAddressZeroNotAllowed"},{"inputs":[],"type":"error","name":"RuleEngine_RuleInvalidInterface"},{"inputs":[],"type":"error","name":"RuleEngine_RulesManagementModule_ArrayIsEmpty"},{"inputs":[{"internalType":"uint256","name":"maxRules","type":"uint256"}],"type":"error","name":"RuleEngine_RulesManagementModule_MaxRulesExceeded"},{"inputs":[],"type":"error","name":"RuleEngine_RulesManagementModule_MaxRulesZeroNotAllowed"},{"inputs":[],"type":"error","name":"RuleEngine_RulesManagementModule_RuleAccountCannotReceivePrivileges"},{"inputs":[],"type":"error","name":"RuleEngine_RulesManagementModule_RuleAddressZeroNotAllowed"},{"inputs":[],"type":"error","name":"RuleEngine_RulesManagementModule_RuleAlreadyExists"},{"inputs":[],"type":"error","name":"RuleEngine_RulesManagementModule_RuleDoNotMatch"},{"inputs":[],"type":"error","name":"TokenBinding_InvalidTokenAddress"},{"inputs":[],"type":"error","name":"TokenBinding_TokenAlreadyBound"},{"inputs":[],"type":"error","name":"TokenBinding_TokenNotBound"},{"inputs":[],"type":"error","name":"TokenBinding_UnauthorizedCaller"},{"inputs":[{"internalType":"contract IRule","name":"rule","type":"address","indexed":true}],"type":"event","name":"AddRule","anonymous":false},{"inputs":[],"type":"event","name":"ClearRules","anonymous":false},{"inputs":[{"internalType":"contract IRule","name":"rule","type":"address","indexed":true}],"type":"event","name":"RemoveRule","anonymous":false},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32","indexed":true},{"internalType":"bytes32","name":"previousAdminRole","type":"bytes32","indexed":true},{"internalType":"bytes32","name":"newAdminRole","type":"bytes32","indexed":true}],"type":"event","name":"RoleAdminChanged","anonymous":false},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32","indexed":true},{"internalType":"address","name":"account","type":"address","indexed":true},{"internalType":"address","name":"sender","type":"address","indexed":true}],"type":"event","name":"RoleGranted","anonymous":false},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32","indexed":true},{"internalType":"address","name":"account","type":"address","indexed":true},{"internalType":"address","name":"sender","type":"address","indexed":true}],"type":"event","name":"RoleRevoked","anonymous":false},{"inputs":[{"internalType":"uint256","name":"maxRules","type":"uint256","indexed":false}],"type":"event","name":"SetMaxRules","anonymous":false},{"inputs":[{"internalType":"address","name":"token","type":"address","indexed":false}],"type":"event","name":"TokenBound","anonymous":false},{"inputs":[{"internalType":"address[]","name":"tokens","type":"address[]","indexed":false},{"internalType":"bool","name":"approved","type":"bool","indexed":false}],"type":"event","name":"TokenSelfBindingApprovalBatchSet","anonymous":false},{"inputs":[{"internalType":"address","name":"token","type":"address","indexed":true},{"internalType":"bool","name":"approved","type":"bool","indexed":false}],"type":"event","name":"TokenSelfBindingApprovalSet","anonymous":false},{"inputs":[{"internalType":"address","name":"token","type":"address","indexed":false}],"type":"event","name":"TokenUnbound","anonymous":false},{"inputs":[],"stateMutability":"view","type":"function","name":"COMPLIANCE_MANAGER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"DEFAULT_MAX_RULES","outputs":[{"internalType":"uint256","name":"","type":"uint256"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"RULES_MANAGEMENT_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}]},{"inputs":[{"internalType":"contract IRule","name":"rule_","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"addRule"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"bindToken"},{"inputs":[{"internalType":"address[]","name":"tokens","type":"address[]"}],"stateMutability":"nonpayable","type":"function","name":"bindTokens"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"view","type":"function","name":"canTransfer","outputs":[{"internalType":"bool","name":"","type":"bool"}]},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"view","type":"function","name":"canTransferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}]},{"inputs":[],"stateMutability":"nonpayable","type":"function","name":"clearRules"},{"inputs":[{"internalType":"contract IRule","name":"rule_","type":"address"}],"stateMutability":"view","type":"function","name":"containsRule","outputs":[{"internalType":"bool","name":"","type":"bool"}]},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"nonpayable","type":"function","name":"created"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"nonpayable","type":"function","name":"destroyed"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"view","type":"function","name":"detectTransferRestriction","outputs":[{"internalType":"uint8","name":"","type":"uint8"}]},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"view","type":"function","name":"detectTransferRestrictionFrom","outputs":[{"internalType":"uint8","name":"","type":"uint8"}]},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"stateMutability":"view","type":"function","name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}]},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"stateMutability":"view","type":"function","name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}]},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"stateMutability":"view","type":"function","name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}]},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"stateMutability":"view","type":"function","name":"getRoleMembers","outputs":[{"internalType":"address[]","name":"","type":"address[]"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"getTokenBound","outputs":[{"internalType":"address","name":"","type":"address"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"getTokenBounds","outputs":[{"internalType":"address[]","name":"","type":"address[]"}]},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"grantRole"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"stateMutability":"view","type":"function","name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}]},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"stateMutability":"view","type":"function","name":"isTokenBound","outputs":[{"internalType":"bool","name":"","type":"bool"}]},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"stateMutability":"view","type":"function","name":"isTokenSelfBindingApproved","outputs":[{"internalType":"bool","name":"","type":"bool"}]},{"inputs":[{"internalType":"address","name":"forwarder","type":"address"}],"stateMutability":"view","type":"function","name":"isTrustedForwarder","outputs":[{"internalType":"bool","name":"","type":"bool"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"maxRules","outputs":[{"internalType":"uint256","name":"","type":"uint256"}]},{"inputs":[{"internalType":"uint8","name":"restrictionCode","type":"uint8"}],"stateMutability":"view","type":"function","name":"messageForTransferRestriction","outputs":[{"internalType":"string","name":"","type":"string"}]},{"inputs":[{"internalType":"contract IRule","name":"rule_","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"removeRule"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"callerConfirmation","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"renounceRole"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"revokeRole"},{"inputs":[{"internalType":"uint256","name":"ruleId","type":"uint256"}],"stateMutability":"view","type":"function","name":"rule","outputs":[{"internalType":"address","name":"","type":"address"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"rules","outputs":[{"internalType":"address[]","name":"","type":"address[]"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"rulesCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}]},{"inputs":[{"internalType":"uint256","name":"maxRules_","type":"uint256"}],"stateMutability":"nonpayable","type":"function","name":"setMaxRules"},{"inputs":[{"internalType":"contract IRule[]","name":"rules_","type":"address[]"}],"stateMutability":"nonpayable","type":"function","name":"setRules"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"stateMutability":"nonpayable","type":"function","name":"setTokenSelfBindingApproval"},{"inputs":[{"internalType":"address[]","name":"tokens","type":"address[]"},{"internalType":"bool","name":"approved","type":"bool"}],"stateMutability":"nonpayable","type":"function","name":"setTokenSelfBindingApprovalBatch"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"stateMutability":"view","type":"function","name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}]},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"nonpayable","type":"function","name":"transferred"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"nonpayable","type":"function","name":"transferred"},{"inputs":[],"stateMutability":"view","type":"function","name":"trustedForwarder","outputs":[{"internalType":"address","name":"","type":"address"}]},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"unbindToken"},{"inputs":[{"internalType":"address[]","name":"tokens","type":"address[]"}],"stateMutability":"nonpayable","type":"function","name":"unbindTokens"},{"inputs":[],"stateMutability":"view","type":"function","name":"version","outputs":[{"internalType":"string","name":"version_","type":"string"}]}],"devdoc":{"kind":"dev","methods":{"addRule(address)":{"details":"Reverts when the configured maximum number of rules is already reached. Security convention: do not grant {RULES_MANAGEMENT_ROLE} to rule contracts.","params":{"rule_":"The IRule contract to add."}},"bindToken(address)":{"custom:security-note":"\"Multi-tenant\" means one instance is shared by multiple token contracts. Downstream state (for the RuleEngine: the per-address accounting held by stateful rules) is shared across all bound tokens, so binding tokens from different issuers silently cross-contaminates it. Only bind tokens that are equally trusted and governed together.","details":"Authorized by {_authorizeTokenBindingChange}.","params":{"token":"The address of the token to bind."}},"bindTokens(address[])":{"custom:security-note":"See {bindToken} for multi-tenant state risks. All tokens bound in this batch share the same downstream state. Only bind tokens that are equally trusted and governed together.","details":"Must be restricted by implementation-specific access control. Atomic: reverts if any token is invalid or already bound (or listed twice), and then binds none of them. This deliberately departs from the usual batch convention of skipping elements already in the target state: a binding change is security-relevant, and a token that is already bound in the list is most likely an operator mistake that should stop the whole operation. An empty array is a no-op.","params":{"tokens":"The token addresses to bind."}},"canTransfer(address,address,uint256)":{"details":"Don't check the balance and the user's right (access control)","params":{"from":"The address sending tokens.","to":"The address receiving tokens.","value":"The amount of tokens to transfer."},"returns":{"_0":"True if the transfer is valid, false otherwise."}},"canTransferFrom(address,address,address,uint256)":{"details":"Does not check balances or access rights (Access Control).","params":{"from":"The source address.","spender":"The address performing the transfer.","to":"The destination address.","value":"The number of tokens to transfer."},"returns":{"_0":"isCompliant True if the transfer complies with policy."}},"clearRules()":{"details":"After calling this function, no rules will remain set. Cost is O(n) in the number of configured rules. With the default cap of 10 this is negligible, but a high {maxRules} setting re-exposes unbounded cost here even though per-transfer cost remains bounded."},"constructor":{"params":{"admin":"Address receiving `DEFAULT_ADMIN_ROLE`; must not be the zero address.","forwarderIrrevocable":"Address of the trusted ERC-2771 forwarder, immutable after construction.","tokenContract":"Token to bind at deployment, or the zero address to bind none."}},"containsRule(address)":{"details":"Complexity: O(1).","params":{"rule_":"The IRule contract to check for membership."},"returns":{"_0":"True if the rule is present, false otherwise."}},"created(address,uint256)":{"details":"Called by the token contract when new tokens are issued to an account. Reverts if the minting does not comply with the rules.","params":{"to":"The address receiving the minted tokens.","value":"The number of tokens created."}},"destroyed(address,uint256)":{"details":"Called by the token contract when tokens are redeemed or burned. Reverts if the burning does not comply with the rules.","params":{"from":"The address whose tokens are being destroyed.","value":"The number of tokens destroyed."}},"detectTransferRestriction(address,address,uint256)":{"params":{"from":"the origin address","to":"the destination address","value":"to transfer"},"returns":{"_0":"The restriction code or REJECTED_CODE_BASE.TRANSFER_OK (0) if the transfer is valid"}},"detectTransferRestrictionFrom(address,address,address,uint256)":{"details":" See {ERC-1404} Add an additionnal argument `spender` This function is where an issuer enforces the restriction logic of their token transfers. Some examples of this might include: - checking if the token recipient is whitelisted, - checking if a sender's tokens are frozen in a lock-up period, etc.","params":{"from":"The address sending tokens.","spender":"The address initiating the delegated transfer.","to":"The address receiving tokens.","value":"amount of tokens to transfer"},"returns":{"_0":"uint8 restricted code, 0 means the transfer is authorized"}},"getRoleAdmin(bytes32)":{"details":"Returns the admin role that controls `role`. See {grantRole} and {revokeRole}. To change a role's admin, use {_setRoleAdmin}."},"getRoleMember(bytes32,uint256)":{"details":"Returns one of the accounts that have `role`. `index` must be a value between 0 and {getRoleMemberCount}, non-inclusive. Role bearers are not sorted in any particular way, and their ordering may change at any point. WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure you perform all queries on the same block. See the following https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post] for more information."},"getRoleMemberCount(bytes32)":{"details":"Returns the number of accounts that have `role`. Can be used together with {getRoleMember} to enumerate all bearers of a role."},"getRoleMembers(bytes32)":{"details":"Return all accounts that have `role` WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that this function has an unbounded cost, and using it as part of a state-changing function may render the function uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block."},"getTokenBound()":{"details":"If multiple tokens are supported, consider using getTokenBounds().","returns":{"_0":"The address of the currently bound token."}},"getTokenBounds()":{"details":"This operation copies the entire storage set to memory and is mainly intended for off-chain reads.","returns":{"_0":"An array of bound token addresses."}},"grantRole(bytes32,address)":{"details":"Prevents granting any role to accounts currently configured as rules. Note: this check is intentionally one-directional. {addRule} does not verify whether the rule address already holds a privileged role, and this function does not prevent adding a privileged address as a rule afterwards. Operators are responsible for keeping rule contracts and privileged accounts disjoint.","params":{"account":"The account receiving the role.","role":"The role identifier to grant."}},"hasRole(bytes32,address)":{"details":"The Default Admin has all roles","params":{"account":"The account to check.","role":"The role identifier to check."},"returns":{"_0":"True if the account holds the role (or is the default admin), false otherwise."}},"isTokenBound(address)":{"details":"Complexity: O(1).","params":{"token":"The token address to verify."},"returns":{"_0":"True if the token is bound, false otherwise."}},"isTokenSelfBindingApproved(address)":{"params":{"token":"The token address to query."},"returns":{"_0":"True if self-binding is approved for `token`, false otherwise."}},"isTrustedForwarder(address)":{"details":"Indicates whether any particular address is the trusted forwarder."},"maxRules()":{"returns":{"_0":"The maximum number of rules that can be configured."}},"messageForTransferRestriction(uint8)":{"details":"See {ERC-1404} This function is effectively an accessor for the \"message\", a human-readable explanation as to why a transaction is restricted.","params":{"restrictionCode":"The restriction code to translate into a message."},"returns":{"_0":"The human-readable message corresponding to `restrictionCode`."}},"removeRule(address)":{"details":"Reverts if the provided rule is not found or does not match the stored rule at its index. Complexity: O(1).","params":{"rule_":"The IRule contract to remove."}},"renounceRole(bytes32,address)":{"details":"Revokes `role` from the calling account. Roles are often managed via {grantRole} and {revokeRole}: this function's purpose is to provide a mechanism for accounts to lose their privileges if they are compromised (such as when a trusted device is misplaced). Emits a {RoleRevoked} event if the calling account had `role` and this call successfully revoked it. Requirements: - the caller must be `callerConfirmation`. May emit a {RoleRevoked} event."},"revokeRole(bytes32,address)":{"details":"Revokes `role` from `account`. If `account` had been granted `role`, emits a {RoleRevoked} event. Requirements: - the caller must have ``role``'s admin role. May emit a {RoleRevoked} event."},"rule(uint256)":{"details":"Reverts if `ruleId` is out of bounds. Complexity: O(1). Note that there are no guarantees on the ordering of values inside the array, and it may change when more values are added or removed.","params":{"ruleId":"The index of the desired rule in the array."},"returns":{"_0":"The address of the corresponding IRule contract, return the `zero address` is out of bounds."}},"rules()":{"details":"This is a view-only function that does not modify state. This operation will copy the entire storage to memory, which can be quite expensive. This is designed to mostly be used by view accessors that are queried without any gas fees.","returns":{"_0":"An array of all active rule contract addresses."}},"rulesCount()":{"details":"Equivalent to the length of the internal rules array. Complexity: O(1)","returns":{"_0":"The number of active rules."}},"setMaxRules(uint256)":{"details":"Access control is implementation specific (admin/owner). Setting a very high cap re-exposes unbounded gas cost for administrative operations such as {clearRules} even though normal per-transfer cost remains bounded.","params":{"maxRules_":"New maximum number of rules."}},"setRules(address[])":{"details":"Replaces the entire rule set atomically. Reverts if `rules_` is empty. Use {clearRules} to remove all rules explicitly. To transition from one non-empty set to another without an enforcement gap, call this function directly with the new set. Emits {ClearRules} when the existing rule set is non-empty, then emits {AddRule} for each new rule. Off-chain indexers must handle both events to reconstruct state. Security convention: rule contracts should be treated as trusted business logic, but should not also be granted {RULES_MANAGEMENT_ROLE}.","params":{"rules_":"The array of addresses representing the new rules to be set."}},"setTokenSelfBindingApproval(address,bool)":{"details":"Must be restricted by implementation-specific access control. An approval stays in force until it is revoked here or until the binding manager unbinds the token ({unbindToken} or {unbindTokens}), which revokes it and emits {TokenSelfBindingApprovalSet} with `false`. A token that unbinds itself keeps its approval, so it can bind itself again later.","params":{"approved":"Whether self-binding is approved for `token`.","token":"The token address to configure."}},"setTokenSelfBindingApprovalBatch(address[],bool)":{"details":"Must be restricted by implementation-specific access control. Reverts if any token in `tokens` is the zero address. Emits a single {TokenSelfBindingApprovalBatchSet} with the input array, not one {TokenSelfBindingApprovalSet} per token.","params":{"approved":"Whether self-binding is approved for all provided tokens.","tokens":"The token addresses to configure."}},"supportsInterface(bytes4)":{"params":{"interfaceId":"The interface identifier to check."},"returns":{"_0":"True if the interface is supported, false otherwise."}},"transferred(address,address,address,uint256)":{"details":"Must revert if the transfer is invalid Same name as ERC-3643 but with one supplementary argument `spender` This function can be used to update state variables of the RuleEngine contract This function can be called ONLY by the token contract bound to the RuleEngine Which overload the token calls (since CMTAT v3.3.0): - this 4-argument overload for `transferFrom` (`spender` = approved spender) and for every operation initiated by an operator, with the operator as `spender`: mint (`from == address(0)`), burn (`to == address(0)`), including `burnFrom`, self-burn and cross-chain mint/burn, and the minter `batchTransfer`; - the 3-argument ERC-3643 overload `transferred(from, to, value)`, inherited from {IERC3643IComplianceContract}, only for a direct `transfer`. Up to CMTAT v3.2.0, mint, burn and the minter transfer used the 3-argument overload. WARNING - zero-value calls are permissionless. ERC-20 requires transfers of `0` to be treated as normal transfers, and OpenZeppelin's `_spendAllowance` consumes no allowance when `value == 0`. Any address can therefore call `transferFrom(victim, anyone, 0)` on the token and reach this callback for an arbitrary `from`, with itself as `spender`, without ever having been approved. The token deliberately does not suppress the notification, because doing so would make its compliance notifications inconsistent with its own ERC-20 transfer semantics. Implementations MUST therefore treat `value == 0` as carrying no economic meaning: any stateful rule (cooldown, holding period, quota, tax bucket, counter, holder tracking, ...) MUST be a no-op for a zero value, otherwise an attacker can desynchronize policy state from balances, or keep a holder permanently restricted, at no cost. The same applies to the 3-argument ERC-3643 overload, which a zero-value `transfer(to, 0)` reaches the same way.","params":{"from":"token holder address","spender":"spender address (sender)","to":"receiver address","value":"value of tokens involved in the transfer; MAY be `0` — see the warning above"}},"transferred(address,address,uint256)":{"details":" This function can be used to update state variables of the compliance contract This function can be called ONLY by the token contract bound to the compliance","params":{"from":"The address of the sender","to":"The address of the receiver","value":"value of tokens involved in the transfer"}},"trustedForwarder()":{"details":"Returns the address of the trusted forwarder."},"unbindToken(address)":{"details":"Authorized by {_authorizeTokenBindingChange}. Operator warning: unbinding is an administrative operation and does not erase any state already stored downstream in a previously shared (\"multi-tenant\") setup.","params":{"token":"The address of the token to unbind."}},"unbindTokens(address[])":{"details":"Must be restricted by implementation-specific access control. Atomic: reverts if any token is not currently bound, and then unbinds none of them. Deliberately not the skip-if-already-done batch convention, for the same reason as {bindTokens}. An empty array is a no-op. Like a manager's {unbindToken}, revokes each token's self-binding approval (see {setTokenSelfBindingApproval}).","params":{"tokens":"The token addresses to unbind."}},"version()":{"details":"This value is useful to know which smart contract version has been used","returns":{"version_":"A string representing the version of the token implementation (e.g., \"1.0.0\")."}}},"version":1},"userdoc":{"kind":"user","methods":{"COMPLIANCE_MANAGER_ROLE()":{"notice":"Role allowed to bind and unbind tokens on the compliance contract."},"DEFAULT_MAX_RULES()":{"notice":"Default upper bound on the number of rules a RuleEngine may hold."},"RULES_MANAGEMENT_ROLE()":{"notice":"Role allowed to add, remove, set and clear rules."},"addRule(address)":{"notice":"Adds a new rule to the current rule set."},"bindToken(address)":{"notice":"Binds a token contract, allowing it to call the bound-token entry points."},"bindTokens(address[])":{"notice":"Binds several token contracts in a single call."},"canTransfer(address,address,uint256)":{"notice":"Returns true if the transfer is valid, and false otherwise."},"canTransferFrom(address,address,address,uint256)":{"notice":"Checks if `spender` can transfer `value` tokens from `from` to `to` under compliance rules."},"clearRules()":{"notice":"Removes all configured rules."},"constructor":{"notice":"Deploys the RBAC RuleEngine with a trusted forwarder."},"containsRule(address)":{"notice":"Checks whether a specific rule is currently configured."},"created(address,uint256)":{"notice":"Updates the compliance contract state when tokens are created (minted)."},"destroyed(address,uint256)":{"notice":"Updates the compliance contract state when tokens are destroyed (burned)."},"detectTransferRestriction(address,address,uint256)":{"notice":"Queries every rule, in order, and returns the first restriction code that is not zero"},"detectTransferRestrictionFrom(address,address,address,uint256)":{"notice":"Returns a uint8 code to indicate if a transfer is restricted or not"},"getTokenBound()":{"notice":"Returns the single token currently bound to this compliance contract."},"getTokenBounds()":{"notice":"Returns all tokens currently bound."},"grantRole(bytes32,address)":{"notice":"Grants `role` to `account`."},"hasRole(bytes32,address)":{"notice":"Returns `true` if `account` has been granted `role`."},"isTokenBound(address)":{"notice":"Checks whether a token is currently bound."},"isTokenSelfBindingApproved(address)":{"notice":"Returns whether a token is approved to bind and unbind itself."},"maxRules()":{"notice":"Returns the maximum number of rules allowed in the engine."},"removeRule(address)":{"notice":"Removes a specific rule from the current rule set."},"rule(uint256)":{"notice":"Retrieves the rule address at a specific index."},"rules()":{"notice":"Returns the full list of currently configured rules."},"rulesCount()":{"notice":"Returns the total number of currently configured rules."},"setMaxRules(uint256)":{"notice":"Updates the maximum number of rules allowed in the engine."},"setRules(address[])":{"notice":"Defines the rules for the rule engine."},"setTokenSelfBindingApproval(address,bool)":{"notice":"Sets whether a token is allowed to bind and unbind itself."},"setTokenSelfBindingApprovalBatch(address[],bool)":{"notice":"Sets self-binding approval for multiple tokens in one transaction."},"supportsInterface(bytes4)":{"notice":"ERC-165 interface detection."},"transferred(address,address,address,uint256)":{"notice":"Function called whenever tokens are transferred from one wallet to another, minted or burned, when the token knows the account that initiated the operation (`spender`)."},"transferred(address,address,uint256)":{"notice":"Function called whenever tokens are transferred from one wallet to another"},"unbindToken(address)":{"notice":"Unbinds a token contract, revoking its access to the bound-token entry points."},"unbindTokens(address[])":{"notice":"Unbinds several token contracts in a single call."},"version()":{"notice":"Returns the current version of the token contract."}},"version":1}},"settings":{"remappings":["@chainlink/contracts-ccip/=lib/Rules/lib/chainlink-ace/node_modules/@chainlink/contracts-ccip/chains/evm/contracts/","@chainlink/contracts/=lib/Rules/lib/chainlink-ace/node_modules/@chainlink/contracts/","@chainlink/contracts@1.4.0/=lib/Rules/lib/chainlink-doc/node_modules/@chainlink/contracts-1.4.0/","@chainlink/cross-chain-identity/=lib/Rules/lib/chainlink-ace/packages/cross-chain-identity/src/","@chainlink/local/=lib/Rules/lib/chainlink-doc/node_modules/@chainlink/local/","@chainlink/policy-management/=lib/Rules/lib/chainlink-ace/packages/policy-management/src/","@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/","@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/","@openzeppelin/contracts@4.7.3/=lib/Rules/lib/chainlink-doc/node_modules/@openzeppelin/contracts-4.7.3/","@openzeppelin/contracts@4.8.3/=lib/Rules/lib/chainlink-ace/node_modules/@openzeppelin/contracts-4.8.3/","@openzeppelin/contracts@4.9.6/=lib/Rules/lib/chainlink-doc/node_modules/@openzeppelin/contracts-4.9.6/","@openzeppelin/contracts@5.0.2/=lib/Rules/lib/chainlink-ace/node_modules/@openzeppelin/contracts/","@openzeppelin/contracts@5.1.0/=lib/Rules/lib/chainlink-doc/node_modules/@openzeppelin/contracts-5.1.0/","@openzeppelin/contracts@5.3.0/=lib/Rules/lib/chainlink-ace/node_modules/@openzeppelin/contracts-5.3.0/","CMTAT/=lib/CMTAT/contracts/","CMTATv3.0.0/=lib/CMTATv3.0.0/contracts/","ERC-3643/=lib/ERC-3643/contracts/","ERC3643/=lib/Rules/lib/ERC-3643/contracts/","RuleEngine/=lib/Rules/lib/RuleEngine/","Rules/=lib/Rules/","chainlink-ace/=lib/Rules/lib/chainlink-ace/","chainlink-doc/=lib/Rules/lib/","erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/","forge-std/=lib/forge-std/src/","halmos-cheatcodes/=lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/","openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/","openzeppelin-contracts/=lib/openzeppelin-contracts/"],"optimizer":{"enabled":true,"runs":200},"metadata":{"bytecodeHash":"ipfs"},"compilationTarget":{"src/deployment/accessControl/RuleEngine2771.sol":"RuleEngine2771"},"evmVersion":"osaka","libraries":{}},"sources":{"lib/CMTAT/contracts/interfaces/engine/IRuleEngine.sol":{"keccak256":"0xeda899e2e46a9b9c3516acb61a7f7e92ed098928379010655c330da721aaffa7","urls":["bzz-raw://60f8555330fc531dff7d0d71a862696fb286a0ba3290e41efbbbf4dd25947a3c","dweb:/ipfs/QmWvbsBGWPtNMNN2EEedwdzzvQG7NtSj9VD2fmNgqVtCXN"],"license":"MPL-2.0"},"lib/CMTAT/contracts/interfaces/technical/IERC5679.sol":{"keccak256":"0x5bee30750c9a65438469a6c5bd8465e1603eec3aeeb94c07bd64ba3e9ee766e1","urls":["bzz-raw://ef7a5c5f0d47135c97ab5d7456d31e513a71c849ae7f2f5395f860be125c4fbc","dweb:/ipfs/Qmezem3qqSjij6ggyB34wC2S15KrY9fu42oymyS9epAYCQ"],"license":"MPL-2.0"},"lib/CMTAT/contracts/interfaces/tokenization/IERC3643Partial.sol":{"keccak256":"0x5c84c2e2442824e98625c471482fb3c9502f43f4c345e7c0fb07fa549be02e26","urls":["bzz-raw://19071f2d12fb580d37eeee07885461f193568df34f3f69d2c5d65ce655d84435","dweb:/ipfs/QmRqHwC7LksE3YPohMtxFieiPerhWdoDNUUMMLbB4XYvhK"],"license":"MPL-2.0"},"lib/CMTAT/contracts/interfaces/tokenization/draft-IERC1404.sol":{"keccak256":"0xc27cdac182d930a94391d589bdafa15364b6f8d9bf211175781dba661f1c0336","urls":["bzz-raw://b509fa7f3cfd785632569f6ae3bec846aa0beefd73c1d5bde233440cae919f0f","dweb:/ipfs/QmPCAdiEun8gaMqS8KhwPpRZV2zXAPfURRaF4C2KjX5Kby"],"license":"MPL-2.0"},"lib/CMTAT/contracts/interfaces/tokenization/draft-IERC7551.sol":{"keccak256":"0x84b73eb77ec82d6d7b313eff2d87f58d3b795840d004aaa10c611b360b827e30","urls":["bzz-raw://a5b8c99fb3600369065a422d3821ba441dc06fc64f50ce0f33950a76ad82b51b","dweb:/ipfs/QmbviJsZPY3xuLU3cHUWJx11aJCPAuN4WKnCufN4kVLm2U"],"license":"MPL-2.0"},"lib/CMTAT/contracts/interfaces/tokenization/draft-IERC7943.sol":{"keccak256":"0xc69588a72da81057ee278e961e8e3bb61a28d64c3c6cebe494ce00809c1cef15","urls":["bzz-raw://148f117d9c463de441f81e6c0a67e95f1f14a61db209492dd0a1767b5572f21a","dweb:/ipfs/QmUjT5uyJfNSYgUWn5Dxhf6Sx9Y1z8CNf3PuTEaGoAx3za"],"license":"MPL-2.0"},"lib/CMTAT/contracts/library/ERC1404ExtendInterfaceId.sol":{"keccak256":"0xf8268f4eb3a6b2e26c32cf76c5c76b6c17df3385c150f05953538a2472149247","urls":["bzz-raw://05108de7a7ba2a0a67978bdfe8e500360674db6d894f42970bb1016b36639056","dweb:/ipfs/QmRux9Qj1GomATseS6Tyq9uiPPNNipuxg2HjdjnPjgSQds"],"license":"MPL-2.0"},"lib/CMTAT/contracts/library/RuleEngineInterfaceId.sol":{"keccak256":"0x1152a49cba4232d943e295d259eb8a1b216d815067367410a5729a256dae4051","urls":["bzz-raw://470f4435a5e62b0ba0ad70f8657b2db0e4cc3b7f2561772adb944ce010551ee6","dweb:/ipfs/QmXECahRr8rK9XJPZwBCnemLDVPdFvPEBusezhaBqbLBqp"],"license":"MPL-2.0"},"lib/openzeppelin-contracts/contracts/access/AccessControl.sol":{"keccak256":"0xf7e47e67e49ee2a94aa5c52580045b6ec2e6e402d2376c14a75a151664d7c98f","urls":["bzz-raw://db6acc2c30f52cb4b5561ffe1db8763200f080c6762db94e4cce0f3623db7080","dweb:/ipfs/QmecnQ1xEh1XMXqVmKZLMkj29iD2y2HJPkZnaYnAe5njFF"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/access/IAccessControl.sol":{"keccak256":"0xbff9f59c84e5337689161ce7641c0ef8e872d6a7536fbc1f5133f128887aba3c","urls":["bzz-raw://b308f882e796f7b79c9502deacb0a62983035c6f6f4e962b319ba6a1f4a77d3d","dweb:/ipfs/QmaWCW7ahEQqFjwhSUhV7Ae7WhfNvzSpE7DQ58hvEooqPL"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/access/extensions/AccessControlEnumerable.sol":{"keccak256":"0x90936bbc993aa96f6431bab0e08c9fcd35b1e58e39c188d64064ada6ed1bde03","urls":["bzz-raw://c6192bce9a802de36f6e2d852b55d0ef47f3f0a79dbed5d7d8d9c4f28982038c","dweb:/ipfs/QmTsJrPZrQ57HaZapedDBHynNUZxvgEbbddMiDxz2cauLR"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/access/extensions/IAccessControlEnumerable.sol":{"keccak256":"0xbc97d8c0d67d4d7eba1e662f0a8671712ace9e060ab03af547c4bb321aec1d8c","urls":["bzz-raw://890d156f50630d52c7be57d7e0499132d6fd92b2e1365b81531f4463b3304377","dweb:/ipfs/QmUHe9uL1ciePH2pQg7wdrgTAFRZWjcpBEAg8V1UNtXutd"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/interfaces/IERC165.sol":{"keccak256":"0x0afcb7e740d1537b252cb2676f600465ce6938398569f09ba1b9ca240dde2dfc","urls":["bzz-raw://1c299900ac4ec268d4570ecef0d697a3013cd11a6eb74e295ee3fbc945056037","dweb:/ipfs/Qmab9owJoxcA7vJT5XNayCMaUR1qxqj1NDzzisduwaJMcZ"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/metatx/ERC2771Context.sol":{"keccak256":"0x9695d220b99dcf62910533bdf5d40d4cf6a4e04d5b106b6803a80586486dc7f7","urls":["bzz-raw://83b7aecd65882d8953643dce144efe91367082cc01830c9c4ed3c8a4837fb558","dweb:/ipfs/QmQ5HxGavcCKjuhd8buv177qjG6A4kvxx4pZviceKdspdM"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/Arrays.sol":{"keccak256":"0x772f0c778626a7bdcbcbabca74b825ae9b9dc89d2a47a98b402b1187fbaa63a4","urls":["bzz-raw://eba1d46e58e8880b45c6d51245dc94585b81d6d7290ca77ef50037a6193ed301","dweb:/ipfs/Qme3CWun5qQACjGEerT2MCvhs6brKGFfJirGnzV1ypKTXA"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/Comparators.sol":{"keccak256":"0x302eecd8cf323b4690e3494a7d960b3cbce077032ab8ef655b323cdd136cec58","urls":["bzz-raw://49ba706f1bc476d68fe6c1fad75517acea4e9e275be0989b548e292eb3a3eacd","dweb:/ipfs/QmeBpvcdGWzWMKTQESUCEhHgnEQYYATVwPxLMxa6vMT7jC"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/Context.sol":{"keccak256":"0x493033a8d1b176a037b2cc6a04dad01a5c157722049bbecf632ca876224dd4b2","urls":["bzz-raw://6a708e8a5bdb1011c2c381c9a5cfd8a9a956d7d0a9dc1bd8bcdaf52f76ef2f12","dweb:/ipfs/Qmax9WHBnVsZP46ZxEMNRQpLQnrdE4dK8LehML1Py8FowF"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/Panic.sol":{"keccak256":"0xf7fe324703a64fc51702311dc51562d5cb1497734f074e4f483bfb6717572d7a","urls":["bzz-raw://c6a5ff4f9fd8649b7ee20800b7fa387d3465bd77cf20c2d1068cd5c98e1ed57a","dweb:/ipfs/QmVSaVJf9FXFhdYEYeCEfjMVHrxDh5qL4CGkxdMWpQCrqG"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/SlotDerivation.sol":{"keccak256":"0x94045fd4f268edf2b2d01ef119268548c320366d6f5294ad30c1b8f9d4f5225f","urls":["bzz-raw://edfda81f426f8948b3834115c21e83c48180e6db0d2a8cd2debb2185ed349337","dweb:/ipfs/QmdYZneFyDAux1BuWQxLAdqtABrGS2k9WYCa7C9dvpKkWv"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol":{"keccak256":"0xcf74f855663ce2ae00ed8352666b7935f6cddea2932fdf2c3ecd30a9b1cd0e97","urls":["bzz-raw://9f660b1f351b757dfe01438e59888f31f33ded3afcf5cb5b0d9bf9aa6f320a8b","dweb:/ipfs/QmarDJ5hZEgBtCmmrVzEZWjub9769eD686jmzb2XpSU1cM"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol":{"keccak256":"0x2d9dc2fe26180f74c11c13663647d38e259e45f95eb88f57b61d2160b0109d3e","urls":["bzz-raw://81233d1f98060113d9922180bb0f14f8335856fe9f339134b09335e9f678c377","dweb:/ipfs/QmWh6R35SarhAn4z2wH8SU456jJSYL2FgucfTFgbHJJN4E"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165Checker.sol":{"keccak256":"0x7c7ad70641a7f8cd44def0857ec97b0e40bfd073b2d6037a5f57ce9527ee9bc5","urls":["bzz-raw://e05c6572dfe769f7aea6f3a8002951cc12d143d980dad29f6c5feedf9408bc14","dweb:/ipfs/QmXM7C8YEptxisZiEefXUrwdXt3zMaCobmkCchxTtDg1oK"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol":{"keccak256":"0x8891738ffe910f0cf2da09566928589bf5d63f4524dd734fd9cedbac3274dd5c","urls":["bzz-raw://971f954442df5c2ef5b5ebf1eb245d7105d9fbacc7386ee5c796df1d45b21617","dweb:/ipfs/QmadRjHbkicwqwwh61raUEapaVEtaLMcYbQZWs9gUkgj3u"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/math/Math.sol":{"keccak256":"0x59973a93b1f983f94e10529f46ca46544a9fec2b5f56fb1390bbe9e0dc79f857","urls":["bzz-raw://c55ef8f0b9719790c2ae6f81d80a59ffb89f2f0abe6bc065585bd79edce058c5","dweb:/ipfs/QmNNmCbX9NjPXKqHJN8R1WC2rNeZSQrPZLd6FF6AKLyH5Y"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol":{"keccak256":"0xc8cae21c9ae4a46e5162ff9bf5b351d6fa6a6eba72d515f3bc1bdfeda7fdf083","urls":["bzz-raw://ce830ebcf28e31643caba318996db3763c36d52cd0f23798ba83c135355d45e9","dweb:/ipfs/QmdGPcvptHN7UBCbUYBbRX3hiRVRFLRwno8b4uga6uFNif"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/structs/EnumerableSet.sol":{"keccak256":"0xd553ff8b7d55679f0711f1598600ac292dbd8cfdf4b2419b9cabe4c931172895","urls":["bzz-raw://7905ccb27e2308fd0d90dc1212161003ab6964e1c176593db1ccedef705bcc09","dweb:/ipfs/QmW37vm2PcrWLKnN74sKkvAzqSwntCEfCp4EoSEvbBHWkj"],"license":"MIT"},"src/RuleEngineBase.sol":{"keccak256":"0xb3d832fa55b615574d80b0e0ad76620ad236aa046523617ed5daa46ae07bf853","urls":["bzz-raw://7be31bf5dbd3fa1be025cdc4b7674b76bf40e1c14ce89ec78f792cb3d7ed804e","dweb:/ipfs/QmPq4xBiB3XwXerWtuonZLGiWHMqvz5tKvjhTh9AiWkbww"],"license":"MPL-2.0"},"src/deployment/accessControl/RuleEngine.sol":{"keccak256":"0x003d3c670256396a0ec6369ff8d44ed0a8cf1e371a44494d1d59d24f82854d86","urls":["bzz-raw://9aaeb4f2e3f2b4b8ecaba4adc13c113a87f4a829af47f6d1bafa77e62c27b149","dweb:/ipfs/Qmaqpqc7JwPCEM9xbctor2xPYop5cSKupsbZdp94aYeKVB"],"license":"MPL-2.0"},"src/deployment/accessControl/RuleEngine2771.sol":{"keccak256":"0xc85b8537e37942a7c107a28e250b4bd0287f59184af4623828b6b755958f282c","urls":["bzz-raw://97a77f3219d65550e2ee092d8e2fd02358a69860a2a11b0f317fcfa325eb4fee","dweb:/ipfs/QmSx6DGkoSQarfuWHG7ef1BX1gRqe1dowF5bTuecUA3uK8"],"license":"MPL-2.0"},"src/interfaces/IERC3643Compliance.sol":{"keccak256":"0xd0edd6697d67135853576ac6a40cadaffd787cedea98071708bbfb189c7ee5bc","urls":["bzz-raw://4ed3cd3af64fccff17a1f33989cdfbdacbc0e4f32a56de11a072cf9e2277a1f6","dweb:/ipfs/QmenRqRw1Yy39yDv1pJgBmnHtwuZhDdHE4omchL41CjXjb"],"license":"MPL-2.0"},"src/interfaces/IERC3643ComplianceExtended.sol":{"keccak256":"0x4a43bf330c7a904cba110acf52f519718d8409514c377912d5bd063c9d963729","urls":["bzz-raw://c671879c591760ecbc2691e2f24adfb215a658c9fe6eb0c05dd1ca980054e585","dweb:/ipfs/QmdbA19PFpJgHraF46YrcMNzUgswbTRA92atL2Lha63JLY"],"license":"MPL-2.0"},"src/interfaces/IRule.sol":{"keccak256":"0x81580b67f7be09049aa64d93cc1d8d691a87c639adc1cf169dc6073e1e543a5c","urls":["bzz-raw://6f1808c3ed18ef1acbccdd9b30011b6e7220d388cfd66cba40b1ef0b485306a1","dweb:/ipfs/QmcUCQ5MYcf7KTtoeqMKsTutPPSJhNTaK1ntHV21ioS9Fm"],"license":"MPL-2.0"},"src/interfaces/IRulesManagementModule.sol":{"keccak256":"0x082dd58070e83b02f275584afa872c4583ac4ca8ad12eb329fc11301470147f9","urls":["bzz-raw://e2d0ad78dc323881864f406acd44976f5de39cdc97a6c99a724d8458b993e2e2","dweb:/ipfs/QmRFfMbXbdiAYV3vQyNppXG7tHTji6mV1Y5Cu3ZzEQm5ng"],"license":"MPL-2.0"},"src/interfaces/ITokenBinding.sol":{"keccak256":"0x34dfea4e118c966adf867c0899844515566251819b4e4510fd8ee424555493fd","urls":["bzz-raw://1d054ed49874816688a6e71f76d611bbdefd492d122ae386cb804c6f5af677a7","dweb:/ipfs/QmRaYX4aJWYSNWNa1D4Nich3k7hkGM9rTfc9s2XaVqyRjy"],"license":"MPL-2.0"},"src/interfaces/ITokenBindingExtended.sol":{"keccak256":"0x01f3ab56dffce860d03e72d10e9f2d13b6bfc9004cf058c63a0b23e3b226da99","urls":["bzz-raw://521e0c9651632b70d61c4c3bd0b14c6f05d818166fe65dbed8e3253158b7637e","dweb:/ipfs/QmY2xEVvfV1dgtFYw6coHX3Z7Fm7yRhzPaGyt6cYBMVf76"],"license":"MPL-2.0"},"src/modules/ERC2771ModuleStandalone.sol":{"keccak256":"0x2135408cd37646f3a27b4a2cdb6f1b9b622541fed4f4b6311a06f986f6eb75d1","urls":["bzz-raw://82229782c9664a8c039fd5a3ecedca8a827fcec190be6c527c1236c864c0418f","dweb:/ipfs/QmXQmX1BFFupTPB27uJweT1tSc6nce3JXDSDa9Ztpf6cKk"],"license":"MPL-2.0"},"src/modules/ERC3643ComplianceExtendedModule.sol":{"keccak256":"0x6f808b068517e9e15f09fc6a9d4190001ec8c2314a10e27a85a2d43e44c84fb1","urls":["bzz-raw://c62c0b77fdd8b6e7bf7aa5bf8134a78ff024d6489a23f746874a99df38a8a265","dweb:/ipfs/QmV7PG3ZUUzwDs9tpooC3hmBu5e39buJnJ4TRditojJ3hu"],"license":"MPL-2.0"},"src/modules/ERC3643ComplianceModule.sol":{"keccak256":"0x7cda81af8687328ac2089f9d1d78352e0e75d0f70a4ba8e2b3ac82896f22863f","urls":["bzz-raw://50711cb94d69ea63d787a8bb19c38c0b99539029ec8fb957a8eff00880fc11fc","dweb:/ipfs/QmSapDWh5mpvWn1q6JteZisJfVGPrCz47WP2BBrJCccEjV"],"license":"MPL-2.0"},"src/modules/RulesManagementModule.sol":{"keccak256":"0xe4d9425613284e71a5e3d590d5433167a9751d9496f57efa914baa81f493e66d","urls":["bzz-raw://d07a16e6869df86c526ef89e7e359e34a9553dc4288b262abd2979359ecf720e","dweb:/ipfs/QmRy2JEsyhkv1mxv7eFaSbEWN4A3gtpPSUnnV48W2KiV4u"],"license":"MPL-2.0"},"src/modules/TokenBindingExtendedModule.sol":{"keccak256":"0x4e1ca7b2ec78608c3a7960bec7102a1780bdf3ec7ff544b612bafaf738b34d05","urls":["bzz-raw://657bcdd303fd5a7fbe733b283f69d8e8aa73efeeeaf95c0ae7479769ac573693","dweb:/ipfs/QmXiWPrv8pEqvBQck8jxC7NwB1MUdGQfLjihK6etYcZ54j"],"license":"MPL-2.0"},"src/modules/TokenBindingModule.sol":{"keccak256":"0xf65f46311d0078f60c30e3359dca988e39cba45b9eee53a09d618bfa70e6ef9b","urls":["bzz-raw://e8c458ecfd41df5fb4a391e7ef837fd5ed5c999e61ccc0e6b4bd23023a739832","dweb:/ipfs/Qmdsr765aw9fPFN2M9cSCP69o1o41FNCqhrXjHgEXNwbXV"],"license":"MPL-2.0"},"src/modules/VersionModule.sol":{"keccak256":"0x35daf007be8b9bb1cb9196ae2decb3e5ad4b574f6390f8fc010b78796ac42f73","urls":["bzz-raw://b1b29d75e1c5023a0c6cb8c56638a17d855a3fdc051a60b9d2f304b99f7876d2","dweb:/ipfs/QmXSCVjLuViC8916LwNpKtw8hqyH78Ptag3xH1n7F1fY4g"],"license":"MPL-2.0"},"src/modules/library/ComplianceInterfaceId.sol":{"keccak256":"0xd54bed5328e732f753d2886aeaa2761b2d66536d5247d4548e0ac1c83c7a0dac","urls":["bzz-raw://ad695339fdfe72446a69d2dfbe39373affe2f37299ad921e57016069a7bc3592","dweb:/ipfs/QmWathGt3E85hLfy5rrAYdb291W8VoTa4gpGPoxtWGvNNA"],"license":"MPL-2.0"},"src/modules/library/ERC1404InterfaceId.sol":{"keccak256":"0x07dc6905e137096cd0ae88be29b112d0e54a83ddf8ca527a281718010f6abcce","urls":["bzz-raw://9249dce67cb59432bdbc9e49978c6cac0346cda3d3fca97c5a310e0f424e1600","dweb:/ipfs/QmRi5awH3hjwvd3k3td48y5Cf64n1wvX9wCWy6fQLayuKs"],"license":"MPL-2.0"},"src/modules/library/ERC3643ComplianceRolesStorage.sol":{"keccak256":"0xe422d67495db0f630a49655d5354a9da89707e692824a100527842928db984b8","urls":["bzz-raw://7d310a535b039f6d42e17e3b024841a28f58ca6434cc3555bd5bcbe9a3bb166b","dweb:/ipfs/QmWMMoJngzay4mASYtJSRW6b8Em3bUVWgPca8PLhH9YPVH"],"license":"MPL-2.0"},"src/modules/library/RuleEngineInvariantStorage.sol":{"keccak256":"0x50a212f09f1695662965e5fba643b42a1978bec2a8368abbf43983489c983096","urls":["bzz-raw://6137f01df7630527c985d85d2f7446359c678fcb933b66c55b51f583757b5c4a","dweb:/ipfs/QmeHo47WQm1V99xZHS4soMk68UdtXtZhtWhV3dQC5BtA7u"],"license":"MPL-2.0"},"src/modules/library/RuleInterfaceId.sol":{"keccak256":"0x0d86820eee4c92b21d6704bea8ce7bd2cc1b35f6e4a1ceabbcf2a10f1c6b02ec","urls":["bzz-raw://cfb560cb8588983b8c79a973d03c214a149bf1ac034fa9130ce93f0031a404d7","dweb:/ipfs/Qmc6qt4E4BHdDyLUegCsgxqhf7ZFUiX4ahj8FjM54V7wpY"],"license":"MPL-2.0"},"src/modules/library/RulesManagementModuleInvariantStorage.sol":{"keccak256":"0xb81ea3a54c6e8d47b87d6c3d9fb5aae80c3430021b8cd66d9adeef7f5fc95893","urls":["bzz-raw://cfcbadc2011f60de7189273c278dda1df2218aeeb153bee3b8a93447ec95df21","dweb:/ipfs/Qmem5FqCLEfBJQdJzS7Xzd3zSfyL8Muf9Wv5WvCiBVsqfh"],"license":"MPL-2.0"},"src/modules/library/RulesManagementModuleRolesStorage.sol":{"keccak256":"0xbd4ccff01c8d3e2ffd8cd8e5b095a284ca6563785a683e07fcecd963568203b1","urls":["bzz-raw://784fd4b297baaa29d06ec36bec3b4b391fac7c145840f7e29a5562ebd18374c5","dweb:/ipfs/QmPaBDVnCvYVBVNGcSywdJKfD4Qo9JpGFbqwmc4RjDZy3A"],"license":"MPL-2.0"},"src/modules/library/TokenBindingModuleInvariantStorage.sol":{"keccak256":"0x9bab8e5b265068da356fd46e343a7c6c73776f3964fdeaeff056e8ce104d40a5","urls":["bzz-raw://e2e75d2d52b1e4f5cbb832d194266de9a1b3a8cc2101e875dce43a2664c31a05","dweb:/ipfs/QmUsd5cTPsE89WKm3kTUWsobR9JsBDUY8NdxDU5RPYpvP6"],"license":"MPL-2.0"}},"version":1},"ast":{"absolutePath":"src/deployment/accessControl/RuleEngine2771.sol","id":9945,"exportedSymbols":{"Context":[3248],"ERC2771Context":[1565],"ERC2771ModuleStandalone":[13340],"RuleEngine":[9869],"RuleEngine2771":[9944]},"nodeType":"SourceUnit","src":"37:2524:31","nodes":[{"id":9871,"nodeType":"PragmaDirective","src":"37:24:31","nodes":[],"literals":["solidity","^","0.8",".27"]},{"id":9873,"nodeType":"ImportDirective","src":"91:66:31","nodes":[],"absolutePath":"lib/openzeppelin-contracts/contracts/utils/Context.sol","file":"@openzeppelin/contracts/utils/Context.sol","nameLocation":"-1:-1:-1","scope":9945,"sourceUnit":3249,"symbolAliases":[{"foreign":{"id":9872,"name":"Context","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":3248,"src":"99:7:31","typeDescriptions":{}},"nameLocation":"-1:-1:-1"}],"unitAlias":""},{"id":9876,"nodeType":"ImportDirective","src":"181:98:31","nodes":[],"absolutePath":"src/modules/ERC2771ModuleStandalone.sol","file":"../../modules/ERC2771ModuleStandalone.sol","nameLocation":"-1:-1:-1","scope":9945,"sourceUnit":13341,"symbolAliases":[{"foreign":{"id":9874,"name":"ERC2771ModuleStandalone","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":13340,"src":"189:23:31","typeDescriptions":{}},"nameLocation":"-1:-1:-1"},{"foreign":{"id":9875,"name":"ERC2771Context","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":1565,"src":"214:14:31","typeDescriptions":{}},"nameLocation":"-1:-1:-1"}],"unitAlias":""},{"id":9878,"nodeType":"ImportDirective","src":"309:44:31","nodes":[],"absolutePath":"src/deployment/accessControl/RuleEngine.sol","file":"./RuleEngine.sol","nameLocation":"-1:-1:-1","scope":9945,"sourceUnit":9870,"symbolAliases":[{"foreign":{"id":9877,"name":"RuleEngine","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":9869,"src":"317:10:31","typeDescriptions":{}},"nameLocation":"-1:-1:-1"}],"unitAlias":""},{"id":9944,"nodeType":"ContractDefinition","src":"706:1854:31","nodes":[{"id":9901,"nodeType":"FunctionDefinition","src":"1149:181:31","nodes":[],"body":{"id":9900,"nodeType":"Block","src":"1328:2:31","nodes":[],"statements":[]},"documentation":{"id":9884,"nodeType":"StructuredDocumentation","src":"775:369:31","text":" @notice Deploys the RBAC RuleEngine with a trusted forwarder.\n @param admin Address receiving `DEFAULT_ADMIN_ROLE`; must not be the zero address.\n @param forwarderIrrevocable Address of the trusted ERC-2771 forwarder, immutable after construction.\n @param tokenContract Token to bind at deployment, or the zero address to bind none."},"implemented":true,"kind":"constructor","modifiers":[{"arguments":[{"id":9893,"name":"forwarderIrrevocable","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":9888,"src":"1261:20:31","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"id":9894,"kind":"baseConstructorSpecifier","modifierName":{"id":9892,"name":"ERC2771ModuleStandalone","nameLocations":["1237:23:31"],"nodeType":"IdentifierPath","referencedDeclaration":13340,"src":"1237:23:31"},"nodeType":"ModifierInvocation","src":"1237:45:31"},{"arguments":[{"id":9896,"name":"admin","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":9886,"src":"1302:5:31","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},{"id":9897,"name":"tokenContract","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":9890,"src":"1309:13:31","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"id":9898,"kind":"baseConstructorSpecifier","modifierName":{"id":9895,"name":"RuleEngine","nameLocations":["1291:10:31"],"nodeType":"IdentifierPath","referencedDeclaration":9869,"src":"1291:10:31"},"nodeType":"ModifierInvocation","src":"1291:32:31"}],"name":"","nameLocation":"-1:-1:-1","parameters":{"id":9891,"nodeType":"ParameterList","parameters":[{"constant":false,"id":9886,"mutability":"mutable","name":"admin","nameLocation":"1169:5:31","nodeType":"VariableDeclaration","scope":9901,"src":"1161:13:31","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":9885,"name":"address","nodeType":"ElementaryTypeName","src":"1161:7:31","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"},{"constant":false,"id":9888,"mutability":"mutable","name":"forwarderIrrevocable","nameLocation":"1184:20:31","nodeType":"VariableDeclaration","scope":9901,"src":"1176:28:31","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":9887,"name":"address","nodeType":"ElementaryTypeName","src":"1176:7:31","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"},{"constant":false,"id":9890,"mutability":"mutable","name":"tokenContract","nameLocation":"1214:13:31","nodeType":"VariableDeclaration","scope":9901,"src":"1206:21:31","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":9889,"name":"address","nodeType":"ElementaryTypeName","src":"1206:7:31","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"src":"1160:68:31"},"returnParameters":{"id":9899,"nodeType":"ParameterList","parameters":[],"src":"1328:0:31"},"scope":9944,"stateMutability":"nonpayable","virtual":false,"visibility":"public"},{"id":9915,"nodeType":"FunctionDefinition","src":"1721:154:31","nodes":[],"body":{"id":9914,"nodeType":"Block","src":"1824:51:31","nodes":[],"statements":[{"expression":{"arguments":[],"expression":{"argumentTypes":[],"expression":{"id":9910,"name":"ERC2771Context","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":1565,"src":"1841:14:31","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_ERC2771Context_$1565_$","typeString":"type(contract ERC2771Context)"}},"id":9911,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberLocation":"1856:10:31","memberName":"_msgSender","nodeType":"MemberAccess","referencedDeclaration":1512,"src":"1841:25:31","typeDescriptions":{"typeIdentifier":"t_function_internal_view$__$returns$_t_address_$","typeString":"function () view returns (address)"}},"id":9912,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"nameLocations":[],"names":[],"nodeType":"FunctionCall","src":"1841:27:31","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"functionReturnParameters":9909,"id":9913,"nodeType":"Return","src":"1834:34:31"}]},"baseFunctions":[1512,3230],"documentation":{"id":9902,"nodeType":"StructuredDocumentation","src":"1510:206:31","text":" @dev Resolves the sender through ERC-2771 when the call comes from the trusted forwarder.\n @return sender The transaction sender, unwrapped from the forwarder calldata when relayed."},"implemented":true,"kind":"function","modifiers":[],"name":"_msgSender","nameLocation":"1730:10:31","overrides":{"id":9906,"nodeType":"OverrideSpecifier","overrides":[{"id":9904,"name":"ERC2771Context","nameLocations":["1774:14:31"],"nodeType":"IdentifierPath","referencedDeclaration":1565,"src":"1774:14:31"},{"id":9905,"name":"Context","nameLocations":["1790:7:31"],"nodeType":"IdentifierPath","referencedDeclaration":3248,"src":"1790:7:31"}],"src":"1765:33:31"},"parameters":{"id":9903,"nodeType":"ParameterList","parameters":[],"src":"1740:2:31"},"returnParameters":{"id":9909,"nodeType":"ParameterList","parameters":[{"constant":false,"id":9908,"mutability":"mutable","name":"sender","nameLocation":"1816:6:31","nodeType":"VariableDeclaration","scope":9915,"src":"1808:14:31","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":9907,"name":"address","nodeType":"ElementaryTypeName","src":"1808:7:31","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"src":"1807:16:31"},"scope":9944,"stateMutability":"view","virtual":true,"visibility":"internal"},{"id":9929,"nodeType":"FunctionDefinition","src":"2085:150:31","nodes":[],"body":{"id":9928,"nodeType":"Block","src":"2186:49:31","nodes":[],"statements":[{"expression":{"arguments":[],"expression":{"argumentTypes":[],"expression":{"id":9924,"name":"ERC2771Context","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":1565,"src":"2203:14:31","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_ERC2771Context_$1565_$","typeString":"type(contract ERC2771Context)"}},"id":9925,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberLocation":"2218:8:31","memberName":"_msgData","nodeType":"MemberAccess","referencedDeclaration":1554,"src":"2203:23:31","typeDescriptions":{"typeIdentifier":"t_function_internal_view$__$returns$_t_bytes_calldata_ptr_$","typeString":"function () view returns (bytes calldata)"}},"id":9926,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"nameLocations":[],"names":[],"nodeType":"FunctionCall","src":"2203:25:31","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes_calldata_ptr","typeString":"bytes calldata"}},"functionReturnParameters":9923,"id":9927,"nodeType":"Return","src":"2196:32:31"}]},"baseFunctions":[1554,3239],"documentation":{"id":9916,"nodeType":"StructuredDocumentation","src":"1881:199:31","text":" @dev Resolves the calldata through ERC-2771 when the call comes from the trusted forwarder.\n @return The transaction calldata, with the appended sender stripped when relayed."},"implemented":true,"kind":"function","modifiers":[],"name":"_msgData","nameLocation":"2094:8:31","overrides":{"id":9920,"nodeType":"OverrideSpecifier","overrides":[{"id":9918,"name":"ERC2771Context","nameLocations":["2136:14:31"],"nodeType":"IdentifierPath","referencedDeclaration":1565,"src":"2136:14:31"},{"id":9919,"name":"Context","nameLocations":["2152:7:31"],"nodeType":"IdentifierPath","referencedDeclaration":3248,"src":"2152:7:31"}],"src":"2127:33:31"},"parameters":{"id":9917,"nodeType":"ParameterList","parameters":[],"src":"2102:2:31"},"returnParameters":{"id":9923,"nodeType":"ParameterList","parameters":[{"constant":false,"id":9922,"mutability":"mutable","name":"","nameLocation":"-1:-1:-1","nodeType":"VariableDeclaration","scope":9929,"src":"2170:14:31","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_bytes_calldata_ptr","typeString":"bytes"},"typeName":{"id":9921,"name":"bytes","nodeType":"ElementaryTypeName","src":"2170:5:31","typeDescriptions":{"typeIdentifier":"t_bytes_storage_ptr","typeString":"bytes"}},"visibility":"internal"}],"src":"2169:16:31"},"scope":9944,"stateMutability":"view","virtual":true,"visibility":"internal"},{"id":9943,"nodeType":"FunctionDefinition","src":"2391:167:31","nodes":[],"body":{"id":9942,"nodeType":"Block","src":"2497:61:31","nodes":[],"statements":[{"expression":{"arguments":[],"expression":{"argumentTypes":[],"expression":{"id":9938,"name":"ERC2771Context","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":1565,"src":"2514:14:31","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_ERC2771Context_$1565_$","typeString":"type(contract ERC2771Context)"}},"id":9939,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberLocation":"2529:20:31","memberName":"_contextSuffixLength","nodeType":"MemberAccess","referencedDeclaration":1564,"src":"2514:35:31","typeDescriptions":{"typeIdentifier":"t_function_internal_view$__$returns$_t_uint256_$","typeString":"function () view returns (uint256)"}},"id":9940,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"nameLocations":[],"names":[],"nodeType":"FunctionCall","src":"2514:37:31","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"functionReturnParameters":9937,"id":9941,"nodeType":"Return","src":"2507:44:31"}]},"baseFunctions":[1564,3247],"documentation":{"id":9930,"nodeType":"StructuredDocumentation","src":"2241:145:31","text":" @dev Length of the sender suffix appended by the trusted forwarder.\n @return The length of the ERC-2771 calldata suffix."},"implemented":true,"kind":"function","modifiers":[],"name":"_contextSuffixLength","nameLocation":"2400:20:31","overrides":{"id":9934,"nodeType":"OverrideSpecifier","overrides":[{"id":9932,"name":"ERC2771Context","nameLocations":["2454:14:31"],"nodeType":"IdentifierPath","referencedDeclaration":1565,"src":"2454:14:31"},{"id":9933,"name":"Context","nameLocations":["2470:7:31"],"nodeType":"IdentifierPath","referencedDeclaration":3248,"src":"2470:7:31"}],"src":"2445:33:31"},"parameters":{"id":9931,"nodeType":"ParameterList","parameters":[],"src":"2420:2:31"},"returnParameters":{"id":9937,"nodeType":"ParameterList","parameters":[{"constant":false,"id":9936,"mutability":"mutable","name":"","nameLocation":"-1:-1:-1","nodeType":"VariableDeclaration","scope":9943,"src":"2488:7:31","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"},"typeName":{"id":9935,"name":"uint256","nodeType":"ElementaryTypeName","src":"2488:7:31","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"visibility":"internal"}],"src":"2487:9:31"},"scope":9944,"stateMutability":"view","virtual":true,"visibility":"internal"}],"abstract":false,"baseContracts":[{"baseName":{"id":9880,"name":"ERC2771ModuleStandalone","nameLocations":["733:23:31"],"nodeType":"IdentifierPath","referencedDeclaration":13340,"src":"733:23:31"},"id":9881,"nodeType":"InheritanceSpecifier","src":"733:23:31"},{"baseName":{"id":9882,"name":"RuleEngine","nameLocations":["758:10:31"],"nodeType":"IdentifierPath","referencedDeclaration":9869,"src":"758:10:31"},"id":9883,"nodeType":"InheritanceSpecifier","src":"758:10:31"}],"canonicalName":"RuleEngine2771","contractDependencies":[],"contractKind":"contract","documentation":{"id":9879,"nodeType":"StructuredDocumentation","src":"355:350:31","text":" @title Implementation of a ruleEngine as defined by the CMTAT, with RBAC access control and ERC-2771\n @dev Administrative calls may be relayed by the immutable trusted forwarder (gasless transactions).\n Token identity is never resolved through the forwarder: the bound-token gate and token self-binding\n compare the raw `msg.sender`."},"fullyImplemented":true,"linearizedBaseContracts":[9944,9869,14590,14453,1390,913,3578,9604,34,28,3800,1416,996,14477,13390,10332,13447,14176,10545,10320,14356,14606,10476,262,464,251,311,285,13340,1565,3248,13913,10442,14580,14379,123],"name":"RuleEngine2771","nameLocation":"715:14:31","scope":9945,"usedErrors":[923,926,14474,14476,14545,14547,14549,14551,14555,14557,14559,14596,14599,14602,14605],"usedEvents":[935,944,953,10450,10455,10490,10498,14565,14571,14574,14579]}],"license":"MPL-2.0"},"id":31} \ No newline at end of file diff --git a/doc/compilation/v3.0.0-rc7/foundry/RuleEngineOwnable.sol/RuleEngineOwnable.json b/doc/compilation/v3.0.0-rc7/foundry/RuleEngineOwnable.sol/RuleEngineOwnable.json new file mode 100644 index 00000000..9c8d756b --- /dev/null +++ b/doc/compilation/v3.0.0-rc7/foundry/RuleEngineOwnable.sol/RuleEngineOwnable.json @@ -0,0 +1 @@ +{"abi":[{"type":"constructor","inputs":[{"name":"owner_","type":"address","internalType":"address"},{"name":"tokenContract","type":"address","internalType":"address"}],"stateMutability":"nonpayable"},{"type":"function","name":"DEFAULT_MAX_RULES","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"addRule","inputs":[{"name":"rule_","type":"address","internalType":"contract IRule"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"bindToken","inputs":[{"name":"token","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"bindTokens","inputs":[{"name":"tokens","type":"address[]","internalType":"address[]"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"canTransfer","inputs":[{"name":"from","type":"address","internalType":"address"},{"name":"to","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"canTransferFrom","inputs":[{"name":"spender","type":"address","internalType":"address"},{"name":"from","type":"address","internalType":"address"},{"name":"to","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"clearRules","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"containsRule","inputs":[{"name":"rule_","type":"address","internalType":"contract IRule"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"created","inputs":[{"name":"to","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"destroyed","inputs":[{"name":"from","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"detectTransferRestriction","inputs":[{"name":"from","type":"address","internalType":"address"},{"name":"to","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint8","internalType":"uint8"}],"stateMutability":"view"},{"type":"function","name":"detectTransferRestrictionFrom","inputs":[{"name":"spender","type":"address","internalType":"address"},{"name":"from","type":"address","internalType":"address"},{"name":"to","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint8","internalType":"uint8"}],"stateMutability":"view"},{"type":"function","name":"getTokenBound","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"getTokenBounds","inputs":[],"outputs":[{"name":"","type":"address[]","internalType":"address[]"}],"stateMutability":"view"},{"type":"function","name":"isTokenBound","inputs":[{"name":"token","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"isTokenSelfBindingApproved","inputs":[{"name":"token","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"maxRules","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"messageForTransferRestriction","inputs":[{"name":"restrictionCode","type":"uint8","internalType":"uint8"}],"outputs":[{"name":"","type":"string","internalType":"string"}],"stateMutability":"view"},{"type":"function","name":"owner","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"removeRule","inputs":[{"name":"rule_","type":"address","internalType":"contract IRule"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"renounceOwnership","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"rule","inputs":[{"name":"ruleId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"rules","inputs":[],"outputs":[{"name":"","type":"address[]","internalType":"address[]"}],"stateMutability":"view"},{"type":"function","name":"rulesCount","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"setMaxRules","inputs":[{"name":"maxRules_","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setRules","inputs":[{"name":"rules_","type":"address[]","internalType":"contract IRule[]"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setTokenSelfBindingApproval","inputs":[{"name":"token","type":"address","internalType":"address"},{"name":"approved","type":"bool","internalType":"bool"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setTokenSelfBindingApprovalBatch","inputs":[{"name":"tokens","type":"address[]","internalType":"address[]"},{"name":"approved","type":"bool","internalType":"bool"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"supportsInterface","inputs":[{"name":"interfaceId","type":"bytes4","internalType":"bytes4"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"transferOwnership","inputs":[{"name":"newOwner","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"transferred","inputs":[{"name":"spender","type":"address","internalType":"address"},{"name":"from","type":"address","internalType":"address"},{"name":"to","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"transferred","inputs":[{"name":"from","type":"address","internalType":"address"},{"name":"to","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"unbindToken","inputs":[{"name":"token","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"unbindTokens","inputs":[{"name":"tokens","type":"address[]","internalType":"address[]"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"version","inputs":[],"outputs":[{"name":"version_","type":"string","internalType":"string"}],"stateMutability":"view"},{"type":"event","name":"AddRule","inputs":[{"name":"rule","type":"address","indexed":true,"internalType":"contract IRule"}],"anonymous":false},{"type":"event","name":"ClearRules","inputs":[],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"name":"previousOwner","type":"address","indexed":true,"internalType":"address"},{"name":"newOwner","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"RemoveRule","inputs":[{"name":"rule","type":"address","indexed":true,"internalType":"contract IRule"}],"anonymous":false},{"type":"event","name":"SetMaxRules","inputs":[{"name":"maxRules","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"TokenBound","inputs":[{"name":"token","type":"address","indexed":false,"internalType":"address"}],"anonymous":false},{"type":"event","name":"TokenSelfBindingApprovalBatchSet","inputs":[{"name":"tokens","type":"address[]","indexed":false,"internalType":"address[]"},{"name":"approved","type":"bool","indexed":false,"internalType":"bool"}],"anonymous":false},{"type":"event","name":"TokenSelfBindingApprovalSet","inputs":[{"name":"token","type":"address","indexed":true,"internalType":"address"},{"name":"approved","type":"bool","indexed":false,"internalType":"bool"}],"anonymous":false},{"type":"event","name":"TokenUnbound","inputs":[{"name":"token","type":"address","indexed":false,"internalType":"address"}],"anonymous":false},{"type":"error","name":"OwnableInvalidOwner","inputs":[{"name":"owner","type":"address","internalType":"address"}]},{"type":"error","name":"OwnableUnauthorizedAccount","inputs":[{"name":"account","type":"address","internalType":"address"}]},{"type":"error","name":"RuleEngine_AdminWithAddressZeroNotAllowed","inputs":[]},{"type":"error","name":"RuleEngine_RuleInvalidInterface","inputs":[]},{"type":"error","name":"RuleEngine_RulesManagementModule_ArrayIsEmpty","inputs":[]},{"type":"error","name":"RuleEngine_RulesManagementModule_MaxRulesExceeded","inputs":[{"name":"maxRules","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"RuleEngine_RulesManagementModule_MaxRulesZeroNotAllowed","inputs":[]},{"type":"error","name":"RuleEngine_RulesManagementModule_RuleAccountCannotReceivePrivileges","inputs":[]},{"type":"error","name":"RuleEngine_RulesManagementModule_RuleAddressZeroNotAllowed","inputs":[]},{"type":"error","name":"RuleEngine_RulesManagementModule_RuleAlreadyExists","inputs":[]},{"type":"error","name":"RuleEngine_RulesManagementModule_RuleDoNotMatch","inputs":[]},{"type":"error","name":"TokenBinding_InvalidTokenAddress","inputs":[]},{"type":"error","name":"TokenBinding_TokenAlreadyBound","inputs":[]},{"type":"error","name":"TokenBinding_TokenNotBound","inputs":[]},{"type":"error","name":"TokenBinding_UnauthorizedCaller","inputs":[]}],"bytecode":{"object":"0x6080604052600a600255348015610014575f5ffd5b50604051611e1c380380611e1c833981016040819052610033916102a4565b81816001600160a01b0381161561004d5761004d81610096565b610057600a61012e565b506001600160a01b03811661008557604051631e4fbdf760e01b81525f600482015260240160405180910390fd5b61008e81610183565b5050506102d5565b6001600160a01b0381166100bd5760405163135217db60e21b815260040160405180910390fd5b6100c6816101d4565b6100d16003826101ff565b6100ee576040516371b3c56560e11b815260040160405180910390fd5b6040516001600160a01b03821681527f2de35142b19ed5a07796cf30791959c592018f70b1d2d7c460eef8ffe713692b906020015b60405180910390a150565b805f0361014e57604051631e69e71760e21b815260040160405180910390fd5b60028190556040518181527f2292ad4720fff63e2bd104c6b1c0d72c2c729a6001c8ab4bb947cbcc5110986390602001610123565b600680546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b6101de5f8261021c565b156101fc576040516302925f7360e11b815260040160405180910390fd5b50565b5f610213836001600160a01b03841661023d565b90505b92915050565b6001600160a01b0381165f9081526001830160205260408120541515610213565b5f81815260018301602052604081205461028257508154600181810184555f848152602080822090930184905584548482528286019093526040902091909155610216565b505f610216565b80516001600160a01b038116811461029f575f5ffd5b919050565b5f5f604083850312156102b5575f5ffd5b6102be83610289565b91506102cc60208401610289565b90509250929050565b611b3a806102e25f395ff3fe608060405234801561000f575f5ffd5b5060043610610208575f3560e01c80638d2ea7721161011f578063d4ce1415116100a9578063e3c4602c11610079578063e3c4602c1461048d578063e46638e6146104a0578063e54621d2146104b3578063f2fde38b146104bb578063f76bf550146104ce575f5ffd5b8063d4ce141514610429578063db18af6c1461043c578063db75d0171461044f578063df21950f1461047a575f5ffd5b8063b27aef3a116100ef578063b27aef3a146103c3578063bb4b6121146103d6578063bc13eacc146103e9578063c7c24b18146103f1578063d32c7bb514610404575f5ffd5b80638d2ea772146103845780638da5cb5b14610397578063993e8b95146103a8578063b043572e146103bb575f5ffd5b806354e4b945116101a05780636ae728c6116101705780636ae728c614610331578063715018a6146103435780637157797f1461034b5780637f4ab1dd1461035e5780638baf29b414610371575f5ffd5b806354e4b945146102bd57806354fd4d50146102d05780635f8dead3146102fe5780636a3edf2814610311575f5ffd5b80633e5af4ca116101db5780633e5af4ca1461026f5780633ff5aa021461028257806340db3b501461029557806352f6747a146102a8575f5ffd5b806301ffc9a71461020c5780631455d0e7146102345780633284a9a5146102495780633a56d6d51461025c575b5f5ffd5b61021f61021a36600461167e565b6104d6565b60405190151581526020015b60405180910390f35b6102476102423660046116ed565b61051c565b005b61024761025736600461174d565b61056a565b61024761026a366004611784565b6105a7565b61024761027d36600461179b565b6105bb565b6102476102903660046117e9565b6105d5565b6102476102a33660046117e9565b6105e7565b6102b06105f9565b60405161022b9190611804565b61021f6102cb3660046117e9565b610609565b604080518082019091526009815268332e302e302d72633760b81b60208201525b60405161022b919061184f565b61024761030c366004611884565b610614565b610319610627565b6040516001600160a01b03909116815260200161022b565b6002545b60405190815260200161022b565b610247610649565b61021f61035936600461179b565b61065c565b6102f161036c3660046118bc565b610679565b61024761037f3660046118d7565b610684565b610247610392366004611884565b610697565b6006546001600160a01b0316610319565b61021f6103b63660046117e9565b6106aa565b6102476106b6565b6102476103d13660046116ed565b6106c6565b6102476103e4366004611915565b610779565b610335610847565b6102476103ff3660046116ed565b610851565b61041761041236600461179b565b61089a565b60405160ff909116815260200161022b565b6104176104373660046118d7565b6108b0565b61031961044a366004611784565b6108c6565b61021f61045d3660046117e9565b6001600160a01b03165f9081526005602052604090205460ff1690565b6102476104883660046117e9565b6108e8565b61024761049b3660046117e9565b6108f9565b61021f6104ae3660046118d7565b61093b565b6102b0610954565b6102476104c93660046117e9565b610960565b610335600a81565b5f6104e08261097a565b806104fb57506001600160e01b031982166307f5828d60e41b145b8061051657506301ffc9a760e01b6001600160e01b03198316145b92915050565b610524610a1b565b5f5b818110156105655761055d83838381811061054357610543611968565b905060200201602081019061055891906117e9565b610a23565b600101610526565b505050565b610572610a1b565b6001600160a01b0382166105995760405163135217db60e21b815260040160405180910390fd5b6105a38282610a2c565b5050565b6105af610a8a565b6105b881610a92565b50565b6105c3610aee565b6105cf84848484610b16565b50505050565b6105de81610bb8565b6105b881610bc1565b6105f081610bb8565b6105b881610a23565b60606106045f610c52565b905090565b5f6105168183610c5e565b61061c610aee565b6105a35f8383610c7e565b5f5f6106336003610d17565b11156106445761060460035f610d20565b505f90565b610651610d2b565b61065a5f610d58565b565b5f8061066a8686868661089a565b60ff161490505b949350505050565b606061051682610da9565b61068c610aee565b610565838383610c7e565b61069f610aee565b6105a3825f83610c7e565b5f610516600383610c5e565b6106be610a8a565b61065a610f1e565b6106ce610a8a565b5f8190036106ef576040516359203cb960e01b815260040160405180910390fd5b6002548082111561071f57604051630befc49d60e01b815260040161071691815260200190565b60405180910390fd5b505f61072a5f610d17565b111561073857610738610f1e565b5f5b818110156105655761077183838381811061075757610757611968565b905060200201602081019061076c91906117e9565b610f4f565b60010161073a565b610781610a1b565b5f5b82811015610806575f84848381811061079e5761079e611968565b90506020020160208101906107b391906117e9565b90506001600160a01b0381166107dc5760405163135217db60e21b815260040160405180910390fd5b6001600160a01b03165f908152600560205260409020805460ff1916831515179055600101610783565b507f430881f04f203566ee9b32d6444cf02e1b2a0f17ab6b4263a1ee2074d3d0f48383838360405161083a9392919061197c565b60405180910390a1505050565b5f6106045f610d17565b610859610a1b565b5f5b818110156105655761089283838381811061087857610878611968565b905060200201602081019061088d91906117e9565b610bc1565b60010161085b565b5f6108a785858585610fb5565b95945050505050565b5f6108bc848484611082565b90505b9392505050565b5f6108d05f610d17565b8210156108e1576105165f83610d20565b505f919050565b6108f0610a8a565b6105b881611146565b610901610a8a565b6002548061090e5f610d17565b10819061093157604051630befc49d60e01b815260040161071691815260200190565b506105a382610f4f565b5f806109488585856108b0565b60ff1614949350505050565b60606106046003610c52565b610968610d2b565b610971816111a3565b6105b8816111ca565b5f6001600160e01b031982166320c49ce760e01b14806109aa57506001600160e01b0319821663157094b960e31b145b806109c557506001600160e01b031982166378a8de7d60e01b145b806109e057506001600160e01b03198216630c51264760e21b145b806109fb57506001600160e01b03198216633235d15f60e11b145b8061051657506001600160e01b03198216637157797f60e01b1492915050565b61065a610a8a565b6105b881611204565b6001600160a01b0382165f81815260056020908152604091829020805460ff191685151590811790915591519182527f407b412a9b6db334d48445ec9bcad46fb50bc4b2e97f73e963e397101957a729910160405180910390a25050565b61065a610d2b565b805f03610ab257604051631e69e71760e21b815260040160405180910390fd5b60028190556040518181527f2292ad4720fff63e2bd104c6b1c0d72c2c729a6001c8ab4bb947cbcc51109863906020015b60405180910390a150565b610af9600333610c5e565b61065a57604051630599c0e960e01b815260040160405180910390fd5b5f610b205f610d17565b90505f5b81811015610bb057610b365f82610d20565b604051631f2d7a6560e11b81526001600160a01b03888116600483015287811660248301528681166044830152606482018690529190911690633e5af4ca906084015f604051808303815f87803b158015610b8f575f5ffd5b505af1158015610ba1573d5f5f3e3d5ffd5b50505050806001019050610b24565b505050505050565b6105b88161124c565b6001600160a01b038116610be85760405163135217db60e21b815260040160405180910390fd5b610bf18161128b565b610bfc600382611295565b610c19576040516371b3c56560e11b815260040160405180910390fd5b6040516001600160a01b03821681527f2de35142b19ed5a07796cf30791959c592018f70b1d2d7c460eef8ffe713692b90602001610ae3565b60605f6108bf836112a9565b6001600160a01b03165f9081526001919091016020526040902054151590565b5f610c885f610d17565b90505f5b81811015610d1057610c9e5f82610d20565b6040516322ebca6d60e21b81526001600160a01b0387811660048301528681166024830152604482018690529190911690638baf29b4906064015f604051808303815f87803b158015610cef575f5ffd5b505af1158015610d01573d5f5f3e3d5ffd5b50505050806001019050610c8c565b5050505050565b5f610516825490565b5f6108bf8383611302565b6006546001600160a01b0316331461065a5760405163118cdaa760e01b8152336004820152602401610716565b600680546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b606060ff8216610ddc57505060408051808201909152600d81526c2737a932b9ba3934b1ba34b7b760991b602082015290565b5f610de65f610d17565b90505f5b81811015610ee2575f610dfd8183610d20565b604051633e822efb60e11b815260ff871660048201529091506001600160a01b03821690637d045df690602401602060405180830381865afa158015610e45573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e6991906119d4565b15610ed957604051637f4ab1dd60e01b815260ff861660048201526001600160a01b03821690637f4ab1dd906024015f60405180830381865afa158015610eb2573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526108a79190810190611a03565b50600101610dea565b505060408051808201909152601881527f556e6b6e6f776e207265737472696374696f6e20636f64650000000000000000602082015292915050565b6040517fdbf61473843cd9be1c9791ce51ef66d0da6c9026d62ba80c1ca433b13fb729b2905f90a161065a5f611328565b610f5881611331565b610f625f82611295565b610f7f5760405163cc790a4b60e01b815260040160405180910390fd5b6040516001600160a01b038216907f60305ce6c9104acd0969d358f926bf391174340660aaf5e6215261fd6847bf46905f90a250565b5f5f610fc05f610d17565b90505f5b81811015611076575f610fd78183610d20565b60405163d32c7bb560e01b81526001600160a01b038a811660048301528981166024830152888116604483015260648201889052919091169063d32c7bb590608401602060405180830381865afa158015611034573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110589190611ab6565b905060ff81161561106d579250610671915050565b50600101610fc4565b505f9695505050505050565b5f5f61108d5f610d17565b90505f5b8181101561113b575f6110a48183610d20565b60405163d4ce141560e01b81526001600160a01b038981166004830152888116602483015260448201889052919091169063d4ce141590606401602060405180830381865afa1580156110f9573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061111d9190611ab6565b905060ff8116156111325792506108bf915050565b50600101611091565b505f95945050505050565b6111505f82611389565b61116d57604051632cdc3a4160e21b815260040160405180910390fd5b6040516001600160a01b038216907f6d83315c9718799346b67584ec64301b1457e989c8e35a8e2982a7776c04bfc4905f90a250565b6111ac81610609565b156105b8576040516302925f7360e11b815260040160405180910390fd5b6111d2610d2b565b6001600160a01b0381166111fb57604051631e4fbdf760e01b81525f6004820152602401610716565b6105b881610d58565b61120d8161139d565b336001600160a01b0382161480159061123d57506001600160a01b0381165f9081526005602052604090205460ff165b156105b8576105b8815f610a2c565b336001600160a01b03821614801561127b57506001600160a01b0381165f9081526005602052604090205460ff165b156112835750565b6105b8610a1b565b6111ac5f82610c5e565b5f6108bf836001600160a01b0384166113fe565b6060815f018054806020026020016040519081016040528092919081815260200182805480156112f657602002820191905f5260205f20905b8154815260200190600101908083116112e2575b50505050509050919050565b5f825f01828154811061131757611317611968565b905f5260205f200154905092915050565b6105b88161144a565b61133a816114a3565b611345600382610c5e565b15611363576040516302925f7360e11b815260040160405180910390fd5b61136c816114ca565b6105b857604051639952e34360e01b815260040160405180910390fd5b5f6108bf836001600160a01b038416611507565b6113a8600382611389565b6113c557604051633477dd1760e01b815260040160405180910390fd5b6040516001600160a01b03821681527f28a4ca7134a3b3f9aff286e79ad3daadb4a06d1b43d037a3a98bdc074edd9b7a90602001610ae3565b5f81815260018301602052604081205461144357508154600181810184555f848152602080822090930184905584548482528286019093526040902091909155610516565b505f610516565b5f611453825490565b90505f5b8181101561149c57826001015f845f01838154811061147857611478611968565b905f5260205f20015481526020019081526020015f205f9055806001019050611457565b50505f9055565b6001600160a01b0381166105b85760405163f9d152fb60e01b815260040160405180910390fd5b5f6114d4826115ea565b6114df57505f919050565b6114f0826358d34ba960e11b611629565b80610516575061051682632497d6cb60e01b611629565b5f81815260018301602052604081205480156115e1575f611529600183611ad1565b85549091505f9061153c90600190611ad1565b905080821461159b575f865f01828154811061155a5761155a611968565b905f5260205f200154905080875f01848154811061157a5761157a611968565b5f918252602080832090910192909255918252600188019052604090208390555b85548690806115ac576115ac611af0565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f905560019350505050610516565b5f915050610516565b5f6115fc826301ffc9a760e01b611629565b156108e1575f80611615846001600160e01b031961164a565b915091508180156106715750159392505050565b5f5f5f611636858561164a565b915091508180156108a75750949350505050565b6301ffc9a760e01b5f818152600483905290819060208260248188617530fa92505f511515601f3d11169150509250929050565b5f6020828403121561168e575f5ffd5b81356001600160e01b0319811681146108bf575f5ffd5b5f5f83601f8401126116b5575f5ffd5b50813567ffffffffffffffff8111156116cc575f5ffd5b6020830191508360208260051b85010111156116e6575f5ffd5b9250929050565b5f5f602083850312156116fe575f5ffd5b823567ffffffffffffffff811115611714575f5ffd5b611720858286016116a5565b90969095509350505050565b6001600160a01b03811681146105b8575f5ffd5b80151581146105b8575f5ffd5b5f5f6040838503121561175e575f5ffd5b82356117698161172c565b9150602083013561177981611740565b809150509250929050565b5f60208284031215611794575f5ffd5b5035919050565b5f5f5f5f608085870312156117ae575f5ffd5b84356117b98161172c565b935060208501356117c98161172c565b925060408501356117d98161172c565b9396929550929360600135925050565b5f602082840312156117f9575f5ffd5b81356108bf8161172c565b602080825282518282018190525f918401906040840190835b818110156118445783516001600160a01b031683526020938401939092019160010161181d565b509095945050505050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b5f5f60408385031215611895575f5ffd5b82356118a08161172c565b946020939093013593505050565b60ff811681146105b8575f5ffd5b5f602082840312156118cc575f5ffd5b81356108bf816118ae565b5f5f5f606084860312156118e9575f5ffd5b83356118f48161172c565b925060208401356119048161172c565b929592945050506040919091013590565b5f5f5f60408486031215611927575f5ffd5b833567ffffffffffffffff81111561193d575f5ffd5b611949868287016116a5565b909450925050602084013561195d81611740565b809150509250925092565b634e487b7160e01b5f52603260045260245ffd5b604080825281018390525f8460608301825b868110156119be5782356119a18161172c565b6001600160a01b031682526020928301929091019060010161198e565b5080925050508215156020830152949350505050565b5f602082840312156119e4575f5ffd5b81516108bf81611740565b634e487b7160e01b5f52604160045260245ffd5b5f60208284031215611a13575f5ffd5b815167ffffffffffffffff811115611a29575f5ffd5b8201601f81018413611a39575f5ffd5b805167ffffffffffffffff811115611a5357611a536119ef565b604051601f8201601f19908116603f0116810167ffffffffffffffff81118282101715611a8257611a826119ef565b604052818152828201602001861015611a99575f5ffd5b8160208401602083015e5f91810160200191909152949350505050565b5f60208284031215611ac6575f5ffd5b81516108bf816118ae565b8181038181111561051657634e487b7160e01b5f52601160045260245ffd5b634e487b7160e01b5f52603160045260245ffdfea264697066735822122035a10b548791d41704bdb7d644b8a65ae46ddf98176be36024e46a9b908b5c3564736f6c63430008250033","sourceMap":"470:1356:32:-:0;;;537:2:80;1188:46:69;;793:108:32;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;891:6;868:13;-1:-1:-1;;;;;1101:27:29;;;1097:83;;1144:25;1155:13;1144:10;:25::i;:::-;1279:31;537:2:80;1279:12:29;:31::i;:::-;-1:-1:-1;;;;;;1273:26:10;;1269:95;;1322:31;;-1:-1:-1;;;1322:31:10;;1350:1;1322:31;;;640:51:83;613:18;;1322:31:10;;;;;;;1269:95;1373:32;1392:12;1373:18;:32::i;:::-;1225:187;793:108:32;;470:1356;;4440:400:71;-1:-1:-1;;;;;4510:19:71;;4502:64;;;;-1:-1:-1;;;4502:64:71;;;;;;;;;;;;4576:26;4596:5;4576:19;:26::i;:::-;4743:23;:12;4760:5;4743:16;:23::i;:::-;4735:66;;;;-1:-1:-1;;;4735:66:71;;;;;;;;;;;;4816:17;;-1:-1:-1;;;;;658:32:83;;640:51;;4816:17:71;;628:2:83;613:18;4816:17:71;;;;;;;;4440:400;:::o;6050:225:69:-;6126:9;6139:1;6126:14;6118:82;;;;-1:-1:-1;;;6118:82:69;;;;;;;;;;;;6210:9;:21;;;6246:22;;848:25:83;;;6246:22:69;;836:2:83;821:18;6246:22:69;702:177:83;2912:187:10;3004:6;;;-1:-1:-1;;;;;3020:17:10;;;-1:-1:-1;;;;;;3020:17:10;;;;;;;3052:40;;3004:6;;;3020:17;3004:6;;3052:40;;2985:16;;3052:40;2975:124;2912:187;:::o;9793:195:28:-;9887:22;:6;9903:5;9887:15;:22::i;:::-;9886:23;9878:103;;;;-1:-1:-1;;;9878:103:28;;;;;;;;;;;;9793:195;:::o;16462:150:27:-;16532:4;16555:50;16560:3;-1:-1:-1;;;;;16580:23:27;;16555:4;:50::i;:::-;16548:57;;16462:150;;;;;:::o;17414:165::-;-1:-1:-1;;;;;17547:23:27;;17494:4;5238:21;;;:14;;;:21;;;;;;:26;;17517:55;5142:129;2538:406;2601:4;5238:21;;;:14;;;:21;;;;;;2617:321;;-1:-1:-1;2659:23:27;;;;;;;;:11;:23;;;;;;;;;;;;;2841:18;;2817:21;;;:14;;;:21;;;;;;:42;;;;2873:11;;2617:321;-1:-1:-1;2922:5:27;2915:12;;14:177:83;93:13;;-1:-1:-1;;;;;135:31:83;;125:42;;115:70;;181:1;178;171:12;115:70;14:177;;;:::o;196:293::-;275:6;283;336:2;324:9;315:7;311:23;307:32;304:52;;;352:1;349;342:12;304:52;375:40;405:9;375:40;:::i;:::-;365:50;;434:49;479:2;468:9;464:18;434:49;:::i;:::-;424:59;;196:293;;;;;:::o;702:177::-;470:1356:32;;;;;;","linkReferences":{}},"deployedBytecode":{"object":"0x608060405234801561000f575f5ffd5b5060043610610208575f3560e01c80638d2ea7721161011f578063d4ce1415116100a9578063e3c4602c11610079578063e3c4602c1461048d578063e46638e6146104a0578063e54621d2146104b3578063f2fde38b146104bb578063f76bf550146104ce575f5ffd5b8063d4ce141514610429578063db18af6c1461043c578063db75d0171461044f578063df21950f1461047a575f5ffd5b8063b27aef3a116100ef578063b27aef3a146103c3578063bb4b6121146103d6578063bc13eacc146103e9578063c7c24b18146103f1578063d32c7bb514610404575f5ffd5b80638d2ea772146103845780638da5cb5b14610397578063993e8b95146103a8578063b043572e146103bb575f5ffd5b806354e4b945116101a05780636ae728c6116101705780636ae728c614610331578063715018a6146103435780637157797f1461034b5780637f4ab1dd1461035e5780638baf29b414610371575f5ffd5b806354e4b945146102bd57806354fd4d50146102d05780635f8dead3146102fe5780636a3edf2814610311575f5ffd5b80633e5af4ca116101db5780633e5af4ca1461026f5780633ff5aa021461028257806340db3b501461029557806352f6747a146102a8575f5ffd5b806301ffc9a71461020c5780631455d0e7146102345780633284a9a5146102495780633a56d6d51461025c575b5f5ffd5b61021f61021a36600461167e565b6104d6565b60405190151581526020015b60405180910390f35b6102476102423660046116ed565b61051c565b005b61024761025736600461174d565b61056a565b61024761026a366004611784565b6105a7565b61024761027d36600461179b565b6105bb565b6102476102903660046117e9565b6105d5565b6102476102a33660046117e9565b6105e7565b6102b06105f9565b60405161022b9190611804565b61021f6102cb3660046117e9565b610609565b604080518082019091526009815268332e302e302d72633760b81b60208201525b60405161022b919061184f565b61024761030c366004611884565b610614565b610319610627565b6040516001600160a01b03909116815260200161022b565b6002545b60405190815260200161022b565b610247610649565b61021f61035936600461179b565b61065c565b6102f161036c3660046118bc565b610679565b61024761037f3660046118d7565b610684565b610247610392366004611884565b610697565b6006546001600160a01b0316610319565b61021f6103b63660046117e9565b6106aa565b6102476106b6565b6102476103d13660046116ed565b6106c6565b6102476103e4366004611915565b610779565b610335610847565b6102476103ff3660046116ed565b610851565b61041761041236600461179b565b61089a565b60405160ff909116815260200161022b565b6104176104373660046118d7565b6108b0565b61031961044a366004611784565b6108c6565b61021f61045d3660046117e9565b6001600160a01b03165f9081526005602052604090205460ff1690565b6102476104883660046117e9565b6108e8565b61024761049b3660046117e9565b6108f9565b61021f6104ae3660046118d7565b61093b565b6102b0610954565b6102476104c93660046117e9565b610960565b610335600a81565b5f6104e08261097a565b806104fb57506001600160e01b031982166307f5828d60e41b145b8061051657506301ffc9a760e01b6001600160e01b03198316145b92915050565b610524610a1b565b5f5b818110156105655761055d83838381811061054357610543611968565b905060200201602081019061055891906117e9565b610a23565b600101610526565b505050565b610572610a1b565b6001600160a01b0382166105995760405163135217db60e21b815260040160405180910390fd5b6105a38282610a2c565b5050565b6105af610a8a565b6105b881610a92565b50565b6105c3610aee565b6105cf84848484610b16565b50505050565b6105de81610bb8565b6105b881610bc1565b6105f081610bb8565b6105b881610a23565b60606106045f610c52565b905090565b5f6105168183610c5e565b61061c610aee565b6105a35f8383610c7e565b5f5f6106336003610d17565b11156106445761060460035f610d20565b505f90565b610651610d2b565b61065a5f610d58565b565b5f8061066a8686868661089a565b60ff161490505b949350505050565b606061051682610da9565b61068c610aee565b610565838383610c7e565b61069f610aee565b6105a3825f83610c7e565b5f610516600383610c5e565b6106be610a8a565b61065a610f1e565b6106ce610a8a565b5f8190036106ef576040516359203cb960e01b815260040160405180910390fd5b6002548082111561071f57604051630befc49d60e01b815260040161071691815260200190565b60405180910390fd5b505f61072a5f610d17565b111561073857610738610f1e565b5f5b818110156105655761077183838381811061075757610757611968565b905060200201602081019061076c91906117e9565b610f4f565b60010161073a565b610781610a1b565b5f5b82811015610806575f84848381811061079e5761079e611968565b90506020020160208101906107b391906117e9565b90506001600160a01b0381166107dc5760405163135217db60e21b815260040160405180910390fd5b6001600160a01b03165f908152600560205260409020805460ff1916831515179055600101610783565b507f430881f04f203566ee9b32d6444cf02e1b2a0f17ab6b4263a1ee2074d3d0f48383838360405161083a9392919061197c565b60405180910390a1505050565b5f6106045f610d17565b610859610a1b565b5f5b818110156105655761089283838381811061087857610878611968565b905060200201602081019061088d91906117e9565b610bc1565b60010161085b565b5f6108a785858585610fb5565b95945050505050565b5f6108bc848484611082565b90505b9392505050565b5f6108d05f610d17565b8210156108e1576105165f83610d20565b505f919050565b6108f0610a8a565b6105b881611146565b610901610a8a565b6002548061090e5f610d17565b10819061093157604051630befc49d60e01b815260040161071691815260200190565b506105a382610f4f565b5f806109488585856108b0565b60ff1614949350505050565b60606106046003610c52565b610968610d2b565b610971816111a3565b6105b8816111ca565b5f6001600160e01b031982166320c49ce760e01b14806109aa57506001600160e01b0319821663157094b960e31b145b806109c557506001600160e01b031982166378a8de7d60e01b145b806109e057506001600160e01b03198216630c51264760e21b145b806109fb57506001600160e01b03198216633235d15f60e11b145b8061051657506001600160e01b03198216637157797f60e01b1492915050565b61065a610a8a565b6105b881611204565b6001600160a01b0382165f81815260056020908152604091829020805460ff191685151590811790915591519182527f407b412a9b6db334d48445ec9bcad46fb50bc4b2e97f73e963e397101957a729910160405180910390a25050565b61065a610d2b565b805f03610ab257604051631e69e71760e21b815260040160405180910390fd5b60028190556040518181527f2292ad4720fff63e2bd104c6b1c0d72c2c729a6001c8ab4bb947cbcc51109863906020015b60405180910390a150565b610af9600333610c5e565b61065a57604051630599c0e960e01b815260040160405180910390fd5b5f610b205f610d17565b90505f5b81811015610bb057610b365f82610d20565b604051631f2d7a6560e11b81526001600160a01b03888116600483015287811660248301528681166044830152606482018690529190911690633e5af4ca906084015f604051808303815f87803b158015610b8f575f5ffd5b505af1158015610ba1573d5f5f3e3d5ffd5b50505050806001019050610b24565b505050505050565b6105b88161124c565b6001600160a01b038116610be85760405163135217db60e21b815260040160405180910390fd5b610bf18161128b565b610bfc600382611295565b610c19576040516371b3c56560e11b815260040160405180910390fd5b6040516001600160a01b03821681527f2de35142b19ed5a07796cf30791959c592018f70b1d2d7c460eef8ffe713692b90602001610ae3565b60605f6108bf836112a9565b6001600160a01b03165f9081526001919091016020526040902054151590565b5f610c885f610d17565b90505f5b81811015610d1057610c9e5f82610d20565b6040516322ebca6d60e21b81526001600160a01b0387811660048301528681166024830152604482018690529190911690638baf29b4906064015f604051808303815f87803b158015610cef575f5ffd5b505af1158015610d01573d5f5f3e3d5ffd5b50505050806001019050610c8c565b5050505050565b5f610516825490565b5f6108bf8383611302565b6006546001600160a01b0316331461065a5760405163118cdaa760e01b8152336004820152602401610716565b600680546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b606060ff8216610ddc57505060408051808201909152600d81526c2737a932b9ba3934b1ba34b7b760991b602082015290565b5f610de65f610d17565b90505f5b81811015610ee2575f610dfd8183610d20565b604051633e822efb60e11b815260ff871660048201529091506001600160a01b03821690637d045df690602401602060405180830381865afa158015610e45573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e6991906119d4565b15610ed957604051637f4ab1dd60e01b815260ff861660048201526001600160a01b03821690637f4ab1dd906024015f60405180830381865afa158015610eb2573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526108a79190810190611a03565b50600101610dea565b505060408051808201909152601881527f556e6b6e6f776e207265737472696374696f6e20636f64650000000000000000602082015292915050565b6040517fdbf61473843cd9be1c9791ce51ef66d0da6c9026d62ba80c1ca433b13fb729b2905f90a161065a5f611328565b610f5881611331565b610f625f82611295565b610f7f5760405163cc790a4b60e01b815260040160405180910390fd5b6040516001600160a01b038216907f60305ce6c9104acd0969d358f926bf391174340660aaf5e6215261fd6847bf46905f90a250565b5f5f610fc05f610d17565b90505f5b81811015611076575f610fd78183610d20565b60405163d32c7bb560e01b81526001600160a01b038a811660048301528981166024830152888116604483015260648201889052919091169063d32c7bb590608401602060405180830381865afa158015611034573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110589190611ab6565b905060ff81161561106d579250610671915050565b50600101610fc4565b505f9695505050505050565b5f5f61108d5f610d17565b90505f5b8181101561113b575f6110a48183610d20565b60405163d4ce141560e01b81526001600160a01b038981166004830152888116602483015260448201889052919091169063d4ce141590606401602060405180830381865afa1580156110f9573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061111d9190611ab6565b905060ff8116156111325792506108bf915050565b50600101611091565b505f95945050505050565b6111505f82611389565b61116d57604051632cdc3a4160e21b815260040160405180910390fd5b6040516001600160a01b038216907f6d83315c9718799346b67584ec64301b1457e989c8e35a8e2982a7776c04bfc4905f90a250565b6111ac81610609565b156105b8576040516302925f7360e11b815260040160405180910390fd5b6111d2610d2b565b6001600160a01b0381166111fb57604051631e4fbdf760e01b81525f6004820152602401610716565b6105b881610d58565b61120d8161139d565b336001600160a01b0382161480159061123d57506001600160a01b0381165f9081526005602052604090205460ff165b156105b8576105b8815f610a2c565b336001600160a01b03821614801561127b57506001600160a01b0381165f9081526005602052604090205460ff165b156112835750565b6105b8610a1b565b6111ac5f82610c5e565b5f6108bf836001600160a01b0384166113fe565b6060815f018054806020026020016040519081016040528092919081815260200182805480156112f657602002820191905f5260205f20905b8154815260200190600101908083116112e2575b50505050509050919050565b5f825f01828154811061131757611317611968565b905f5260205f200154905092915050565b6105b88161144a565b61133a816114a3565b611345600382610c5e565b15611363576040516302925f7360e11b815260040160405180910390fd5b61136c816114ca565b6105b857604051639952e34360e01b815260040160405180910390fd5b5f6108bf836001600160a01b038416611507565b6113a8600382611389565b6113c557604051633477dd1760e01b815260040160405180910390fd5b6040516001600160a01b03821681527f28a4ca7134a3b3f9aff286e79ad3daadb4a06d1b43d037a3a98bdc074edd9b7a90602001610ae3565b5f81815260018301602052604081205461144357508154600181810184555f848152602080822090930184905584548482528286019093526040902091909155610516565b505f610516565b5f611453825490565b90505f5b8181101561149c57826001015f845f01838154811061147857611478611968565b905f5260205f20015481526020019081526020015f205f9055806001019050611457565b50505f9055565b6001600160a01b0381166105b85760405163f9d152fb60e01b815260040160405180910390fd5b5f6114d4826115ea565b6114df57505f919050565b6114f0826358d34ba960e11b611629565b80610516575061051682632497d6cb60e01b611629565b5f81815260018301602052604081205480156115e1575f611529600183611ad1565b85549091505f9061153c90600190611ad1565b905080821461159b575f865f01828154811061155a5761155a611968565b905f5260205f200154905080875f01848154811061157a5761157a611968565b5f918252602080832090910192909255918252600188019052604090208390555b85548690806115ac576115ac611af0565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f905560019350505050610516565b5f915050610516565b5f6115fc826301ffc9a760e01b611629565b156108e1575f80611615846001600160e01b031961164a565b915091508180156106715750159392505050565b5f5f5f611636858561164a565b915091508180156108a75750949350505050565b6301ffc9a760e01b5f818152600483905290819060208260248188617530fa92505f511515601f3d11169150509250929050565b5f6020828403121561168e575f5ffd5b81356001600160e01b0319811681146108bf575f5ffd5b5f5f83601f8401126116b5575f5ffd5b50813567ffffffffffffffff8111156116cc575f5ffd5b6020830191508360208260051b85010111156116e6575f5ffd5b9250929050565b5f5f602083850312156116fe575f5ffd5b823567ffffffffffffffff811115611714575f5ffd5b611720858286016116a5565b90969095509350505050565b6001600160a01b03811681146105b8575f5ffd5b80151581146105b8575f5ffd5b5f5f6040838503121561175e575f5ffd5b82356117698161172c565b9150602083013561177981611740565b809150509250929050565b5f60208284031215611794575f5ffd5b5035919050565b5f5f5f5f608085870312156117ae575f5ffd5b84356117b98161172c565b935060208501356117c98161172c565b925060408501356117d98161172c565b9396929550929360600135925050565b5f602082840312156117f9575f5ffd5b81356108bf8161172c565b602080825282518282018190525f918401906040840190835b818110156118445783516001600160a01b031683526020938401939092019160010161181d565b509095945050505050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b5f5f60408385031215611895575f5ffd5b82356118a08161172c565b946020939093013593505050565b60ff811681146105b8575f5ffd5b5f602082840312156118cc575f5ffd5b81356108bf816118ae565b5f5f5f606084860312156118e9575f5ffd5b83356118f48161172c565b925060208401356119048161172c565b929592945050506040919091013590565b5f5f5f60408486031215611927575f5ffd5b833567ffffffffffffffff81111561193d575f5ffd5b611949868287016116a5565b909450925050602084013561195d81611740565b809150509250925092565b634e487b7160e01b5f52603260045260245ffd5b604080825281018390525f8460608301825b868110156119be5782356119a18161172c565b6001600160a01b031682526020928301929091019060010161198e565b5080925050508215156020830152949350505050565b5f602082840312156119e4575f5ffd5b81516108bf81611740565b634e487b7160e01b5f52604160045260245ffd5b5f60208284031215611a13575f5ffd5b815167ffffffffffffffff811115611a29575f5ffd5b8201601f81018413611a39575f5ffd5b805167ffffffffffffffff811115611a5357611a536119ef565b604051601f8201601f19908116603f0116810167ffffffffffffffff81118282101715611a8257611a826119ef565b604052818152828201602001861015611a99575f5ffd5b8160208401602083015e5f91810160200191909152949350505050565b5f60208284031215611ac6575f5ffd5b81516108bf816118ae565b8181038181111561051657634e487b7160e01b5f52601160045260245ffd5b634e487b7160e01b5f52603160045260245ffdfea264697066735822122035a10b548791d41704bdb7d644b8a65ae46ddf98176be36024e46a9b908b5c3564736f6c63430008250033","sourceMap":"470:1356:32:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1556:288:29;;;;;;:::i;:::-;;:::i;:::-;;;470:14:83;;463:22;445:41;;433:2;418:18;1556:288:29;;;;;;;;1872:205:70;;;;;;:::i;:::-;;:::i;:::-;;2125:251;;;;;;:::i;:::-;;:::i;3487:150:69:-;;;;;;:::i;:::-;;:::i;2583:330:28:-;;;;;;:::i;:::-;;:::i;2979:137:71:-;;;;;;:::i;:::-;;:::i;3404:141::-;;;;;;:::i;:::-;;:::i;5029:136:69:-;;;:::i;:::-;;;;;;;:::i;4333:158::-;;;;;;:::i;:::-;;:::i;737:129:72:-;852:7;;;;;;;;;;;;-1:-1:-1;;;852:7:72;;;;737:129;;;;;;;:::i;3239:155:28:-;;;;;;:::i;:::-;;:::i;2211:383:68:-;;;:::i;:::-;;;-1:-1:-1;;;;;4963:32:83;;;4945:51;;4933:2;4918:18;2211:383:68;4799:203:83;3949:124:69;4057:9;;3949:124;;;5153:25:83;;;5141:2;5126:18;3949:124:69;5007:177:83;2293:101:10;;;:::i;5266:311:28:-;;;;;;:::i;:::-;;:::i;4621:240::-;;;;;;:::i;:::-;;:::i;2982:212::-;;;;;;:::i;:::-;;:::i;3439:161::-;;;;;;:::i;:::-;;:::i;1638:85:10:-;1710:6;;-1:-1:-1;;;;;1710:6:10;1638:85;;3636:133:71;;;;;;:::i;:::-;;:::i;2691:117:69:-;;;:::i;2150:477::-;;;;;;:::i;:::-;;:::i;2424:478:70:-;;;;;;:::i;:::-;;:::i;4137:132:69:-;;;:::i;1623:201:70:-;;;;;;:::i;:::-;;:::i;4289:282:28:-;;;;;;:::i;:::-;;:::i;:::-;;;7269:4:83;7257:17;;;7239:36;;7227:2;7212:18;4289:282:28;7097:184:83;3991:242:28;;;;;;:::i;:::-;;:::i;4555:410:69:-;;;;;;:::i;:::-;;:::i;3001:151:70:-;;;;;;:::i;:::-;-1:-1:-1;;;;;3113:32:70;3090:4;3113:32;;;:25;:32;;;;;;;;;3001:151;3701:133:69;;;;;;:::i;:::-;;:::i;3040:383::-;;;;;;:::i;:::-;;:::i;4925:281:28:-;;;;;;:::i;:::-;;:::i;3200:127:70:-;;;:::i;1127:204:32:-;;;;;;:::i;:::-;;:::i;493:46:80:-;;537:2;493:46;;1556:288:29;1658:4;1681:45;1714:11;1681:32;:45::i;:::-;:103;;;-1:-1:-1;;;;;;;1730:54:29;;-1:-1:-1;;;1730:54:29;1681:103;:156;;;-1:-1:-1;;;;;;;;;;829:40:22;;;1800:37:29;1674:163;1556:288;-1:-1:-1;;1556:288:29:o;1872:205:70:-;2185:26:71;:24;:26::i;:::-;1984:9:70::1;1979:92;1999:17:::0;;::::1;1979:92;;;2037:23;2050:6;;2057:1;2050:9;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;2037:12;:23::i;:::-;2018:3;;1979:92;;;;1872:205:::0;;:::o;2125:251::-;2185:26:71;:24;:26::i;:::-;-1:-1:-1;;;;;2258:19:70;::::1;2250:64;;;;-1:-1:-1::0;;;2250:64:70::1;;;;;;;;;;;;2324:45;2353:5;2360:8;2324:28;:45::i;:::-;2125:251:::0;;:::o;3487:150:69:-;880:24;:22;:24::i;:::-;3607:23:::1;3620:9;3607:12;:23::i;:::-;3487:150:::0;:::o;2583:330:28:-;2002:18:71;:16;:18::i;:::-;2846:60:28::1;2881:7;2890:4;2896:2;2900:5;2846:34;:60::i;:::-;2583:330:::0;;;;:::o;2979:137:71:-;3047:35;3076:5;3047:28;:35::i;:::-;3092:17;3103:5;3092:10;:17::i;3404:141::-;3474:35;3503:5;3474:28;:35::i;:::-;3519:19;3532:5;3519:12;:19::i;5029:136:69:-;5108:16;5143:15;:6;:13;:15::i;:::-;5136:22;;5029:136;:::o;4333:158::-;4430:4;4453:31;4430:4;4477:5;4453:15;:31::i;3239:155:28:-;2002:18:71;:16;:18::i;:::-;3352:35:28::1;3373:1;3377:2;3381:5;3352:12;:35::i;2211:383:68:-:0;2274:7;2321:1;2297:21;:12;:19;:21::i;:::-;:25;2293:295;;;2510:19;:12;2527:1;2510:16;:19::i;2293:295::-;-1:-1:-1;2575:1:68;;2211:383::o;2293:101:10:-;1531:13;:11;:13::i;:::-;2357:30:::1;2384:1;2357:18;:30::i;:::-;2293:101::o:0;5266:311:28:-;5447:4;;5474:55;5504:7;5513:4;5519:2;5523:5;5474:29;:55::i;:::-;:96;;;5467:103;;5266:311;;;;;;;:::o;4621:240::-;4771:13;4807:47;4838:15;4807:30;:47::i;2982:212::-;2002:18:71;:16;:18::i;:::-;3158:29:28::1;3171:4;3177:2;3181:5;3158:12;:29::i;3439:161::-:0;2002:18:71;:16;:18::i;:::-;3556:37:28::1;3569:4;3583:1;3587:5;3556:12;:37::i;3636:133:71:-:0;3711:4;3734:28;:12;3756:5;3734:21;:28::i;2691:117:69:-;794:19;:17;:19::i;:::-;2788:13:::1;:11;:13::i;2150:477::-:0;794:19;:17;:19::i;:::-;2293:1:::1;2276:18:::0;;;2268:76:::1;;;;-1:-1:-1::0;;;2268:76:69::1;;;;;;;;;;;;2379:9;::::0;2362:26;;::::1;;2354:97;;;;-1:-1:-1::0;;;2354:97:69::1;;;;;;5153:25:83::0;;5141:2;5126:18;;5007:177;2354:97:69::1;;;;;;;;;;2483:1;2465:15;:6;:13;:15::i;:::-;:19;2461:63;;;2500:13;:11;:13::i;:::-;2538:9;2533:88;2553:17:::0;;::::1;2533:88;;;2591:19;2600:6;;2607:1;2600:9;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;2591:8;:19::i;:::-;2572:3;;2533:88;;2424:478:70::0;2185:26:71;:24;:26::i;:::-;2607:9:70::1;2602:229;2622:17:::0;;::::1;2602:229;;;2660:13;2676:6;;2683:1;2676:9;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;2660:25:::0;-1:-1:-1;;;;;;2707:19:70;::::1;2699:64;;;;-1:-1:-1::0;;;2699:64:70::1;;;;;;;;;;;;-1:-1:-1::0;;;;;2777:32:70::1;;::::0;;;:25:::1;:32;::::0;;;;:43;;-1:-1:-1;;2777:43:70::1;::::0;::::1;;;::::0;;-1:-1:-1;2641:3:70::1;2602:229;;;;2845:50;2878:6;;2886:8;2845:50;;;;;;;;:::i;:::-;;;;;;;;2424:478:::0;;;:::o;4137:132:69:-;4221:7;4247:15;:6;:13;:15::i;1623:201:70:-;2185:26:71;:24;:26::i;:::-;1733:9:70::1;1728:90;1748:17:::0;;::::1;1728:90;;;1786:21;1797:6;;1804:1;1797:9;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;1786:10;:21::i;:::-;1767:3;;1728:90;;4289:282:28::0;4480:5;4508:56;4539:7;4548:4;4554:2;4558:5;4508:30;:56::i;:::-;4501:63;4289:282;-1:-1:-1;;;;;4289:282:28:o;3991:242::-;4155:5;4183:43;4210:4;4216:2;4220:5;4183:26;:43::i;:::-;4176:50;;3991:242;;;;;;:::o;4555:410:69:-;4647:7;4679:15;:6;:13;:15::i;:::-;4670:6;:24;4666:293;;;4882:18;:6;4893;4882:10;:18::i;4666:293::-;-1:-1:-1;4946:1:69;;4555:410;-1:-1:-1;4555:410:69:o;3701:133::-;794:19;:17;:19::i;:::-;3809:18:::1;3821:5;3809:11;:18::i;3040:383::-:0;794:19;:17;:19::i;:::-;3274:9:::1;::::0;;3301:15:::1;3254:17;3301:13;:15::i;:::-;:27;3380:9;3293:98;;;;;-1:-1:-1::0;;;3293:98:69::1;;;;;;5153:25:83::0;;5141:2;5126:18;;5007:177;3293:98:69::1;;3401:15;3410:5;3401:8;:15::i;4925:281:28:-:0;5089:4;;5116:42;5142:4;5148:2;5152:5;5116:25;:42::i;:::-;:83;;;;4925:281;-1:-1:-1;;;;4925:281:28:o;3200:127:70:-;3264:16;3299:21;:12;:19;:21::i;1127:204:32:-;1531:13:10;:11;:13::i;:::-;1216:63:32::1;1270:8;1216:53;:63::i;:::-;1289:35;1315:8;1289:25;:35::i;11440:599:28:-:0;11533:4;-1:-1:-1;;;;;;11556:61:28;;-1:-1:-1;;;11556:61:28;;:132;;-1:-1:-1;;;;;;;11633:55:28;;-1:-1:-1;;;11633:55:28;11556:132;:214;;;-1:-1:-1;;;;;;;11704:66:28;;-1:-1:-1;;;11704:66:28;11556:214;:298;;;-1:-1:-1;;;;;;;11786:68:28;;-1:-1:-1;;;11786:68:28;11556:298;:391;;;-1:-1:-1;;;;;;;11870:77:28;;-1:-1:-1;;;11870:77:28;11556:391;:476;;;-1:-1:-1;;;;;;;11963:69:28;;-1:-1:-1;;;11963:69:28;11549:483;11440:599;-1:-1:-1;;11440:599:28:o;2998:103:68:-;3070:24;:22;:24::i;2008:174:67:-;2129:46;2169:5;2129:39;:46::i;4883:204:70:-;-1:-1:-1;;;;;4978:32:70;;;;;;:25;:32;;;;;;;;;:43;;-1:-1:-1;;4978:43:70;;;;;;;;;;5036:44;;445:41:83;;;5036:44:70;;418:18:83;5036:44:70;;;;;;;4883:204;;:::o;1603:72:32:-;1531:13:10;:11;:13::i;6050:225:69:-;6126:9;6139:1;6126:14;6118:82;;;;-1:-1:-1;;;6118:82:69;;;;;;;;;;;;6210:9;:21;;;6246:22;;5153:25:83;;;6246:22:69;;5141:2:83;5126:18;6246:22:69;;;;;;;;6050:225;:::o;6902:144:71:-;6970:33;:12;6992:10;6970:21;:33::i;:::-;6962:77;;;;-1:-1:-1;;;6962:77:71;;;;;;;;;;;9164:285:69;9271:19;9293:15;:6;:13;:15::i;:::-;9271:37;-1:-1:-1;9323:9:69;9318:125;9342:11;9338:1;:15;9318:125;;;9380:13;:6;9391:1;9380:10;:13::i;:::-;9374:58;;-1:-1:-1;;;9374:58:69;;-1:-1:-1;;;;;8575:32:83;;;9374:58:69;;;8557:51:83;8644:32;;;8624:18;;;8617:60;8713:32;;;8693:18;;;8686:60;8762:18;;;8755:34;;;9374:32:69;;;;;;;8529:19:83;;9374:58:69;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;9355:3;;;;;9318:125;;;;9261:188;9164:285;;;;:::o;1475:234:67:-;1640:62;1696:5;1640:55;:62::i;4440:400:71:-;-1:-1:-1;;;;;4510:19:71;;4502:64;;;;-1:-1:-1;;;4502:64:71;;;;;;;;;;;;4576:26;4596:5;4576:19;:26::i;:::-;4743:23;:12;4760:5;4743:16;:23::i;:::-;4735:66;;;;-1:-1:-1;;;4735:66:71;;;;;;;;;;;;4816:17;;-1:-1:-1;;;;;4963:32:83;;4945:51;;4816:17:71;;4933:2:83;4918:18;4816:17:71;4799:203:83;19500:273:27;19563:16;19591:22;19616:19;19624:3;19616:7;:19::i;17414:165::-;-1:-1:-1;;;;;17547:23:27;17494:4;5238:21;;;:14;;;;;:21;;;;;;:26;;;17414:165::o;8250:259:69:-;8340:19;8362:15;:6;:13;:15::i;:::-;8340:37;-1:-1:-1;8392:9:69;8387:116;8411:11;8407:1;:15;8387:116;;;8449:13;:6;8460:1;8449:10;:13::i;:::-;8443:49;;-1:-1:-1;;;8443:49:69;;-1:-1:-1;;;;;9020:32:83;;;8443:49:69;;;9002:51:83;9089:32;;;9069:18;;;9062:60;9138:18;;;9131:34;;;8443:32:69;;;;;;;8975:18:83;;8443:49:69;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8424:3;;;;;8387:116;;;;8330:179;8250:259;;;:::o;17660:115:27:-;17723:7;17749:19;17757:3;5434:18;;5352:107;18802:158;18877:7;18927:23;18932:3;18944:5;18927:4;:23::i;1796:162:10:-;1710:6;;-1:-1:-1;;;;;1710:6:10;735:10:18;1855:23:10;1851:101;;1901:40;;-1:-1:-1;;;1901:40:10;;735:10:18;1901:40:10;;;4945:51:83;4918:18;;1901:40:10;4799:203:83;2912:187:10;3004:6;;;-1:-1:-1;;;;;3020:17:10;;;-1:-1:-1;;;;;;3020:17:10;;;;;;;3052:40;;3004:6;;;3020:17;3004:6;;3052:40;;2985:16;;3052:40;2975:124;2912:187;:::o;8179:594:28:-;8273:13;8302:56;;;8298:110;;-1:-1:-1;;8381:16:28;;;;;;;;;;;;-1:-1:-1;;;8381:16:28;;;;;8179:594::o;8298:110::-;8417:19;8439:15;:6;:13;:15::i;:::-;8417:37;-1:-1:-1;8469:9:28;8464:267;8488:11;8484:1;:15;8464:267;;;8520:11;8540:13;8520:11;8551:1;8540:10;:13::i;:::-;8572:55;;-1:-1:-1;;;8572:55:28;;7269:4:83;7257:17;;8572:55:28;;;7239:36:83;8520:34:28;;-1:-1:-1;;;;;;8572:38:28;;;;;7212:18:83;;8572:55:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;8568:153;;;8654:52;;-1:-1:-1;;;8654:52:28;;7269:4:83;7257:17;;8654:52:28;;;7239:36:83;-1:-1:-1;;;;;8654:35:28;;;;;7212:18:83;;8654:52:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;8654:52:28;;;;;;;;;;;;:::i;8568:153::-;-1:-1:-1;8501:3:28;;8464:267;;;-1:-1:-1;;8747:19:28;;;;;;;;;;;;;;;;;;8179:594;-1:-1:-1;;8179:594:28:o;5444:98:69:-;5499:12;;;;;;;5521:14;:6;:12;:14::i;6762:312::-;6820:26;6839:5;6820:10;:26::i;:::-;6957;:6;6976:5;6957:10;:26::i;:::-;6949:89;;;;-1:-1:-1;;;6949:89:69;;;;;;;;;;;;7053:14;;-1:-1:-1;;;;;7053:14:69;;;;;;;;6762:312;:::o;6974:537:28:-;7135:5;7156:19;7178:15;:6;:13;:15::i;:::-;7156:37;-1:-1:-1;7208:9:28;7203:248;7227:11;7223:1;:15;7203:248;;;7259:17;7285:13;7259:17;7296:1;7285:10;:13::i;:::-;7279:76;;-1:-1:-1;;;7279:76:28;;-1:-1:-1;;;;;8575:32:83;;;7279:76:28;;;8557:51:83;8644:32;;;8624:18;;;8617:60;8713:32;;;8693:18;;;8686:60;8762:18;;;8755:34;;;7279:50:28;;;;;;;8529:19:83;;7279:76:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;7259:96;-1:-1:-1;7373:15:28;;;;7369:72;;7415:11;-1:-1:-1;7408:18:28;;-1:-1:-1;;7408:18:28;7369:72;-1:-1:-1;7240:3:28;;7203:248;;;-1:-1:-1;7473:30:28;7460:44;6974:537;-1:-1:-1;;;;;;6974:537:28:o;6110:467::-;6218:5;6235:19;6257:15;:6;:13;:15::i;:::-;6235:37;-1:-1:-1;6287:9:28;6282:235;6306:11;6302:1;:15;6282:235;;;6338:17;6364:13;6338:17;6375:1;6364:10;:13::i;:::-;6358:63;;-1:-1:-1;;;6358:63:28;;-1:-1:-1;;;;;9020:32:83;;;6358:63:28;;;9002:51:83;9089:32;;;9069:18;;;9062:60;9138:18;;;9131:34;;;6358:46:28;;;;;;;8975:18:83;;6358:63:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;6338:83;-1:-1:-1;6439:15:28;;;;6435:72;;6481:11;-1:-1:-1;6474:18:28;;-1:-1:-1;;6474:18:28;6435:72;-1:-1:-1;6319:3:28;;6282:235;;;-1:-1:-1;6539:30:28;6526:44;6110:467;-1:-1:-1;;;;;6110:467:28:o;7335:255:69:-;7470:29;:6;7492:5;7470:13;:29::i;:::-;7462:89;;;;-1:-1:-1;;;7462:89:69;;;;;;;;;;;;7566:17;;-1:-1:-1;;;;;7566:17:69;;;;;;;;7335:255;:::o;2022:206:29:-;2120:29;2139:8;2120:12;:29::i;:::-;2119:30;2111:110;;;;-1:-1:-1;;;2111:110:29;;;;;;;;;;;2543:215:10;1531:13;:11;:13::i;:::-;-1:-1:-1;;;;;2627:22:10;::::1;2623:91;;2672:31;::::0;-1:-1:-1;;;2672:31:10;;2700:1:::1;2672:31;::::0;::::1;4945:51:83::0;4918:18;;2672:31:10::1;4799:203:83::0;2623:91:10::1;2723:28;2742:8;2723:18;:28::i;4275:255:70:-:0;4348:38;4380:5;4348:31;:38::i;:::-;4400:10;-1:-1:-1;;;;;4400:19:70;;;;;;:55;;-1:-1:-1;;;;;;4423:32:70;;;;;;:25;:32;;;;;;;;4400:55;4396:128;;;4471:42;4500:5;4507;4471:28;:42::i;5759:223::-;5852:10;-1:-1:-1;;;;;5852:19:70;;;:55;;;;-1:-1:-1;;;;;;5875:32:70;;;;;;:25;:32;;;;;;;;5852:55;5848:92;;;5759:223;:::o;5848:92::-;5949:26;:24;:26::i;9793:195:28:-;9887:22;:6;9903:5;9887:15;:22::i;16462:150:27:-;16532:4;16555:50;16560:3;-1:-1:-1;;;;;16580:23:27;;16555:4;:50::i;6460:109::-;6516:16;6551:3;:11;;6544:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6460:109;;;:::o;5801:119::-;5869:7;5895:3;:11;;5907:5;5895:18;;;;;;;;:::i;:::-;;;;;;;;;5888:25;;5801:119;;;;:::o;17250:83::-;17308:18;17315:3;17308:6;:18::i;9061:324:28:-;9137:39;9170:5;9137:32;:39::i;:::-;9195:28;:12;9217:5;9195:21;:28::i;:::-;9194:29;9186:109;;;;-1:-1:-1;;;9186:109:28;;;;;;;;;;;;9313:29;9336:5;9313:22;:29::i;:::-;9305:73;;;;-1:-1:-1;;;9305:73:28;;;;;;;;;;;16780:156:27;16853:4;16876:53;16884:3;-1:-1:-1;;;;;16904:23:27;;16876:7;:53::i;5410:294:71:-;5605:26;:12;5625:5;5605:19;:26::i;:::-;5597:65;;;;-1:-1:-1;;;5597:65:71;;;;;;;;;;;;5678:19;;-1:-1:-1;;;;;4963:32:83;;4945:51;;5678:19:71;;4933:2:83;4918:18;5678:19:71;4799:203:83;2538:406:27;2601:4;5238:21;;;:14;;;:21;;;;;;2617:321;;-1:-1:-1;2659:23:27;;;;;;;;:11;:23;;;;;;;;;;;;;2841:18;;2817:21;;;:14;;;:21;;;;;;:42;;;;2873:11;;2617:321;-1:-1:-1;2922:5:27;2915:12;;4824:237;4875:11;4889:12;4897:3;5434:18;;5352:107;4889:12;4875:26;-1:-1:-1;4916:9:27;4911:96;4935:3;4931:1;:7;4911:96;;;4966:3;:14;;:30;4981:3;:11;;4993:1;4981:14;;;;;;;;:::i;:::-;;;;;;;;;4966:30;;;;;;;;;;;4959:37;;;4940:3;;;;;4911:96;;;-1:-1:-1;;5039:11:27;34209:23:16;;2125:251:70:o;9974:164:69:-;-1:-1:-1;;;;;10049:19:69;;10041:90;;;;-1:-1:-1;;;10041:90:69;;;;;;;;;;;10702:397:28;10780:4;10801:35;10830:5;10801:28;:35::i;:::-;10796:79;;-1:-1:-1;10859:5:28;;10702:397;-1:-1:-1;10702:397:28:o;10796:79::-;10891:89;10938:5;-1:-1:-1;;;10891:46:28;:89::i;:::-;:201;;;-1:-1:-1;10996:96:28;11043:5;-1:-1:-1;;;10996:46:28;:96::i;3112:1368:27:-;3178:4;3307:21;;;:14;;;:21;;;;;;3343:13;;3339:1135;;3710:18;3731:12;3742:1;3731:8;:12;:::i;:::-;3777:18;;3710:33;;-1:-1:-1;3757:17:27;;3777:22;;3798:1;;3777:22;:::i;:::-;3757:42;;3832:9;3818:10;:23;3814:378;;3861:17;3881:3;:11;;3893:9;3881:22;;;;;;;;:::i;:::-;;;;;;;;;3861:42;;4028:9;4002:3;:11;;4014:10;4002:23;;;;;;;;:::i;:::-;;;;;;;;;;;;:35;;;;4141:25;;;:14;;;:25;;;;;:36;;;3814:378;4270:17;;:3;;:17;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;4373:3;:14;;:21;4388:5;4373:21;;;;;;;;;;;4366:28;;;4416:4;4409:11;;;;;;;3339:1135;4458:5;4451:12;;;;;719:528:23;783:4;976:68;1009:7;-1:-1:-1;;;976:32:23;:68::i;:::-;972:269;;;1061:12;;1093:52;1115:7;-1:-1:-1;;;;;;1093:21:23;:52::i;:::-;1060:85;;;;1166:7;:21;;;;-1:-1:-1;1177:10:23;;1159:28;-1:-1:-1;;;719:528:23:o;4504:238::-;4606:4;4623:12;4637:14;4655:43;4677:7;4686:11;4655:21;:43::i;:::-;4622:76;;;;4715:7;:20;;;;-1:-1:-1;4726:9:23;4708:27;-1:-1:-1;;;;4504:238:23:o;5198:628::-;-1:-1:-1;;;5310:12:23;5452:22;;;5494:4;5487:25;;;5310:12;;;5581:4;5310:12;5569:4;5310:12;5554:7;5547:5;5536:50;5525:61;;5740:4;5734:11;5727:19;5720:27;5654:4;5636:16;5633:26;5612:198;5599:211;;5438:382;5198:628;;;;;:::o;14:286:83:-;72:6;125:2;113:9;104:7;100:23;96:32;93:52;;;141:1;138;131:12;93:52;167:23;;-1:-1:-1;;;;;;219:32:83;;209:43;;199:71;;266:1;263;256:12;497:367;560:8;570:6;624:3;617:4;609:6;605:17;601:27;591:55;;642:1;639;632:12;591:55;-1:-1:-1;665:20:83;;708:18;697:30;;694:50;;;740:1;737;730:12;694:50;777:4;769:6;765:17;753:29;;837:3;830:4;820:6;817:1;813:14;805:6;801:27;797:38;794:47;791:67;;;854:1;851;844:12;791:67;497:367;;;;;:::o;869:437::-;955:6;963;1016:2;1004:9;995:7;991:23;987:32;984:52;;;1032:1;1029;1022:12;984:52;1072:9;1059:23;1105:18;1097:6;1094:30;1091:50;;;1137:1;1134;1127:12;1091:50;1176:70;1238:7;1229:6;1218:9;1214:22;1176:70;:::i;:::-;1265:8;;1150:96;;-1:-1:-1;869:437:83;-1:-1:-1;;;;869:437:83:o;1311:131::-;-1:-1:-1;;;;;1386:31:83;;1376:42;;1366:70;;1432:1;1429;1422:12;1447:118;1533:5;1526:13;1519:21;1512:5;1509:32;1499:60;;1555:1;1552;1545:12;1570:382;1635:6;1643;1696:2;1684:9;1675:7;1671:23;1667:32;1664:52;;;1712:1;1709;1702:12;1664:52;1751:9;1738:23;1770:31;1795:5;1770:31;:::i;:::-;1820:5;-1:-1:-1;1877:2:83;1862:18;;1849:32;1890:30;1849:32;1890:30;:::i;:::-;1939:7;1929:17;;;1570:382;;;;;:::o;1957:226::-;2016:6;2069:2;2057:9;2048:7;2044:23;2040:32;2037:52;;;2085:1;2082;2075:12;2037:52;-1:-1:-1;2130:23:83;;1957:226;-1:-1:-1;1957:226:83:o;2188:650::-;2274:6;2282;2290;2298;2351:3;2339:9;2330:7;2326:23;2322:33;2319:53;;;2368:1;2365;2358:12;2319:53;2407:9;2394:23;2426:31;2451:5;2426:31;:::i;:::-;2476:5;-1:-1:-1;2533:2:83;2518:18;;2505:32;2546:33;2505:32;2546:33;:::i;:::-;2598:7;-1:-1:-1;2657:2:83;2642:18;;2629:32;2670:33;2629:32;2670:33;:::i;:::-;2188:650;;;;-1:-1:-1;2722:7:83;;2802:2;2787:18;2774:32;;-1:-1:-1;;2188:650:83:o;2843:247::-;2902:6;2955:2;2943:9;2934:7;2930:23;2926:32;2923:52;;;2971:1;2968;2961:12;2923:52;3010:9;2997:23;3029:31;3054:5;3029:31;:::i;3095:637::-;3285:2;3297:21;;;3367:13;;3270:18;;;3389:22;;;3237:4;;3468:15;;;3442:2;3427:18;;;3237:4;3511:195;3525:6;3522:1;3519:13;3511:195;;;3590:13;;-1:-1:-1;;;;;3586:39:83;3574:52;;3655:2;3681:15;;;;3646:12;;;;3622:1;3540:9;3511:195;;;-1:-1:-1;3723:3:83;;3095:637;-1:-1:-1;;;;;3095:637:83:o;4004:418::-;4153:2;4142:9;4135:21;4116:4;4185:6;4179:13;4228:6;4223:2;4212:9;4208:18;4201:34;4287:6;4282:2;4274:6;4270:15;4265:2;4254:9;4250:18;4244:50;4343:1;4338:2;4329:6;4318:9;4314:22;4310:31;4303:42;4413:2;4406;4402:7;4397:2;4389:6;4385:15;4381:29;4370:9;4366:45;4362:54;4354:62;;;4004:418;;;;:::o;4427:367::-;4495:6;4503;4556:2;4544:9;4535:7;4531:23;4527:32;4524:52;;;4572:1;4569;4562:12;4524:52;4611:9;4598:23;4630:31;4655:5;4630:31;:::i;:::-;4680:5;4758:2;4743:18;;;;4730:32;;-1:-1:-1;;;4427:367:83:o;5189:114::-;5273:4;5266:5;5262:16;5255:5;5252:27;5242:55;;5293:1;5290;5283:12;5308:243;5365:6;5418:2;5406:9;5397:7;5393:23;5389:32;5386:52;;;5434:1;5431;5424:12;5386:52;5473:9;5460:23;5492:29;5515:5;5492:29;:::i;5556:508::-;5633:6;5641;5649;5702:2;5690:9;5681:7;5677:23;5673:32;5670:52;;;5718:1;5715;5708:12;5670:52;5757:9;5744:23;5776:31;5801:5;5776:31;:::i;:::-;5826:5;-1:-1:-1;5883:2:83;5868:18;;5855:32;5896:33;5855:32;5896:33;:::i;:::-;5556:508;;5948:7;;-1:-1:-1;;;6028:2:83;6013:18;;;;6000:32;;5556:508::o;6526:566::-;6618:6;6626;6634;6687:2;6675:9;6666:7;6662:23;6658:32;6655:52;;;6703:1;6700;6693:12;6655:52;6743:9;6730:23;6776:18;6768:6;6765:30;6762:50;;;6808:1;6805;6798:12;6762:50;6847:70;6909:7;6900:6;6889:9;6885:22;6847:70;:::i;:::-;6936:8;;-1:-1:-1;6821:96:83;-1:-1:-1;;7021:2:83;7006:18;;6993:32;7034:28;6993:32;7034:28;:::i;:::-;7081:5;7071:15;;;6526:566;;;;;:::o;7286:127::-;7347:10;7342:3;7338:20;7335:1;7328:31;7378:4;7375:1;7368:15;7402:4;7399:1;7392:15;7550:771;7772:2;7784:21;;;7757:18;;7840:22;;;7724:4;7919:6;7893:2;7878:18;;7724:4;7953:281;7967:6;7964:1;7961:13;7953:281;;;8042:6;8029:20;8062:31;8087:5;8062:31;:::i;:::-;-1:-1:-1;;;;;8118:31:83;8106:44;;8179:4;8207:17;;;;8170:14;;;;8146:1;7982:9;7953:281;;;7957:3;8251;8243:11;;;;8306:6;8299:14;8292:22;8285:4;8274:9;8270:20;8263:52;7550:771;;;;;;:::o;9176:245::-;9243:6;9296:2;9284:9;9275:7;9271:23;9267:32;9264:52;;;9312:1;9309;9302:12;9264:52;9344:9;9338:16;9363:28;9385:5;9363:28;:::i;9426:127::-;9487:10;9482:3;9478:20;9475:1;9468:31;9518:4;9515:1;9508:15;9542:4;9539:1;9532:15;9558:935;9638:6;9691:2;9679:9;9670:7;9666:23;9662:32;9659:52;;;9707:1;9704;9697:12;9659:52;9740:9;9734:16;9773:18;9765:6;9762:30;9759:50;;;9805:1;9802;9795:12;9759:50;9828:22;;9881:4;9873:13;;9869:27;-1:-1:-1;9859:55:83;;9910:1;9907;9900:12;9859:55;9943:2;9937:9;9969:18;9961:6;9958:30;9955:56;;;9991:18;;:::i;:::-;10040:2;10034:9;10132:2;10094:17;;-1:-1:-1;;10090:31:83;;;10123:2;10086:40;10082:54;10070:67;;10167:18;10152:34;;10188:22;;;10149:62;10146:88;;;10214:18;;:::i;:::-;10250:2;10243:22;10274;;;10315:15;;;10332:2;10311:24;10308:37;-1:-1:-1;10305:57:83;;;10358:1;10355;10348:12;10305:57;10407:6;10402:2;10398;10394:11;10389:2;10381:6;10377:15;10371:43;10460:1;10434:19;;;10455:2;10430:28;10423:39;;;;10438:6;9558:935;-1:-1:-1;;;;9558:935:83:o;10498:247::-;10566:6;10619:2;10607:9;10598:7;10594:23;10590:32;10587:52;;;10635:1;10632;10625:12;10587:52;10667:9;10661:16;10686:29;10709:5;10686:29;:::i;10750:225::-;10817:9;;;10838:11;;;10835:134;;;10891:10;10886:3;10882:20;10879:1;10872:31;10926:4;10923:1;10916:15;10954:4;10951:1;10944:15;10980:127;11041:10;11036:3;11032:20;11029:1;11022:31;11072:4;11069:1;11062:15;11096:4;11093:1;11086:15","linkReferences":{}},"methodIdentifiers":{"DEFAULT_MAX_RULES()":"f76bf550","addRule(address)":"e3c4602c","bindToken(address)":"3ff5aa02","bindTokens(address[])":"c7c24b18","canTransfer(address,address,uint256)":"e46638e6","canTransferFrom(address,address,address,uint256)":"7157797f","clearRules()":"b043572e","containsRule(address)":"54e4b945","created(address,uint256)":"5f8dead3","destroyed(address,uint256)":"8d2ea772","detectTransferRestriction(address,address,uint256)":"d4ce1415","detectTransferRestrictionFrom(address,address,address,uint256)":"d32c7bb5","getTokenBound()":"6a3edf28","getTokenBounds()":"e54621d2","isTokenBound(address)":"993e8b95","isTokenSelfBindingApproved(address)":"db75d017","maxRules()":"6ae728c6","messageForTransferRestriction(uint8)":"7f4ab1dd","owner()":"8da5cb5b","removeRule(address)":"df21950f","renounceOwnership()":"715018a6","rule(uint256)":"db18af6c","rules()":"52f6747a","rulesCount()":"bc13eacc","setMaxRules(uint256)":"3a56d6d5","setRules(address[])":"b27aef3a","setTokenSelfBindingApproval(address,bool)":"3284a9a5","setTokenSelfBindingApprovalBatch(address[],bool)":"bb4b6121","supportsInterface(bytes4)":"01ffc9a7","transferOwnership(address)":"f2fde38b","transferred(address,address,address,uint256)":"3e5af4ca","transferred(address,address,uint256)":"8baf29b4","unbindToken(address)":"40db3b50","unbindTokens(address[])":"1455d0e7","version()":"54fd4d50"},"rawMetadata":"{\"compiler\":{\"version\":\"0.8.37+commit.f401782d\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenContract\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"OwnableInvalidOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"OwnableUnauthorizedAccount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_AdminWithAddressZeroNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_RuleInvalidInterface\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_RulesManagementModule_ArrayIsEmpty\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"maxRules\",\"type\":\"uint256\"}],\"name\":\"RuleEngine_RulesManagementModule_MaxRulesExceeded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_RulesManagementModule_MaxRulesZeroNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_RulesManagementModule_RuleAccountCannotReceivePrivileges\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_RulesManagementModule_RuleAddressZeroNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_RulesManagementModule_RuleAlreadyExists\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_RulesManagementModule_RuleDoNotMatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TokenBinding_InvalidTokenAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TokenBinding_TokenAlreadyBound\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TokenBinding_TokenNotBound\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TokenBinding_UnauthorizedCaller\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract IRule\",\"name\":\"rule\",\"type\":\"address\"}],\"name\":\"AddRule\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"ClearRules\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract IRule\",\"name\":\"rule\",\"type\":\"address\"}],\"name\":\"RemoveRule\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"maxRules\",\"type\":\"uint256\"}],\"name\":\"SetMaxRules\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"TokenBound\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"tokens\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"TokenSelfBindingApprovalBatchSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"TokenSelfBindingApprovalSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"TokenUnbound\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DEFAULT_MAX_RULES\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IRule\",\"name\":\"rule_\",\"type\":\"address\"}],\"name\":\"addRule\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"bindToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"tokens\",\"type\":\"address[]\"}],\"name\":\"bindTokens\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"canTransfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"canTransferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"clearRules\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IRule\",\"name\":\"rule_\",\"type\":\"address\"}],\"name\":\"containsRule\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"created\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"destroyed\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"detectTransferRestriction\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"detectTransferRestrictionFrom\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTokenBound\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTokenBounds\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"isTokenBound\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"isTokenSelfBindingApproved\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"maxRules\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"restrictionCode\",\"type\":\"uint8\"}],\"name\":\"messageForTransferRestriction\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IRule\",\"name\":\"rule_\",\"type\":\"address\"}],\"name\":\"removeRule\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"ruleId\",\"type\":\"uint256\"}],\"name\":\"rule\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"rules\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"rulesCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"maxRules_\",\"type\":\"uint256\"}],\"name\":\"setMaxRules\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IRule[]\",\"name\":\"rules_\",\"type\":\"address[]\"}],\"name\":\"setRules\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"setTokenSelfBindingApproval\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"tokens\",\"type\":\"address[]\"},{\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"setTokenSelfBindingApprovalBatch\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"transferred\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"transferred\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"unbindToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"tokens\",\"type\":\"address[]\"}],\"name\":\"unbindTokens\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"version_\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"No ERC-2771 support: every caller is the raw `msg.sender`. Deploy {RuleEngineOwnable2771} to administer the engine through a trusted forwarder (gasless transactions).\",\"errors\":{\"OwnableInvalidOwner(address)\":[{\"details\":\"The owner is not a valid owner account. (eg. `address(0)`)\"}],\"OwnableUnauthorizedAccount(address)\":[{\"details\":\"The caller account is not authorized to perform an operation.\"}]},\"events\":{\"AddRule(address)\":{\"params\":{\"rule\":\"The address of the rule contract that was added.\"}},\"RemoveRule(address)\":{\"params\":{\"rule\":\"The address of the rule contract that was removed.\"}},\"SetMaxRules(uint256)\":{\"params\":{\"maxRules\":\"The new rule cap.\"}},\"TokenBound(address)\":{\"details\":\"Same declaration as ERC-3643 `TokenBound(address _token)`, which does not index the token. Keep it non-indexed: `indexed` would move `token` from the data to a topic and break consumers decoding with the standard ERC-3643 ABI.\",\"params\":{\"token\":\"The address of the token that was bound.\"}},\"TokenSelfBindingApprovalBatchSet(address[],bool)\":{\"details\":\"`tokens` is the array as passed: it may contain tokens already at `approved` and duplicates, and is empty for an empty batch, so it lists the tokens that were set, not only those that changed. No {TokenSelfBindingApprovalSet} is emitted per token, so a filter on that event's indexed `token` does not see batch updates. `tokens` is not indexed: an indexed array is stored as a hash and cannot be filtered per token.\",\"params\":{\"approved\":\"True if token self-bind/unbind is allowed, false otherwise.\",\"tokens\":\"The token addresses whose self-binding permission was set, as passed to the call.\"}},\"TokenSelfBindingApprovalSet(address,bool)\":{\"details\":\"Emitted on every call, also when `approved` equals the current value. Not emitted by {setTokenSelfBindingApprovalBatch}, which emits {TokenSelfBindingApprovalBatchSet} instead: a consumer reconstructing the approvals, or filtering on `token`, must handle both events, or read {isTokenSelfBindingApproved}, which is authoritative.\",\"params\":{\"approved\":\"True if token self-bind/unbind is allowed, false otherwise.\",\"token\":\"The token address whose self-binding permission was set.\"}},\"TokenUnbound(address)\":{\"details\":\"Same declaration as ERC-3643 `TokenUnbound(address _token)`; kept non-indexed for the same reason as {TokenBound}.\",\"params\":{\"token\":\"The address of the token that was unbound.\"}}},\"kind\":\"dev\",\"methods\":{\"addRule(address)\":{\"details\":\"Reverts when the configured maximum number of rules is already reached. Security convention: do not grant {RULES_MANAGEMENT_ROLE} to rule contracts.\",\"params\":{\"rule_\":\"The IRule contract to add.\"}},\"bindToken(address)\":{\"custom:security-note\":\"\\\"Multi-tenant\\\" means one instance is shared by multiple token contracts. Downstream state (for the RuleEngine: the per-address accounting held by stateful rules) is shared across all bound tokens, so binding tokens from different issuers silently cross-contaminates it. Only bind tokens that are equally trusted and governed together.\",\"details\":\"Authorized by {_authorizeTokenBindingChange}.\",\"params\":{\"token\":\"The address of the token to bind.\"}},\"bindTokens(address[])\":{\"custom:security-note\":\"See {bindToken} for multi-tenant state risks. All tokens bound in this batch share the same downstream state. Only bind tokens that are equally trusted and governed together.\",\"details\":\"Must be restricted by implementation-specific access control. Atomic: reverts if any token is invalid or already bound (or listed twice), and then binds none of them. This deliberately departs from the usual batch convention of skipping elements already in the target state: a binding change is security-relevant, and a token that is already bound in the list is most likely an operator mistake that should stop the whole operation. An empty array is a no-op.\",\"params\":{\"tokens\":\"The token addresses to bind.\"}},\"canTransfer(address,address,uint256)\":{\"details\":\"Don't check the balance and the user's right (access control)\",\"params\":{\"from\":\"The address sending tokens.\",\"to\":\"The address receiving tokens.\",\"value\":\"The amount of tokens to transfer.\"},\"returns\":{\"_0\":\"True if the transfer is valid, false otherwise.\"}},\"canTransferFrom(address,address,address,uint256)\":{\"details\":\"Does not check balances or access rights (Access Control).\",\"params\":{\"from\":\"The source address.\",\"spender\":\"The address performing the transfer.\",\"to\":\"The destination address.\",\"value\":\"The number of tokens to transfer.\"},\"returns\":{\"_0\":\"isCompliant True if the transfer complies with policy.\"}},\"clearRules()\":{\"details\":\"After calling this function, no rules will remain set. Cost is O(n) in the number of configured rules. With the default cap of 10 this is negligible, but a high {maxRules} setting re-exposes unbounded cost here even though per-transfer cost remains bounded.\"},\"constructor\":{\"params\":{\"owner_\":\"Address of the contract owner (ERC-173)\",\"tokenContract\":\"Address of the token contract to bind (can be zero address)\"}},\"containsRule(address)\":{\"details\":\"Complexity: O(1).\",\"params\":{\"rule_\":\"The IRule contract to check for membership.\"},\"returns\":{\"_0\":\"True if the rule is present, false otherwise.\"}},\"created(address,uint256)\":{\"details\":\"Called by the token contract when new tokens are issued to an account. Reverts if the minting does not comply with the rules.\",\"params\":{\"to\":\"The address receiving the minted tokens.\",\"value\":\"The number of tokens created.\"}},\"destroyed(address,uint256)\":{\"details\":\"Called by the token contract when tokens are redeemed or burned. Reverts if the burning does not comply with the rules.\",\"params\":{\"from\":\"The address whose tokens are being destroyed.\",\"value\":\"The number of tokens destroyed.\"}},\"detectTransferRestriction(address,address,uint256)\":{\"params\":{\"from\":\"the origin address\",\"to\":\"the destination address\",\"value\":\"to transfer\"},\"returns\":{\"_0\":\"The restriction code or REJECTED_CODE_BASE.TRANSFER_OK (0) if the transfer is valid\"}},\"detectTransferRestrictionFrom(address,address,address,uint256)\":{\"details\":\" See {ERC-1404} Add an additionnal argument `spender` This function is where an issuer enforces the restriction logic of their token transfers. Some examples of this might include: - checking if the token recipient is whitelisted, - checking if a sender's tokens are frozen in a lock-up period, etc.\",\"params\":{\"from\":\"The address sending tokens.\",\"spender\":\"The address initiating the delegated transfer.\",\"to\":\"The address receiving tokens.\",\"value\":\"amount of tokens to transfer\"},\"returns\":{\"_0\":\"uint8 restricted code, 0 means the transfer is authorized\"}},\"getTokenBound()\":{\"details\":\"If multiple tokens are supported, consider using getTokenBounds().\",\"returns\":{\"_0\":\"The address of the currently bound token.\"}},\"getTokenBounds()\":{\"details\":\"This operation copies the entire storage set to memory and is mainly intended for off-chain reads.\",\"returns\":{\"_0\":\"An array of bound token addresses.\"}},\"isTokenBound(address)\":{\"details\":\"Complexity: O(1).\",\"params\":{\"token\":\"The token address to verify.\"},\"returns\":{\"_0\":\"True if the token is bound, false otherwise.\"}},\"isTokenSelfBindingApproved(address)\":{\"params\":{\"token\":\"The token address to query.\"},\"returns\":{\"_0\":\"True if self-binding is approved for `token`, false otherwise.\"}},\"maxRules()\":{\"returns\":{\"_0\":\"The maximum number of rules that can be configured.\"}},\"messageForTransferRestriction(uint8)\":{\"details\":\"See {ERC-1404} This function is effectively an accessor for the \\\"message\\\", a human-readable explanation as to why a transaction is restricted.\",\"params\":{\"restrictionCode\":\"The restriction code to translate into a message.\"},\"returns\":{\"_0\":\"The human-readable message corresponding to `restrictionCode`.\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"removeRule(address)\":{\"details\":\"Reverts if the provided rule is not found or does not match the stored rule at its index. Complexity: O(1).\",\"params\":{\"rule_\":\"The IRule contract to remove.\"}},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.\"},\"rule(uint256)\":{\"details\":\"Reverts if `ruleId` is out of bounds. Complexity: O(1). Note that there are no guarantees on the ordering of values inside the array, and it may change when more values are added or removed.\",\"params\":{\"ruleId\":\"The index of the desired rule in the array.\"},\"returns\":{\"_0\":\"The address of the corresponding IRule contract, return the `zero address` is out of bounds.\"}},\"rules()\":{\"details\":\"This is a view-only function that does not modify state. This operation will copy the entire storage to memory, which can be quite expensive. This is designed to mostly be used by view accessors that are queried without any gas fees.\",\"returns\":{\"_0\":\"An array of all active rule contract addresses.\"}},\"rulesCount()\":{\"details\":\"Equivalent to the length of the internal rules array. Complexity: O(1)\",\"returns\":{\"_0\":\"The number of active rules.\"}},\"setMaxRules(uint256)\":{\"details\":\"Access control is implementation specific (admin/owner). Setting a very high cap re-exposes unbounded gas cost for administrative operations such as {clearRules} even though normal per-transfer cost remains bounded.\",\"params\":{\"maxRules_\":\"New maximum number of rules.\"}},\"setRules(address[])\":{\"details\":\"Replaces the entire rule set atomically. Reverts if `rules_` is empty. Use {clearRules} to remove all rules explicitly. To transition from one non-empty set to another without an enforcement gap, call this function directly with the new set. Emits {ClearRules} when the existing rule set is non-empty, then emits {AddRule} for each new rule. Off-chain indexers must handle both events to reconstruct state. Security convention: rule contracts should be treated as trusted business logic, but should not also be granted {RULES_MANAGEMENT_ROLE}.\",\"params\":{\"rules_\":\"The array of addresses representing the new rules to be set.\"}},\"setTokenSelfBindingApproval(address,bool)\":{\"details\":\"Must be restricted by implementation-specific access control. An approval stays in force until it is revoked here or until the binding manager unbinds the token ({unbindToken} or {unbindTokens}), which revokes it and emits {TokenSelfBindingApprovalSet} with `false`. A token that unbinds itself keeps its approval, so it can bind itself again later.\",\"params\":{\"approved\":\"Whether self-binding is approved for `token`.\",\"token\":\"The token address to configure.\"}},\"setTokenSelfBindingApprovalBatch(address[],bool)\":{\"details\":\"Must be restricted by implementation-specific access control. Reverts if any token in `tokens` is the zero address. Emits a single {TokenSelfBindingApprovalBatchSet} with the input array, not one {TokenSelfBindingApprovalSet} per token.\",\"params\":{\"approved\":\"Whether self-binding is approved for all provided tokens.\",\"tokens\":\"The token addresses to configure.\"}},\"supportsInterface(bytes4)\":{\"params\":{\"interfaceId\":\"The interface identifier to check.\"},\"returns\":{\"_0\":\"True if the interface is supported, false otherwise.\"}},\"transferOwnership(address)\":{\"details\":\"Reverts when `newOwner` is already configured as a rule.\",\"params\":{\"newOwner\":\"The address of the new owner.\"}},\"transferred(address,address,address,uint256)\":{\"details\":\"Must revert if the transfer is invalid Same name as ERC-3643 but with one supplementary argument `spender` This function can be used to update state variables of the RuleEngine contract This function can be called ONLY by the token contract bound to the RuleEngine Which overload the token calls (since CMTAT v3.3.0): - this 4-argument overload for `transferFrom` (`spender` = approved spender) and for every operation initiated by an operator, with the operator as `spender`: mint (`from == address(0)`), burn (`to == address(0)`), including `burnFrom`, self-burn and cross-chain mint/burn, and the minter `batchTransfer`; - the 3-argument ERC-3643 overload `transferred(from, to, value)`, inherited from {IERC3643IComplianceContract}, only for a direct `transfer`. Up to CMTAT v3.2.0, mint, burn and the minter transfer used the 3-argument overload. WARNING - zero-value calls are permissionless. ERC-20 requires transfers of `0` to be treated as normal transfers, and OpenZeppelin's `_spendAllowance` consumes no allowance when `value == 0`. Any address can therefore call `transferFrom(victim, anyone, 0)` on the token and reach this callback for an arbitrary `from`, with itself as `spender`, without ever having been approved. The token deliberately does not suppress the notification, because doing so would make its compliance notifications inconsistent with its own ERC-20 transfer semantics. Implementations MUST therefore treat `value == 0` as carrying no economic meaning: any stateful rule (cooldown, holding period, quota, tax bucket, counter, holder tracking, ...) MUST be a no-op for a zero value, otherwise an attacker can desynchronize policy state from balances, or keep a holder permanently restricted, at no cost. The same applies to the 3-argument ERC-3643 overload, which a zero-value `transfer(to, 0)` reaches the same way.\",\"params\":{\"from\":\"token holder address\",\"spender\":\"spender address (sender)\",\"to\":\"receiver address\",\"value\":\"value of tokens involved in the transfer; MAY be `0` \\u2014 see the warning above\"}},\"transferred(address,address,uint256)\":{\"details\":\" This function can be used to update state variables of the compliance contract This function can be called ONLY by the token contract bound to the compliance\",\"params\":{\"from\":\"The address of the sender\",\"to\":\"The address of the receiver\",\"value\":\"value of tokens involved in the transfer\"}},\"unbindToken(address)\":{\"details\":\"Authorized by {_authorizeTokenBindingChange}. Operator warning: unbinding is an administrative operation and does not erase any state already stored downstream in a previously shared (\\\"multi-tenant\\\") setup.\",\"params\":{\"token\":\"The address of the token to unbind.\"}},\"unbindTokens(address[])\":{\"details\":\"Must be restricted by implementation-specific access control. Atomic: reverts if any token is not currently bound, and then unbinds none of them. Deliberately not the skip-if-already-done batch convention, for the same reason as {bindTokens}. An empty array is a no-op. Like a manager's {unbindToken}, revokes each token's self-binding approval (see {setTokenSelfBindingApproval}).\",\"params\":{\"tokens\":\"The token addresses to unbind.\"}},\"version()\":{\"details\":\"This value is useful to know which smart contract version has been used\",\"returns\":{\"version_\":\"A string representing the version of the token implementation (e.g., \\\"1.0.0\\\").\"}}},\"title\":\"Implementation of a ruleEngine with ERC-173 Ownable access control\",\"version\":1},\"userdoc\":{\"errors\":{\"TokenBinding_InvalidTokenAddress()\":[{\"notice\":\"Thrown when the zero address is passed as a token to bind or to approve.\"}],\"TokenBinding_TokenAlreadyBound()\":[{\"notice\":\"Thrown when binding a token that is already bound.\"}],\"TokenBinding_TokenNotBound()\":[{\"notice\":\"Thrown when unbinding a token that is not currently bound.\"}],\"TokenBinding_UnauthorizedCaller()\":[{\"notice\":\"Thrown when a caller that is not a bound token calls a bound-token entry point.\"}]},\"events\":{\"AddRule(address)\":{\"notice\":\"Emitted when a new rule is added to the rule set.\"},\"ClearRules()\":{\"notice\":\"Emitted when all rules are cleared from the rule set.\"},\"RemoveRule(address)\":{\"notice\":\"Emitted when a rule is removed from the rule set.\"},\"SetMaxRules(uint256)\":{\"notice\":\"Emitted when the maximum allowed number of rules is updated.\"},\"TokenBound(address)\":{\"notice\":\"Emitted when a token is successfully bound.\"},\"TokenSelfBindingApprovalBatchSet(address[],bool)\":{\"notice\":\"Emitted once by {setTokenSelfBindingApprovalBatch}, with the input array.\"},\"TokenSelfBindingApprovalSet(address,bool)\":{\"notice\":\"Emitted by {setTokenSelfBindingApproval} when self-binding permission is set for a token.\"},\"TokenUnbound(address)\":{\"notice\":\"Emitted when a token is successfully unbound.\"}},\"kind\":\"user\",\"methods\":{\"DEFAULT_MAX_RULES()\":{\"notice\":\"Default upper bound on the number of rules a RuleEngine may hold.\"},\"addRule(address)\":{\"notice\":\"Adds a new rule to the current rule set.\"},\"bindToken(address)\":{\"notice\":\"Binds a token contract, allowing it to call the bound-token entry points.\"},\"bindTokens(address[])\":{\"notice\":\"Binds several token contracts in a single call.\"},\"canTransfer(address,address,uint256)\":{\"notice\":\"Returns true if the transfer is valid, and false otherwise.\"},\"canTransferFrom(address,address,address,uint256)\":{\"notice\":\"Checks if `spender` can transfer `value` tokens from `from` to `to` under compliance rules.\"},\"clearRules()\":{\"notice\":\"Removes all configured rules.\"},\"constructor\":{\"notice\":\"Deploys a RuleEngine with ERC-173 ownership, without a trusted forwarder.\"},\"containsRule(address)\":{\"notice\":\"Checks whether a specific rule is currently configured.\"},\"created(address,uint256)\":{\"notice\":\"Updates the compliance contract state when tokens are created (minted).\"},\"destroyed(address,uint256)\":{\"notice\":\"Updates the compliance contract state when tokens are destroyed (burned).\"},\"detectTransferRestriction(address,address,uint256)\":{\"notice\":\"Queries every rule, in order, and returns the first restriction code that is not zero\"},\"detectTransferRestrictionFrom(address,address,address,uint256)\":{\"notice\":\"Returns a uint8 code to indicate if a transfer is restricted or not\"},\"getTokenBound()\":{\"notice\":\"Returns the single token currently bound to this compliance contract.\"},\"getTokenBounds()\":{\"notice\":\"Returns all tokens currently bound.\"},\"isTokenBound(address)\":{\"notice\":\"Checks whether a token is currently bound.\"},\"isTokenSelfBindingApproved(address)\":{\"notice\":\"Returns whether a token is approved to bind and unbind itself.\"},\"maxRules()\":{\"notice\":\"Returns the maximum number of rules allowed in the engine.\"},\"removeRule(address)\":{\"notice\":\"Removes a specific rule from the current rule set.\"},\"rule(uint256)\":{\"notice\":\"Retrieves the rule address at a specific index.\"},\"rules()\":{\"notice\":\"Returns the full list of currently configured rules.\"},\"rulesCount()\":{\"notice\":\"Returns the total number of currently configured rules.\"},\"setMaxRules(uint256)\":{\"notice\":\"Updates the maximum number of rules allowed in the engine.\"},\"setRules(address[])\":{\"notice\":\"Defines the rules for the rule engine.\"},\"setTokenSelfBindingApproval(address,bool)\":{\"notice\":\"Sets whether a token is allowed to bind and unbind itself.\"},\"setTokenSelfBindingApprovalBatch(address[],bool)\":{\"notice\":\"Sets self-binding approval for multiple tokens in one transaction.\"},\"supportsInterface(bytes4)\":{\"notice\":\"ERC-165 interface detection.\"},\"transferOwnership(address)\":{\"notice\":\"Transfers ownership of the contract to a new account (`newOwner`).\"},\"transferred(address,address,address,uint256)\":{\"notice\":\"Function called whenever tokens are transferred from one wallet to another, minted or burned, when the token knows the account that initiated the operation (`spender`).\"},\"transferred(address,address,uint256)\":{\"notice\":\"Function called whenever tokens are transferred from one wallet to another\"},\"unbindToken(address)\":{\"notice\":\"Unbinds a token contract, revoking its access to the bound-token entry points.\"},\"unbindTokens(address[])\":{\"notice\":\"Unbinds several token contracts in a single call.\"},\"version()\":{\"notice\":\"Returns the current version of the token contract.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/deployment/ownable/RuleEngineOwnable.sol\":\"RuleEngineOwnable\"},\"evmVersion\":\"osaka\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[\":@chainlink/contracts-ccip/=lib/Rules/lib/chainlink-ace/node_modules/@chainlink/contracts-ccip/chains/evm/contracts/\",\":@chainlink/contracts/=lib/Rules/lib/chainlink-ace/node_modules/@chainlink/contracts/\",\":@chainlink/contracts@1.4.0/=lib/Rules/lib/chainlink-doc/node_modules/@chainlink/contracts-1.4.0/\",\":@chainlink/cross-chain-identity/=lib/Rules/lib/chainlink-ace/packages/cross-chain-identity/src/\",\":@chainlink/local/=lib/Rules/lib/chainlink-doc/node_modules/@chainlink/local/\",\":@chainlink/policy-management/=lib/Rules/lib/chainlink-ace/packages/policy-management/src/\",\":@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\":@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\":@openzeppelin/contracts@4.7.3/=lib/Rules/lib/chainlink-doc/node_modules/@openzeppelin/contracts-4.7.3/\",\":@openzeppelin/contracts@4.8.3/=lib/Rules/lib/chainlink-ace/node_modules/@openzeppelin/contracts-4.8.3/\",\":@openzeppelin/contracts@4.9.6/=lib/Rules/lib/chainlink-doc/node_modules/@openzeppelin/contracts-4.9.6/\",\":@openzeppelin/contracts@5.0.2/=lib/Rules/lib/chainlink-ace/node_modules/@openzeppelin/contracts/\",\":@openzeppelin/contracts@5.1.0/=lib/Rules/lib/chainlink-doc/node_modules/@openzeppelin/contracts-5.1.0/\",\":@openzeppelin/contracts@5.3.0/=lib/Rules/lib/chainlink-ace/node_modules/@openzeppelin/contracts-5.3.0/\",\":CMTAT/=lib/CMTAT/contracts/\",\":CMTATv3.0.0/=lib/CMTATv3.0.0/contracts/\",\":ERC-3643/=lib/ERC-3643/contracts/\",\":ERC3643/=lib/Rules/lib/ERC-3643/contracts/\",\":RuleEngine/=lib/Rules/lib/RuleEngine/\",\":Rules/=lib/Rules/\",\":chainlink-ace/=lib/Rules/lib/chainlink-ace/\",\":chainlink-doc/=lib/Rules/lib/\",\":erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/\",\":forge-std/=lib/forge-std/src/\",\":halmos-cheatcodes/=lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/\",\":openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\":openzeppelin-contracts/=lib/openzeppelin-contracts/\"]},\"sources\":{\"lib/CMTAT/contracts/interfaces/engine/IRuleEngine.sol\":{\"keccak256\":\"0xeda899e2e46a9b9c3516acb61a7f7e92ed098928379010655c330da721aaffa7\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://60f8555330fc531dff7d0d71a862696fb286a0ba3290e41efbbbf4dd25947a3c\",\"dweb:/ipfs/QmWvbsBGWPtNMNN2EEedwdzzvQG7NtSj9VD2fmNgqVtCXN\"]},\"lib/CMTAT/contracts/interfaces/technical/IERC5679.sol\":{\"keccak256\":\"0x5bee30750c9a65438469a6c5bd8465e1603eec3aeeb94c07bd64ba3e9ee766e1\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://ef7a5c5f0d47135c97ab5d7456d31e513a71c849ae7f2f5395f860be125c4fbc\",\"dweb:/ipfs/Qmezem3qqSjij6ggyB34wC2S15KrY9fu42oymyS9epAYCQ\"]},\"lib/CMTAT/contracts/interfaces/tokenization/IERC3643Partial.sol\":{\"keccak256\":\"0x5c84c2e2442824e98625c471482fb3c9502f43f4c345e7c0fb07fa549be02e26\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://19071f2d12fb580d37eeee07885461f193568df34f3f69d2c5d65ce655d84435\",\"dweb:/ipfs/QmRqHwC7LksE3YPohMtxFieiPerhWdoDNUUMMLbB4XYvhK\"]},\"lib/CMTAT/contracts/interfaces/tokenization/draft-IERC1404.sol\":{\"keccak256\":\"0xc27cdac182d930a94391d589bdafa15364b6f8d9bf211175781dba661f1c0336\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://b509fa7f3cfd785632569f6ae3bec846aa0beefd73c1d5bde233440cae919f0f\",\"dweb:/ipfs/QmPCAdiEun8gaMqS8KhwPpRZV2zXAPfURRaF4C2KjX5Kby\"]},\"lib/CMTAT/contracts/interfaces/tokenization/draft-IERC7551.sol\":{\"keccak256\":\"0x84b73eb77ec82d6d7b313eff2d87f58d3b795840d004aaa10c611b360b827e30\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://a5b8c99fb3600369065a422d3821ba441dc06fc64f50ce0f33950a76ad82b51b\",\"dweb:/ipfs/QmbviJsZPY3xuLU3cHUWJx11aJCPAuN4WKnCufN4kVLm2U\"]},\"lib/CMTAT/contracts/interfaces/tokenization/draft-IERC7943.sol\":{\"keccak256\":\"0xc69588a72da81057ee278e961e8e3bb61a28d64c3c6cebe494ce00809c1cef15\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://148f117d9c463de441f81e6c0a67e95f1f14a61db209492dd0a1767b5572f21a\",\"dweb:/ipfs/QmUjT5uyJfNSYgUWn5Dxhf6Sx9Y1z8CNf3PuTEaGoAx3za\"]},\"lib/CMTAT/contracts/library/ERC1404ExtendInterfaceId.sol\":{\"keccak256\":\"0xf8268f4eb3a6b2e26c32cf76c5c76b6c17df3385c150f05953538a2472149247\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://05108de7a7ba2a0a67978bdfe8e500360674db6d894f42970bb1016b36639056\",\"dweb:/ipfs/QmRux9Qj1GomATseS6Tyq9uiPPNNipuxg2HjdjnPjgSQds\"]},\"lib/CMTAT/contracts/library/RuleEngineInterfaceId.sol\":{\"keccak256\":\"0x1152a49cba4232d943e295d259eb8a1b216d815067367410a5729a256dae4051\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://470f4435a5e62b0ba0ad70f8657b2db0e4cc3b7f2561772adb944ce010551ee6\",\"dweb:/ipfs/QmXECahRr8rK9XJPZwBCnemLDVPdFvPEBusezhaBqbLBqp\"]},\"lib/openzeppelin-contracts/contracts/access/Ownable.sol\":{\"keccak256\":\"0xff6d0bb2e285473e5311d9d3caacb525ae3538a80758c10649a4d61029b017bb\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://8ed324d3920bb545059d66ab97d43e43ee85fd3bd52e03e401f020afb0b120f6\",\"dweb:/ipfs/QmfEckWLmZkDDcoWrkEvMWhms66xwTLff9DDhegYpvHo1a\"]},\"lib/openzeppelin-contracts/contracts/interfaces/IERC165.sol\":{\"keccak256\":\"0x0afcb7e740d1537b252cb2676f600465ce6938398569f09ba1b9ca240dde2dfc\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://1c299900ac4ec268d4570ecef0d697a3013cd11a6eb74e295ee3fbc945056037\",\"dweb:/ipfs/Qmab9owJoxcA7vJT5XNayCMaUR1qxqj1NDzzisduwaJMcZ\"]},\"lib/openzeppelin-contracts/contracts/utils/Arrays.sol\":{\"keccak256\":\"0x772f0c778626a7bdcbcbabca74b825ae9b9dc89d2a47a98b402b1187fbaa63a4\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://eba1d46e58e8880b45c6d51245dc94585b81d6d7290ca77ef50037a6193ed301\",\"dweb:/ipfs/Qme3CWun5qQACjGEerT2MCvhs6brKGFfJirGnzV1ypKTXA\"]},\"lib/openzeppelin-contracts/contracts/utils/Comparators.sol\":{\"keccak256\":\"0x302eecd8cf323b4690e3494a7d960b3cbce077032ab8ef655b323cdd136cec58\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://49ba706f1bc476d68fe6c1fad75517acea4e9e275be0989b548e292eb3a3eacd\",\"dweb:/ipfs/QmeBpvcdGWzWMKTQESUCEhHgnEQYYATVwPxLMxa6vMT7jC\"]},\"lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"keccak256\":\"0x493033a8d1b176a037b2cc6a04dad01a5c157722049bbecf632ca876224dd4b2\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6a708e8a5bdb1011c2c381c9a5cfd8a9a956d7d0a9dc1bd8bcdaf52f76ef2f12\",\"dweb:/ipfs/Qmax9WHBnVsZP46ZxEMNRQpLQnrdE4dK8LehML1Py8FowF\"]},\"lib/openzeppelin-contracts/contracts/utils/Panic.sol\":{\"keccak256\":\"0xf7fe324703a64fc51702311dc51562d5cb1497734f074e4f483bfb6717572d7a\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c6a5ff4f9fd8649b7ee20800b7fa387d3465bd77cf20c2d1068cd5c98e1ed57a\",\"dweb:/ipfs/QmVSaVJf9FXFhdYEYeCEfjMVHrxDh5qL4CGkxdMWpQCrqG\"]},\"lib/openzeppelin-contracts/contracts/utils/SlotDerivation.sol\":{\"keccak256\":\"0x94045fd4f268edf2b2d01ef119268548c320366d6f5294ad30c1b8f9d4f5225f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://edfda81f426f8948b3834115c21e83c48180e6db0d2a8cd2debb2185ed349337\",\"dweb:/ipfs/QmdYZneFyDAux1BuWQxLAdqtABrGS2k9WYCa7C9dvpKkWv\"]},\"lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol\":{\"keccak256\":\"0xcf74f855663ce2ae00ed8352666b7935f6cddea2932fdf2c3ecd30a9b1cd0e97\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://9f660b1f351b757dfe01438e59888f31f33ded3afcf5cb5b0d9bf9aa6f320a8b\",\"dweb:/ipfs/QmarDJ5hZEgBtCmmrVzEZWjub9769eD686jmzb2XpSU1cM\"]},\"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\":{\"keccak256\":\"0x2d9dc2fe26180f74c11c13663647d38e259e45f95eb88f57b61d2160b0109d3e\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://81233d1f98060113d9922180bb0f14f8335856fe9f339134b09335e9f678c377\",\"dweb:/ipfs/QmWh6R35SarhAn4z2wH8SU456jJSYL2FgucfTFgbHJJN4E\"]},\"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165Checker.sol\":{\"keccak256\":\"0x7c7ad70641a7f8cd44def0857ec97b0e40bfd073b2d6037a5f57ce9527ee9bc5\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://e05c6572dfe769f7aea6f3a8002951cc12d143d980dad29f6c5feedf9408bc14\",\"dweb:/ipfs/QmXM7C8YEptxisZiEefXUrwdXt3zMaCobmkCchxTtDg1oK\"]},\"lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"keccak256\":\"0x8891738ffe910f0cf2da09566928589bf5d63f4524dd734fd9cedbac3274dd5c\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://971f954442df5c2ef5b5ebf1eb245d7105d9fbacc7386ee5c796df1d45b21617\",\"dweb:/ipfs/QmadRjHbkicwqwwh61raUEapaVEtaLMcYbQZWs9gUkgj3u\"]},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"keccak256\":\"0x59973a93b1f983f94e10529f46ca46544a9fec2b5f56fb1390bbe9e0dc79f857\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c55ef8f0b9719790c2ae6f81d80a59ffb89f2f0abe6bc065585bd79edce058c5\",\"dweb:/ipfs/QmNNmCbX9NjPXKqHJN8R1WC2rNeZSQrPZLd6FF6AKLyH5Y\"]},\"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\":{\"keccak256\":\"0xc8cae21c9ae4a46e5162ff9bf5b351d6fa6a6eba72d515f3bc1bdfeda7fdf083\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://ce830ebcf28e31643caba318996db3763c36d52cd0f23798ba83c135355d45e9\",\"dweb:/ipfs/QmdGPcvptHN7UBCbUYBbRX3hiRVRFLRwno8b4uga6uFNif\"]},\"lib/openzeppelin-contracts/contracts/utils/structs/EnumerableSet.sol\":{\"keccak256\":\"0xd553ff8b7d55679f0711f1598600ac292dbd8cfdf4b2419b9cabe4c931172895\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://7905ccb27e2308fd0d90dc1212161003ab6964e1c176593db1ccedef705bcc09\",\"dweb:/ipfs/QmW37vm2PcrWLKnN74sKkvAzqSwntCEfCp4EoSEvbBHWkj\"]},\"src/RuleEngineBase.sol\":{\"keccak256\":\"0xb3d832fa55b615574d80b0e0ad76620ad236aa046523617ed5daa46ae07bf853\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://7be31bf5dbd3fa1be025cdc4b7674b76bf40e1c14ce89ec78f792cb3d7ed804e\",\"dweb:/ipfs/QmPq4xBiB3XwXerWtuonZLGiWHMqvz5tKvjhTh9AiWkbww\"]},\"src/RuleEngineOwnableShared.sol\":{\"keccak256\":\"0xa78493398d8b0554e72def7f14d7439109bd4dbd5e07f1466b40acea2bb7dc02\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://ebd87d69b4f6eb193c5d03476381ac132f9587248422d3306dda95b79fd4e470\",\"dweb:/ipfs/QmWYDLvPWjRcfxdR2KhXAij8U9TrFjeM77fsJRX25jWQmY\"]},\"src/deployment/ownable/RuleEngineOwnable.sol\":{\"keccak256\":\"0x9f34713fce49bbc841ed5f0d24c5b53455359a11d904f7ceb3c7ef210494c6c5\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://71875cc9f3a8f9f35b5ec06273cc1c83a23b2cb775ab2974610ca0dc4ac74945\",\"dweb:/ipfs/QmQUVtngskTrnPjv85BLJhEDxYVwp7WFhBHPBpRL4cvn27\"]},\"src/interfaces/IERC3643Compliance.sol\":{\"keccak256\":\"0xd0edd6697d67135853576ac6a40cadaffd787cedea98071708bbfb189c7ee5bc\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://4ed3cd3af64fccff17a1f33989cdfbdacbc0e4f32a56de11a072cf9e2277a1f6\",\"dweb:/ipfs/QmenRqRw1Yy39yDv1pJgBmnHtwuZhDdHE4omchL41CjXjb\"]},\"src/interfaces/IERC3643ComplianceExtended.sol\":{\"keccak256\":\"0x4a43bf330c7a904cba110acf52f519718d8409514c377912d5bd063c9d963729\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://c671879c591760ecbc2691e2f24adfb215a658c9fe6eb0c05dd1ca980054e585\",\"dweb:/ipfs/QmdbA19PFpJgHraF46YrcMNzUgswbTRA92atL2Lha63JLY\"]},\"src/interfaces/IRule.sol\":{\"keccak256\":\"0x81580b67f7be09049aa64d93cc1d8d691a87c639adc1cf169dc6073e1e543a5c\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://6f1808c3ed18ef1acbccdd9b30011b6e7220d388cfd66cba40b1ef0b485306a1\",\"dweb:/ipfs/QmcUCQ5MYcf7KTtoeqMKsTutPPSJhNTaK1ntHV21ioS9Fm\"]},\"src/interfaces/IRulesManagementModule.sol\":{\"keccak256\":\"0x082dd58070e83b02f275584afa872c4583ac4ca8ad12eb329fc11301470147f9\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://e2d0ad78dc323881864f406acd44976f5de39cdc97a6c99a724d8458b993e2e2\",\"dweb:/ipfs/QmRFfMbXbdiAYV3vQyNppXG7tHTji6mV1Y5Cu3ZzEQm5ng\"]},\"src/interfaces/ITokenBinding.sol\":{\"keccak256\":\"0x34dfea4e118c966adf867c0899844515566251819b4e4510fd8ee424555493fd\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://1d054ed49874816688a6e71f76d611bbdefd492d122ae386cb804c6f5af677a7\",\"dweb:/ipfs/QmRaYX4aJWYSNWNa1D4Nich3k7hkGM9rTfc9s2XaVqyRjy\"]},\"src/interfaces/ITokenBindingExtended.sol\":{\"keccak256\":\"0x01f3ab56dffce860d03e72d10e9f2d13b6bfc9004cf058c63a0b23e3b226da99\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://521e0c9651632b70d61c4c3bd0b14c6f05d818166fe65dbed8e3253158b7637e\",\"dweb:/ipfs/QmY2xEVvfV1dgtFYw6coHX3Z7Fm7yRhzPaGyt6cYBMVf76\"]},\"src/modules/ERC3643ComplianceExtendedModule.sol\":{\"keccak256\":\"0x6f808b068517e9e15f09fc6a9d4190001ec8c2314a10e27a85a2d43e44c84fb1\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://c62c0b77fdd8b6e7bf7aa5bf8134a78ff024d6489a23f746874a99df38a8a265\",\"dweb:/ipfs/QmV7PG3ZUUzwDs9tpooC3hmBu5e39buJnJ4TRditojJ3hu\"]},\"src/modules/ERC3643ComplianceModule.sol\":{\"keccak256\":\"0x7cda81af8687328ac2089f9d1d78352e0e75d0f70a4ba8e2b3ac82896f22863f\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://50711cb94d69ea63d787a8bb19c38c0b99539029ec8fb957a8eff00880fc11fc\",\"dweb:/ipfs/QmSapDWh5mpvWn1q6JteZisJfVGPrCz47WP2BBrJCccEjV\"]},\"src/modules/RulesManagementModule.sol\":{\"keccak256\":\"0xe4d9425613284e71a5e3d590d5433167a9751d9496f57efa914baa81f493e66d\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://d07a16e6869df86c526ef89e7e359e34a9553dc4288b262abd2979359ecf720e\",\"dweb:/ipfs/QmRy2JEsyhkv1mxv7eFaSbEWN4A3gtpPSUnnV48W2KiV4u\"]},\"src/modules/TokenBindingExtendedModule.sol\":{\"keccak256\":\"0x4e1ca7b2ec78608c3a7960bec7102a1780bdf3ec7ff544b612bafaf738b34d05\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://657bcdd303fd5a7fbe733b283f69d8e8aa73efeeeaf95c0ae7479769ac573693\",\"dweb:/ipfs/QmXiWPrv8pEqvBQck8jxC7NwB1MUdGQfLjihK6etYcZ54j\"]},\"src/modules/TokenBindingModule.sol\":{\"keccak256\":\"0xf65f46311d0078f60c30e3359dca988e39cba45b9eee53a09d618bfa70e6ef9b\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://e8c458ecfd41df5fb4a391e7ef837fd5ed5c999e61ccc0e6b4bd23023a739832\",\"dweb:/ipfs/Qmdsr765aw9fPFN2M9cSCP69o1o41FNCqhrXjHgEXNwbXV\"]},\"src/modules/VersionModule.sol\":{\"keccak256\":\"0x35daf007be8b9bb1cb9196ae2decb3e5ad4b574f6390f8fc010b78796ac42f73\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://b1b29d75e1c5023a0c6cb8c56638a17d855a3fdc051a60b9d2f304b99f7876d2\",\"dweb:/ipfs/QmXSCVjLuViC8916LwNpKtw8hqyH78Ptag3xH1n7F1fY4g\"]},\"src/modules/library/ComplianceInterfaceId.sol\":{\"keccak256\":\"0xd54bed5328e732f753d2886aeaa2761b2d66536d5247d4548e0ac1c83c7a0dac\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://ad695339fdfe72446a69d2dfbe39373affe2f37299ad921e57016069a7bc3592\",\"dweb:/ipfs/QmWathGt3E85hLfy5rrAYdb291W8VoTa4gpGPoxtWGvNNA\"]},\"src/modules/library/ERC1404InterfaceId.sol\":{\"keccak256\":\"0x07dc6905e137096cd0ae88be29b112d0e54a83ddf8ca527a281718010f6abcce\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://9249dce67cb59432bdbc9e49978c6cac0346cda3d3fca97c5a310e0f424e1600\",\"dweb:/ipfs/QmRi5awH3hjwvd3k3td48y5Cf64n1wvX9wCWy6fQLayuKs\"]},\"src/modules/library/OwnableInterfaceId.sol\":{\"keccak256\":\"0xdbe06b3203e21e41d1fd2a3ef373a80727193443dfd981de6821422158015d4f\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://ebe8699ae8af81c5cd82f25a1609d9396d72ae957647c33aaa745aadcdac8d18\",\"dweb:/ipfs/QmV73gwDJPFthn8VspdYE6GsoAcQMAR7TachUK8YrPonuT\"]},\"src/modules/library/RuleEngineInvariantStorage.sol\":{\"keccak256\":\"0x50a212f09f1695662965e5fba643b42a1978bec2a8368abbf43983489c983096\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://6137f01df7630527c985d85d2f7446359c678fcb933b66c55b51f583757b5c4a\",\"dweb:/ipfs/QmeHo47WQm1V99xZHS4soMk68UdtXtZhtWhV3dQC5BtA7u\"]},\"src/modules/library/RuleInterfaceId.sol\":{\"keccak256\":\"0x0d86820eee4c92b21d6704bea8ce7bd2cc1b35f6e4a1ceabbcf2a10f1c6b02ec\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://cfb560cb8588983b8c79a973d03c214a149bf1ac034fa9130ce93f0031a404d7\",\"dweb:/ipfs/Qmc6qt4E4BHdDyLUegCsgxqhf7ZFUiX4ahj8FjM54V7wpY\"]},\"src/modules/library/RulesManagementModuleInvariantStorage.sol\":{\"keccak256\":\"0xb81ea3a54c6e8d47b87d6c3d9fb5aae80c3430021b8cd66d9adeef7f5fc95893\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://cfcbadc2011f60de7189273c278dda1df2218aeeb153bee3b8a93447ec95df21\",\"dweb:/ipfs/Qmem5FqCLEfBJQdJzS7Xzd3zSfyL8Muf9Wv5WvCiBVsqfh\"]},\"src/modules/library/TokenBindingModuleInvariantStorage.sol\":{\"keccak256\":\"0x9bab8e5b265068da356fd46e343a7c6c73776f3964fdeaeff056e8ce104d40a5\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://e2e75d2d52b1e4f5cbb832d194266de9a1b3a8cc2101e875dce43a2664c31a05\",\"dweb:/ipfs/QmUsd5cTPsE89WKm3kTUWsobR9JsBDUY8NdxDU5RPYpvP6\"]}},\"version\":1}","metadata":{"compiler":{"version":"0.8.37+commit.f401782d"},"language":"Solidity","output":{"abi":[{"inputs":[{"internalType":"address","name":"owner_","type":"address"},{"internalType":"address","name":"tokenContract","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"type":"error","name":"OwnableInvalidOwner"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"type":"error","name":"OwnableUnauthorizedAccount"},{"inputs":[],"type":"error","name":"RuleEngine_AdminWithAddressZeroNotAllowed"},{"inputs":[],"type":"error","name":"RuleEngine_RuleInvalidInterface"},{"inputs":[],"type":"error","name":"RuleEngine_RulesManagementModule_ArrayIsEmpty"},{"inputs":[{"internalType":"uint256","name":"maxRules","type":"uint256"}],"type":"error","name":"RuleEngine_RulesManagementModule_MaxRulesExceeded"},{"inputs":[],"type":"error","name":"RuleEngine_RulesManagementModule_MaxRulesZeroNotAllowed"},{"inputs":[],"type":"error","name":"RuleEngine_RulesManagementModule_RuleAccountCannotReceivePrivileges"},{"inputs":[],"type":"error","name":"RuleEngine_RulesManagementModule_RuleAddressZeroNotAllowed"},{"inputs":[],"type":"error","name":"RuleEngine_RulesManagementModule_RuleAlreadyExists"},{"inputs":[],"type":"error","name":"RuleEngine_RulesManagementModule_RuleDoNotMatch"},{"inputs":[],"type":"error","name":"TokenBinding_InvalidTokenAddress"},{"inputs":[],"type":"error","name":"TokenBinding_TokenAlreadyBound"},{"inputs":[],"type":"error","name":"TokenBinding_TokenNotBound"},{"inputs":[],"type":"error","name":"TokenBinding_UnauthorizedCaller"},{"inputs":[{"internalType":"contract IRule","name":"rule","type":"address","indexed":true}],"type":"event","name":"AddRule","anonymous":false},{"inputs":[],"type":"event","name":"ClearRules","anonymous":false},{"inputs":[{"internalType":"address","name":"previousOwner","type":"address","indexed":true},{"internalType":"address","name":"newOwner","type":"address","indexed":true}],"type":"event","name":"OwnershipTransferred","anonymous":false},{"inputs":[{"internalType":"contract IRule","name":"rule","type":"address","indexed":true}],"type":"event","name":"RemoveRule","anonymous":false},{"inputs":[{"internalType":"uint256","name":"maxRules","type":"uint256","indexed":false}],"type":"event","name":"SetMaxRules","anonymous":false},{"inputs":[{"internalType":"address","name":"token","type":"address","indexed":false}],"type":"event","name":"TokenBound","anonymous":false},{"inputs":[{"internalType":"address[]","name":"tokens","type":"address[]","indexed":false},{"internalType":"bool","name":"approved","type":"bool","indexed":false}],"type":"event","name":"TokenSelfBindingApprovalBatchSet","anonymous":false},{"inputs":[{"internalType":"address","name":"token","type":"address","indexed":true},{"internalType":"bool","name":"approved","type":"bool","indexed":false}],"type":"event","name":"TokenSelfBindingApprovalSet","anonymous":false},{"inputs":[{"internalType":"address","name":"token","type":"address","indexed":false}],"type":"event","name":"TokenUnbound","anonymous":false},{"inputs":[],"stateMutability":"view","type":"function","name":"DEFAULT_MAX_RULES","outputs":[{"internalType":"uint256","name":"","type":"uint256"}]},{"inputs":[{"internalType":"contract IRule","name":"rule_","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"addRule"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"bindToken"},{"inputs":[{"internalType":"address[]","name":"tokens","type":"address[]"}],"stateMutability":"nonpayable","type":"function","name":"bindTokens"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"view","type":"function","name":"canTransfer","outputs":[{"internalType":"bool","name":"","type":"bool"}]},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"view","type":"function","name":"canTransferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}]},{"inputs":[],"stateMutability":"nonpayable","type":"function","name":"clearRules"},{"inputs":[{"internalType":"contract IRule","name":"rule_","type":"address"}],"stateMutability":"view","type":"function","name":"containsRule","outputs":[{"internalType":"bool","name":"","type":"bool"}]},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"nonpayable","type":"function","name":"created"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"nonpayable","type":"function","name":"destroyed"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"view","type":"function","name":"detectTransferRestriction","outputs":[{"internalType":"uint8","name":"","type":"uint8"}]},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"view","type":"function","name":"detectTransferRestrictionFrom","outputs":[{"internalType":"uint8","name":"","type":"uint8"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"getTokenBound","outputs":[{"internalType":"address","name":"","type":"address"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"getTokenBounds","outputs":[{"internalType":"address[]","name":"","type":"address[]"}]},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"stateMutability":"view","type":"function","name":"isTokenBound","outputs":[{"internalType":"bool","name":"","type":"bool"}]},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"stateMutability":"view","type":"function","name":"isTokenSelfBindingApproved","outputs":[{"internalType":"bool","name":"","type":"bool"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"maxRules","outputs":[{"internalType":"uint256","name":"","type":"uint256"}]},{"inputs":[{"internalType":"uint8","name":"restrictionCode","type":"uint8"}],"stateMutability":"view","type":"function","name":"messageForTransferRestriction","outputs":[{"internalType":"string","name":"","type":"string"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}]},{"inputs":[{"internalType":"contract IRule","name":"rule_","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"removeRule"},{"inputs":[],"stateMutability":"nonpayable","type":"function","name":"renounceOwnership"},{"inputs":[{"internalType":"uint256","name":"ruleId","type":"uint256"}],"stateMutability":"view","type":"function","name":"rule","outputs":[{"internalType":"address","name":"","type":"address"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"rules","outputs":[{"internalType":"address[]","name":"","type":"address[]"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"rulesCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}]},{"inputs":[{"internalType":"uint256","name":"maxRules_","type":"uint256"}],"stateMutability":"nonpayable","type":"function","name":"setMaxRules"},{"inputs":[{"internalType":"contract IRule[]","name":"rules_","type":"address[]"}],"stateMutability":"nonpayable","type":"function","name":"setRules"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"stateMutability":"nonpayable","type":"function","name":"setTokenSelfBindingApproval"},{"inputs":[{"internalType":"address[]","name":"tokens","type":"address[]"},{"internalType":"bool","name":"approved","type":"bool"}],"stateMutability":"nonpayable","type":"function","name":"setTokenSelfBindingApprovalBatch"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"stateMutability":"view","type":"function","name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}]},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"transferOwnership"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"nonpayable","type":"function","name":"transferred"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"nonpayable","type":"function","name":"transferred"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"unbindToken"},{"inputs":[{"internalType":"address[]","name":"tokens","type":"address[]"}],"stateMutability":"nonpayable","type":"function","name":"unbindTokens"},{"inputs":[],"stateMutability":"view","type":"function","name":"version","outputs":[{"internalType":"string","name":"version_","type":"string"}]}],"devdoc":{"kind":"dev","methods":{"addRule(address)":{"details":"Reverts when the configured maximum number of rules is already reached. Security convention: do not grant {RULES_MANAGEMENT_ROLE} to rule contracts.","params":{"rule_":"The IRule contract to add."}},"bindToken(address)":{"custom:security-note":"\"Multi-tenant\" means one instance is shared by multiple token contracts. Downstream state (for the RuleEngine: the per-address accounting held by stateful rules) is shared across all bound tokens, so binding tokens from different issuers silently cross-contaminates it. Only bind tokens that are equally trusted and governed together.","details":"Authorized by {_authorizeTokenBindingChange}.","params":{"token":"The address of the token to bind."}},"bindTokens(address[])":{"custom:security-note":"See {bindToken} for multi-tenant state risks. All tokens bound in this batch share the same downstream state. Only bind tokens that are equally trusted and governed together.","details":"Must be restricted by implementation-specific access control. Atomic: reverts if any token is invalid or already bound (or listed twice), and then binds none of them. This deliberately departs from the usual batch convention of skipping elements already in the target state: a binding change is security-relevant, and a token that is already bound in the list is most likely an operator mistake that should stop the whole operation. An empty array is a no-op.","params":{"tokens":"The token addresses to bind."}},"canTransfer(address,address,uint256)":{"details":"Don't check the balance and the user's right (access control)","params":{"from":"The address sending tokens.","to":"The address receiving tokens.","value":"The amount of tokens to transfer."},"returns":{"_0":"True if the transfer is valid, false otherwise."}},"canTransferFrom(address,address,address,uint256)":{"details":"Does not check balances or access rights (Access Control).","params":{"from":"The source address.","spender":"The address performing the transfer.","to":"The destination address.","value":"The number of tokens to transfer."},"returns":{"_0":"isCompliant True if the transfer complies with policy."}},"clearRules()":{"details":"After calling this function, no rules will remain set. Cost is O(n) in the number of configured rules. With the default cap of 10 this is negligible, but a high {maxRules} setting re-exposes unbounded cost here even though per-transfer cost remains bounded."},"constructor":{"params":{"owner_":"Address of the contract owner (ERC-173)","tokenContract":"Address of the token contract to bind (can be zero address)"}},"containsRule(address)":{"details":"Complexity: O(1).","params":{"rule_":"The IRule contract to check for membership."},"returns":{"_0":"True if the rule is present, false otherwise."}},"created(address,uint256)":{"details":"Called by the token contract when new tokens are issued to an account. Reverts if the minting does not comply with the rules.","params":{"to":"The address receiving the minted tokens.","value":"The number of tokens created."}},"destroyed(address,uint256)":{"details":"Called by the token contract when tokens are redeemed or burned. Reverts if the burning does not comply with the rules.","params":{"from":"The address whose tokens are being destroyed.","value":"The number of tokens destroyed."}},"detectTransferRestriction(address,address,uint256)":{"params":{"from":"the origin address","to":"the destination address","value":"to transfer"},"returns":{"_0":"The restriction code or REJECTED_CODE_BASE.TRANSFER_OK (0) if the transfer is valid"}},"detectTransferRestrictionFrom(address,address,address,uint256)":{"details":" See {ERC-1404} Add an additionnal argument `spender` This function is where an issuer enforces the restriction logic of their token transfers. Some examples of this might include: - checking if the token recipient is whitelisted, - checking if a sender's tokens are frozen in a lock-up period, etc.","params":{"from":"The address sending tokens.","spender":"The address initiating the delegated transfer.","to":"The address receiving tokens.","value":"amount of tokens to transfer"},"returns":{"_0":"uint8 restricted code, 0 means the transfer is authorized"}},"getTokenBound()":{"details":"If multiple tokens are supported, consider using getTokenBounds().","returns":{"_0":"The address of the currently bound token."}},"getTokenBounds()":{"details":"This operation copies the entire storage set to memory and is mainly intended for off-chain reads.","returns":{"_0":"An array of bound token addresses."}},"isTokenBound(address)":{"details":"Complexity: O(1).","params":{"token":"The token address to verify."},"returns":{"_0":"True if the token is bound, false otherwise."}},"isTokenSelfBindingApproved(address)":{"params":{"token":"The token address to query."},"returns":{"_0":"True if self-binding is approved for `token`, false otherwise."}},"maxRules()":{"returns":{"_0":"The maximum number of rules that can be configured."}},"messageForTransferRestriction(uint8)":{"details":"See {ERC-1404} This function is effectively an accessor for the \"message\", a human-readable explanation as to why a transaction is restricted.","params":{"restrictionCode":"The restriction code to translate into a message."},"returns":{"_0":"The human-readable message corresponding to `restrictionCode`."}},"owner()":{"details":"Returns the address of the current owner."},"removeRule(address)":{"details":"Reverts if the provided rule is not found or does not match the stored rule at its index. Complexity: O(1).","params":{"rule_":"The IRule contract to remove."}},"renounceOwnership()":{"details":"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner."},"rule(uint256)":{"details":"Reverts if `ruleId` is out of bounds. Complexity: O(1). Note that there are no guarantees on the ordering of values inside the array, and it may change when more values are added or removed.","params":{"ruleId":"The index of the desired rule in the array."},"returns":{"_0":"The address of the corresponding IRule contract, return the `zero address` is out of bounds."}},"rules()":{"details":"This is a view-only function that does not modify state. This operation will copy the entire storage to memory, which can be quite expensive. This is designed to mostly be used by view accessors that are queried without any gas fees.","returns":{"_0":"An array of all active rule contract addresses."}},"rulesCount()":{"details":"Equivalent to the length of the internal rules array. Complexity: O(1)","returns":{"_0":"The number of active rules."}},"setMaxRules(uint256)":{"details":"Access control is implementation specific (admin/owner). Setting a very high cap re-exposes unbounded gas cost for administrative operations such as {clearRules} even though normal per-transfer cost remains bounded.","params":{"maxRules_":"New maximum number of rules."}},"setRules(address[])":{"details":"Replaces the entire rule set atomically. Reverts if `rules_` is empty. Use {clearRules} to remove all rules explicitly. To transition from one non-empty set to another without an enforcement gap, call this function directly with the new set. Emits {ClearRules} when the existing rule set is non-empty, then emits {AddRule} for each new rule. Off-chain indexers must handle both events to reconstruct state. Security convention: rule contracts should be treated as trusted business logic, but should not also be granted {RULES_MANAGEMENT_ROLE}.","params":{"rules_":"The array of addresses representing the new rules to be set."}},"setTokenSelfBindingApproval(address,bool)":{"details":"Must be restricted by implementation-specific access control. An approval stays in force until it is revoked here or until the binding manager unbinds the token ({unbindToken} or {unbindTokens}), which revokes it and emits {TokenSelfBindingApprovalSet} with `false`. A token that unbinds itself keeps its approval, so it can bind itself again later.","params":{"approved":"Whether self-binding is approved for `token`.","token":"The token address to configure."}},"setTokenSelfBindingApprovalBatch(address[],bool)":{"details":"Must be restricted by implementation-specific access control. Reverts if any token in `tokens` is the zero address. Emits a single {TokenSelfBindingApprovalBatchSet} with the input array, not one {TokenSelfBindingApprovalSet} per token.","params":{"approved":"Whether self-binding is approved for all provided tokens.","tokens":"The token addresses to configure."}},"supportsInterface(bytes4)":{"params":{"interfaceId":"The interface identifier to check."},"returns":{"_0":"True if the interface is supported, false otherwise."}},"transferOwnership(address)":{"details":"Reverts when `newOwner` is already configured as a rule.","params":{"newOwner":"The address of the new owner."}},"transferred(address,address,address,uint256)":{"details":"Must revert if the transfer is invalid Same name as ERC-3643 but with one supplementary argument `spender` This function can be used to update state variables of the RuleEngine contract This function can be called ONLY by the token contract bound to the RuleEngine Which overload the token calls (since CMTAT v3.3.0): - this 4-argument overload for `transferFrom` (`spender` = approved spender) and for every operation initiated by an operator, with the operator as `spender`: mint (`from == address(0)`), burn (`to == address(0)`), including `burnFrom`, self-burn and cross-chain mint/burn, and the minter `batchTransfer`; - the 3-argument ERC-3643 overload `transferred(from, to, value)`, inherited from {IERC3643IComplianceContract}, only for a direct `transfer`. Up to CMTAT v3.2.0, mint, burn and the minter transfer used the 3-argument overload. WARNING - zero-value calls are permissionless. ERC-20 requires transfers of `0` to be treated as normal transfers, and OpenZeppelin's `_spendAllowance` consumes no allowance when `value == 0`. Any address can therefore call `transferFrom(victim, anyone, 0)` on the token and reach this callback for an arbitrary `from`, with itself as `spender`, without ever having been approved. The token deliberately does not suppress the notification, because doing so would make its compliance notifications inconsistent with its own ERC-20 transfer semantics. Implementations MUST therefore treat `value == 0` as carrying no economic meaning: any stateful rule (cooldown, holding period, quota, tax bucket, counter, holder tracking, ...) MUST be a no-op for a zero value, otherwise an attacker can desynchronize policy state from balances, or keep a holder permanently restricted, at no cost. The same applies to the 3-argument ERC-3643 overload, which a zero-value `transfer(to, 0)` reaches the same way.","params":{"from":"token holder address","spender":"spender address (sender)","to":"receiver address","value":"value of tokens involved in the transfer; MAY be `0` — see the warning above"}},"transferred(address,address,uint256)":{"details":" This function can be used to update state variables of the compliance contract This function can be called ONLY by the token contract bound to the compliance","params":{"from":"The address of the sender","to":"The address of the receiver","value":"value of tokens involved in the transfer"}},"unbindToken(address)":{"details":"Authorized by {_authorizeTokenBindingChange}. Operator warning: unbinding is an administrative operation and does not erase any state already stored downstream in a previously shared (\"multi-tenant\") setup.","params":{"token":"The address of the token to unbind."}},"unbindTokens(address[])":{"details":"Must be restricted by implementation-specific access control. Atomic: reverts if any token is not currently bound, and then unbinds none of them. Deliberately not the skip-if-already-done batch convention, for the same reason as {bindTokens}. An empty array is a no-op. Like a manager's {unbindToken}, revokes each token's self-binding approval (see {setTokenSelfBindingApproval}).","params":{"tokens":"The token addresses to unbind."}},"version()":{"details":"This value is useful to know which smart contract version has been used","returns":{"version_":"A string representing the version of the token implementation (e.g., \"1.0.0\")."}}},"version":1},"userdoc":{"kind":"user","methods":{"DEFAULT_MAX_RULES()":{"notice":"Default upper bound on the number of rules a RuleEngine may hold."},"addRule(address)":{"notice":"Adds a new rule to the current rule set."},"bindToken(address)":{"notice":"Binds a token contract, allowing it to call the bound-token entry points."},"bindTokens(address[])":{"notice":"Binds several token contracts in a single call."},"canTransfer(address,address,uint256)":{"notice":"Returns true if the transfer is valid, and false otherwise."},"canTransferFrom(address,address,address,uint256)":{"notice":"Checks if `spender` can transfer `value` tokens from `from` to `to` under compliance rules."},"clearRules()":{"notice":"Removes all configured rules."},"constructor":{"notice":"Deploys a RuleEngine with ERC-173 ownership, without a trusted forwarder."},"containsRule(address)":{"notice":"Checks whether a specific rule is currently configured."},"created(address,uint256)":{"notice":"Updates the compliance contract state when tokens are created (minted)."},"destroyed(address,uint256)":{"notice":"Updates the compliance contract state when tokens are destroyed (burned)."},"detectTransferRestriction(address,address,uint256)":{"notice":"Queries every rule, in order, and returns the first restriction code that is not zero"},"detectTransferRestrictionFrom(address,address,address,uint256)":{"notice":"Returns a uint8 code to indicate if a transfer is restricted or not"},"getTokenBound()":{"notice":"Returns the single token currently bound to this compliance contract."},"getTokenBounds()":{"notice":"Returns all tokens currently bound."},"isTokenBound(address)":{"notice":"Checks whether a token is currently bound."},"isTokenSelfBindingApproved(address)":{"notice":"Returns whether a token is approved to bind and unbind itself."},"maxRules()":{"notice":"Returns the maximum number of rules allowed in the engine."},"removeRule(address)":{"notice":"Removes a specific rule from the current rule set."},"rule(uint256)":{"notice":"Retrieves the rule address at a specific index."},"rules()":{"notice":"Returns the full list of currently configured rules."},"rulesCount()":{"notice":"Returns the total number of currently configured rules."},"setMaxRules(uint256)":{"notice":"Updates the maximum number of rules allowed in the engine."},"setRules(address[])":{"notice":"Defines the rules for the rule engine."},"setTokenSelfBindingApproval(address,bool)":{"notice":"Sets whether a token is allowed to bind and unbind itself."},"setTokenSelfBindingApprovalBatch(address[],bool)":{"notice":"Sets self-binding approval for multiple tokens in one transaction."},"supportsInterface(bytes4)":{"notice":"ERC-165 interface detection."},"transferOwnership(address)":{"notice":"Transfers ownership of the contract to a new account (`newOwner`)."},"transferred(address,address,address,uint256)":{"notice":"Function called whenever tokens are transferred from one wallet to another, minted or burned, when the token knows the account that initiated the operation (`spender`)."},"transferred(address,address,uint256)":{"notice":"Function called whenever tokens are transferred from one wallet to another"},"unbindToken(address)":{"notice":"Unbinds a token contract, revoking its access to the bound-token entry points."},"unbindTokens(address[])":{"notice":"Unbinds several token contracts in a single call."},"version()":{"notice":"Returns the current version of the token contract."}},"version":1}},"settings":{"remappings":["@chainlink/contracts-ccip/=lib/Rules/lib/chainlink-ace/node_modules/@chainlink/contracts-ccip/chains/evm/contracts/","@chainlink/contracts/=lib/Rules/lib/chainlink-ace/node_modules/@chainlink/contracts/","@chainlink/contracts@1.4.0/=lib/Rules/lib/chainlink-doc/node_modules/@chainlink/contracts-1.4.0/","@chainlink/cross-chain-identity/=lib/Rules/lib/chainlink-ace/packages/cross-chain-identity/src/","@chainlink/local/=lib/Rules/lib/chainlink-doc/node_modules/@chainlink/local/","@chainlink/policy-management/=lib/Rules/lib/chainlink-ace/packages/policy-management/src/","@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/","@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/","@openzeppelin/contracts@4.7.3/=lib/Rules/lib/chainlink-doc/node_modules/@openzeppelin/contracts-4.7.3/","@openzeppelin/contracts@4.8.3/=lib/Rules/lib/chainlink-ace/node_modules/@openzeppelin/contracts-4.8.3/","@openzeppelin/contracts@4.9.6/=lib/Rules/lib/chainlink-doc/node_modules/@openzeppelin/contracts-4.9.6/","@openzeppelin/contracts@5.0.2/=lib/Rules/lib/chainlink-ace/node_modules/@openzeppelin/contracts/","@openzeppelin/contracts@5.1.0/=lib/Rules/lib/chainlink-doc/node_modules/@openzeppelin/contracts-5.1.0/","@openzeppelin/contracts@5.3.0/=lib/Rules/lib/chainlink-ace/node_modules/@openzeppelin/contracts-5.3.0/","CMTAT/=lib/CMTAT/contracts/","CMTATv3.0.0/=lib/CMTATv3.0.0/contracts/","ERC-3643/=lib/ERC-3643/contracts/","ERC3643/=lib/Rules/lib/ERC-3643/contracts/","RuleEngine/=lib/Rules/lib/RuleEngine/","Rules/=lib/Rules/","chainlink-ace/=lib/Rules/lib/chainlink-ace/","chainlink-doc/=lib/Rules/lib/","erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/","forge-std/=lib/forge-std/src/","halmos-cheatcodes/=lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/","openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/","openzeppelin-contracts/=lib/openzeppelin-contracts/"],"optimizer":{"enabled":true,"runs":200},"metadata":{"bytecodeHash":"ipfs"},"compilationTarget":{"src/deployment/ownable/RuleEngineOwnable.sol":"RuleEngineOwnable"},"evmVersion":"osaka","libraries":{}},"sources":{"lib/CMTAT/contracts/interfaces/engine/IRuleEngine.sol":{"keccak256":"0xeda899e2e46a9b9c3516acb61a7f7e92ed098928379010655c330da721aaffa7","urls":["bzz-raw://60f8555330fc531dff7d0d71a862696fb286a0ba3290e41efbbbf4dd25947a3c","dweb:/ipfs/QmWvbsBGWPtNMNN2EEedwdzzvQG7NtSj9VD2fmNgqVtCXN"],"license":"MPL-2.0"},"lib/CMTAT/contracts/interfaces/technical/IERC5679.sol":{"keccak256":"0x5bee30750c9a65438469a6c5bd8465e1603eec3aeeb94c07bd64ba3e9ee766e1","urls":["bzz-raw://ef7a5c5f0d47135c97ab5d7456d31e513a71c849ae7f2f5395f860be125c4fbc","dweb:/ipfs/Qmezem3qqSjij6ggyB34wC2S15KrY9fu42oymyS9epAYCQ"],"license":"MPL-2.0"},"lib/CMTAT/contracts/interfaces/tokenization/IERC3643Partial.sol":{"keccak256":"0x5c84c2e2442824e98625c471482fb3c9502f43f4c345e7c0fb07fa549be02e26","urls":["bzz-raw://19071f2d12fb580d37eeee07885461f193568df34f3f69d2c5d65ce655d84435","dweb:/ipfs/QmRqHwC7LksE3YPohMtxFieiPerhWdoDNUUMMLbB4XYvhK"],"license":"MPL-2.0"},"lib/CMTAT/contracts/interfaces/tokenization/draft-IERC1404.sol":{"keccak256":"0xc27cdac182d930a94391d589bdafa15364b6f8d9bf211175781dba661f1c0336","urls":["bzz-raw://b509fa7f3cfd785632569f6ae3bec846aa0beefd73c1d5bde233440cae919f0f","dweb:/ipfs/QmPCAdiEun8gaMqS8KhwPpRZV2zXAPfURRaF4C2KjX5Kby"],"license":"MPL-2.0"},"lib/CMTAT/contracts/interfaces/tokenization/draft-IERC7551.sol":{"keccak256":"0x84b73eb77ec82d6d7b313eff2d87f58d3b795840d004aaa10c611b360b827e30","urls":["bzz-raw://a5b8c99fb3600369065a422d3821ba441dc06fc64f50ce0f33950a76ad82b51b","dweb:/ipfs/QmbviJsZPY3xuLU3cHUWJx11aJCPAuN4WKnCufN4kVLm2U"],"license":"MPL-2.0"},"lib/CMTAT/contracts/interfaces/tokenization/draft-IERC7943.sol":{"keccak256":"0xc69588a72da81057ee278e961e8e3bb61a28d64c3c6cebe494ce00809c1cef15","urls":["bzz-raw://148f117d9c463de441f81e6c0a67e95f1f14a61db209492dd0a1767b5572f21a","dweb:/ipfs/QmUjT5uyJfNSYgUWn5Dxhf6Sx9Y1z8CNf3PuTEaGoAx3za"],"license":"MPL-2.0"},"lib/CMTAT/contracts/library/ERC1404ExtendInterfaceId.sol":{"keccak256":"0xf8268f4eb3a6b2e26c32cf76c5c76b6c17df3385c150f05953538a2472149247","urls":["bzz-raw://05108de7a7ba2a0a67978bdfe8e500360674db6d894f42970bb1016b36639056","dweb:/ipfs/QmRux9Qj1GomATseS6Tyq9uiPPNNipuxg2HjdjnPjgSQds"],"license":"MPL-2.0"},"lib/CMTAT/contracts/library/RuleEngineInterfaceId.sol":{"keccak256":"0x1152a49cba4232d943e295d259eb8a1b216d815067367410a5729a256dae4051","urls":["bzz-raw://470f4435a5e62b0ba0ad70f8657b2db0e4cc3b7f2561772adb944ce010551ee6","dweb:/ipfs/QmXECahRr8rK9XJPZwBCnemLDVPdFvPEBusezhaBqbLBqp"],"license":"MPL-2.0"},"lib/openzeppelin-contracts/contracts/access/Ownable.sol":{"keccak256":"0xff6d0bb2e285473e5311d9d3caacb525ae3538a80758c10649a4d61029b017bb","urls":["bzz-raw://8ed324d3920bb545059d66ab97d43e43ee85fd3bd52e03e401f020afb0b120f6","dweb:/ipfs/QmfEckWLmZkDDcoWrkEvMWhms66xwTLff9DDhegYpvHo1a"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/interfaces/IERC165.sol":{"keccak256":"0x0afcb7e740d1537b252cb2676f600465ce6938398569f09ba1b9ca240dde2dfc","urls":["bzz-raw://1c299900ac4ec268d4570ecef0d697a3013cd11a6eb74e295ee3fbc945056037","dweb:/ipfs/Qmab9owJoxcA7vJT5XNayCMaUR1qxqj1NDzzisduwaJMcZ"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/Arrays.sol":{"keccak256":"0x772f0c778626a7bdcbcbabca74b825ae9b9dc89d2a47a98b402b1187fbaa63a4","urls":["bzz-raw://eba1d46e58e8880b45c6d51245dc94585b81d6d7290ca77ef50037a6193ed301","dweb:/ipfs/Qme3CWun5qQACjGEerT2MCvhs6brKGFfJirGnzV1ypKTXA"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/Comparators.sol":{"keccak256":"0x302eecd8cf323b4690e3494a7d960b3cbce077032ab8ef655b323cdd136cec58","urls":["bzz-raw://49ba706f1bc476d68fe6c1fad75517acea4e9e275be0989b548e292eb3a3eacd","dweb:/ipfs/QmeBpvcdGWzWMKTQESUCEhHgnEQYYATVwPxLMxa6vMT7jC"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/Context.sol":{"keccak256":"0x493033a8d1b176a037b2cc6a04dad01a5c157722049bbecf632ca876224dd4b2","urls":["bzz-raw://6a708e8a5bdb1011c2c381c9a5cfd8a9a956d7d0a9dc1bd8bcdaf52f76ef2f12","dweb:/ipfs/Qmax9WHBnVsZP46ZxEMNRQpLQnrdE4dK8LehML1Py8FowF"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/Panic.sol":{"keccak256":"0xf7fe324703a64fc51702311dc51562d5cb1497734f074e4f483bfb6717572d7a","urls":["bzz-raw://c6a5ff4f9fd8649b7ee20800b7fa387d3465bd77cf20c2d1068cd5c98e1ed57a","dweb:/ipfs/QmVSaVJf9FXFhdYEYeCEfjMVHrxDh5qL4CGkxdMWpQCrqG"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/SlotDerivation.sol":{"keccak256":"0x94045fd4f268edf2b2d01ef119268548c320366d6f5294ad30c1b8f9d4f5225f","urls":["bzz-raw://edfda81f426f8948b3834115c21e83c48180e6db0d2a8cd2debb2185ed349337","dweb:/ipfs/QmdYZneFyDAux1BuWQxLAdqtABrGS2k9WYCa7C9dvpKkWv"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol":{"keccak256":"0xcf74f855663ce2ae00ed8352666b7935f6cddea2932fdf2c3ecd30a9b1cd0e97","urls":["bzz-raw://9f660b1f351b757dfe01438e59888f31f33ded3afcf5cb5b0d9bf9aa6f320a8b","dweb:/ipfs/QmarDJ5hZEgBtCmmrVzEZWjub9769eD686jmzb2XpSU1cM"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol":{"keccak256":"0x2d9dc2fe26180f74c11c13663647d38e259e45f95eb88f57b61d2160b0109d3e","urls":["bzz-raw://81233d1f98060113d9922180bb0f14f8335856fe9f339134b09335e9f678c377","dweb:/ipfs/QmWh6R35SarhAn4z2wH8SU456jJSYL2FgucfTFgbHJJN4E"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165Checker.sol":{"keccak256":"0x7c7ad70641a7f8cd44def0857ec97b0e40bfd073b2d6037a5f57ce9527ee9bc5","urls":["bzz-raw://e05c6572dfe769f7aea6f3a8002951cc12d143d980dad29f6c5feedf9408bc14","dweb:/ipfs/QmXM7C8YEptxisZiEefXUrwdXt3zMaCobmkCchxTtDg1oK"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol":{"keccak256":"0x8891738ffe910f0cf2da09566928589bf5d63f4524dd734fd9cedbac3274dd5c","urls":["bzz-raw://971f954442df5c2ef5b5ebf1eb245d7105d9fbacc7386ee5c796df1d45b21617","dweb:/ipfs/QmadRjHbkicwqwwh61raUEapaVEtaLMcYbQZWs9gUkgj3u"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/math/Math.sol":{"keccak256":"0x59973a93b1f983f94e10529f46ca46544a9fec2b5f56fb1390bbe9e0dc79f857","urls":["bzz-raw://c55ef8f0b9719790c2ae6f81d80a59ffb89f2f0abe6bc065585bd79edce058c5","dweb:/ipfs/QmNNmCbX9NjPXKqHJN8R1WC2rNeZSQrPZLd6FF6AKLyH5Y"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol":{"keccak256":"0xc8cae21c9ae4a46e5162ff9bf5b351d6fa6a6eba72d515f3bc1bdfeda7fdf083","urls":["bzz-raw://ce830ebcf28e31643caba318996db3763c36d52cd0f23798ba83c135355d45e9","dweb:/ipfs/QmdGPcvptHN7UBCbUYBbRX3hiRVRFLRwno8b4uga6uFNif"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/structs/EnumerableSet.sol":{"keccak256":"0xd553ff8b7d55679f0711f1598600ac292dbd8cfdf4b2419b9cabe4c931172895","urls":["bzz-raw://7905ccb27e2308fd0d90dc1212161003ab6964e1c176593db1ccedef705bcc09","dweb:/ipfs/QmW37vm2PcrWLKnN74sKkvAzqSwntCEfCp4EoSEvbBHWkj"],"license":"MIT"},"src/RuleEngineBase.sol":{"keccak256":"0xb3d832fa55b615574d80b0e0ad76620ad236aa046523617ed5daa46ae07bf853","urls":["bzz-raw://7be31bf5dbd3fa1be025cdc4b7674b76bf40e1c14ce89ec78f792cb3d7ed804e","dweb:/ipfs/QmPq4xBiB3XwXerWtuonZLGiWHMqvz5tKvjhTh9AiWkbww"],"license":"MPL-2.0"},"src/RuleEngineOwnableShared.sol":{"keccak256":"0xa78493398d8b0554e72def7f14d7439109bd4dbd5e07f1466b40acea2bb7dc02","urls":["bzz-raw://ebd87d69b4f6eb193c5d03476381ac132f9587248422d3306dda95b79fd4e470","dweb:/ipfs/QmWYDLvPWjRcfxdR2KhXAij8U9TrFjeM77fsJRX25jWQmY"],"license":"MPL-2.0"},"src/deployment/ownable/RuleEngineOwnable.sol":{"keccak256":"0x9f34713fce49bbc841ed5f0d24c5b53455359a11d904f7ceb3c7ef210494c6c5","urls":["bzz-raw://71875cc9f3a8f9f35b5ec06273cc1c83a23b2cb775ab2974610ca0dc4ac74945","dweb:/ipfs/QmQUVtngskTrnPjv85BLJhEDxYVwp7WFhBHPBpRL4cvn27"],"license":"MPL-2.0"},"src/interfaces/IERC3643Compliance.sol":{"keccak256":"0xd0edd6697d67135853576ac6a40cadaffd787cedea98071708bbfb189c7ee5bc","urls":["bzz-raw://4ed3cd3af64fccff17a1f33989cdfbdacbc0e4f32a56de11a072cf9e2277a1f6","dweb:/ipfs/QmenRqRw1Yy39yDv1pJgBmnHtwuZhDdHE4omchL41CjXjb"],"license":"MPL-2.0"},"src/interfaces/IERC3643ComplianceExtended.sol":{"keccak256":"0x4a43bf330c7a904cba110acf52f519718d8409514c377912d5bd063c9d963729","urls":["bzz-raw://c671879c591760ecbc2691e2f24adfb215a658c9fe6eb0c05dd1ca980054e585","dweb:/ipfs/QmdbA19PFpJgHraF46YrcMNzUgswbTRA92atL2Lha63JLY"],"license":"MPL-2.0"},"src/interfaces/IRule.sol":{"keccak256":"0x81580b67f7be09049aa64d93cc1d8d691a87c639adc1cf169dc6073e1e543a5c","urls":["bzz-raw://6f1808c3ed18ef1acbccdd9b30011b6e7220d388cfd66cba40b1ef0b485306a1","dweb:/ipfs/QmcUCQ5MYcf7KTtoeqMKsTutPPSJhNTaK1ntHV21ioS9Fm"],"license":"MPL-2.0"},"src/interfaces/IRulesManagementModule.sol":{"keccak256":"0x082dd58070e83b02f275584afa872c4583ac4ca8ad12eb329fc11301470147f9","urls":["bzz-raw://e2d0ad78dc323881864f406acd44976f5de39cdc97a6c99a724d8458b993e2e2","dweb:/ipfs/QmRFfMbXbdiAYV3vQyNppXG7tHTji6mV1Y5Cu3ZzEQm5ng"],"license":"MPL-2.0"},"src/interfaces/ITokenBinding.sol":{"keccak256":"0x34dfea4e118c966adf867c0899844515566251819b4e4510fd8ee424555493fd","urls":["bzz-raw://1d054ed49874816688a6e71f76d611bbdefd492d122ae386cb804c6f5af677a7","dweb:/ipfs/QmRaYX4aJWYSNWNa1D4Nich3k7hkGM9rTfc9s2XaVqyRjy"],"license":"MPL-2.0"},"src/interfaces/ITokenBindingExtended.sol":{"keccak256":"0x01f3ab56dffce860d03e72d10e9f2d13b6bfc9004cf058c63a0b23e3b226da99","urls":["bzz-raw://521e0c9651632b70d61c4c3bd0b14c6f05d818166fe65dbed8e3253158b7637e","dweb:/ipfs/QmY2xEVvfV1dgtFYw6coHX3Z7Fm7yRhzPaGyt6cYBMVf76"],"license":"MPL-2.0"},"src/modules/ERC3643ComplianceExtendedModule.sol":{"keccak256":"0x6f808b068517e9e15f09fc6a9d4190001ec8c2314a10e27a85a2d43e44c84fb1","urls":["bzz-raw://c62c0b77fdd8b6e7bf7aa5bf8134a78ff024d6489a23f746874a99df38a8a265","dweb:/ipfs/QmV7PG3ZUUzwDs9tpooC3hmBu5e39buJnJ4TRditojJ3hu"],"license":"MPL-2.0"},"src/modules/ERC3643ComplianceModule.sol":{"keccak256":"0x7cda81af8687328ac2089f9d1d78352e0e75d0f70a4ba8e2b3ac82896f22863f","urls":["bzz-raw://50711cb94d69ea63d787a8bb19c38c0b99539029ec8fb957a8eff00880fc11fc","dweb:/ipfs/QmSapDWh5mpvWn1q6JteZisJfVGPrCz47WP2BBrJCccEjV"],"license":"MPL-2.0"},"src/modules/RulesManagementModule.sol":{"keccak256":"0xe4d9425613284e71a5e3d590d5433167a9751d9496f57efa914baa81f493e66d","urls":["bzz-raw://d07a16e6869df86c526ef89e7e359e34a9553dc4288b262abd2979359ecf720e","dweb:/ipfs/QmRy2JEsyhkv1mxv7eFaSbEWN4A3gtpPSUnnV48W2KiV4u"],"license":"MPL-2.0"},"src/modules/TokenBindingExtendedModule.sol":{"keccak256":"0x4e1ca7b2ec78608c3a7960bec7102a1780bdf3ec7ff544b612bafaf738b34d05","urls":["bzz-raw://657bcdd303fd5a7fbe733b283f69d8e8aa73efeeeaf95c0ae7479769ac573693","dweb:/ipfs/QmXiWPrv8pEqvBQck8jxC7NwB1MUdGQfLjihK6etYcZ54j"],"license":"MPL-2.0"},"src/modules/TokenBindingModule.sol":{"keccak256":"0xf65f46311d0078f60c30e3359dca988e39cba45b9eee53a09d618bfa70e6ef9b","urls":["bzz-raw://e8c458ecfd41df5fb4a391e7ef837fd5ed5c999e61ccc0e6b4bd23023a739832","dweb:/ipfs/Qmdsr765aw9fPFN2M9cSCP69o1o41FNCqhrXjHgEXNwbXV"],"license":"MPL-2.0"},"src/modules/VersionModule.sol":{"keccak256":"0x35daf007be8b9bb1cb9196ae2decb3e5ad4b574f6390f8fc010b78796ac42f73","urls":["bzz-raw://b1b29d75e1c5023a0c6cb8c56638a17d855a3fdc051a60b9d2f304b99f7876d2","dweb:/ipfs/QmXSCVjLuViC8916LwNpKtw8hqyH78Ptag3xH1n7F1fY4g"],"license":"MPL-2.0"},"src/modules/library/ComplianceInterfaceId.sol":{"keccak256":"0xd54bed5328e732f753d2886aeaa2761b2d66536d5247d4548e0ac1c83c7a0dac","urls":["bzz-raw://ad695339fdfe72446a69d2dfbe39373affe2f37299ad921e57016069a7bc3592","dweb:/ipfs/QmWathGt3E85hLfy5rrAYdb291W8VoTa4gpGPoxtWGvNNA"],"license":"MPL-2.0"},"src/modules/library/ERC1404InterfaceId.sol":{"keccak256":"0x07dc6905e137096cd0ae88be29b112d0e54a83ddf8ca527a281718010f6abcce","urls":["bzz-raw://9249dce67cb59432bdbc9e49978c6cac0346cda3d3fca97c5a310e0f424e1600","dweb:/ipfs/QmRi5awH3hjwvd3k3td48y5Cf64n1wvX9wCWy6fQLayuKs"],"license":"MPL-2.0"},"src/modules/library/OwnableInterfaceId.sol":{"keccak256":"0xdbe06b3203e21e41d1fd2a3ef373a80727193443dfd981de6821422158015d4f","urls":["bzz-raw://ebe8699ae8af81c5cd82f25a1609d9396d72ae957647c33aaa745aadcdac8d18","dweb:/ipfs/QmV73gwDJPFthn8VspdYE6GsoAcQMAR7TachUK8YrPonuT"],"license":"MPL-2.0"},"src/modules/library/RuleEngineInvariantStorage.sol":{"keccak256":"0x50a212f09f1695662965e5fba643b42a1978bec2a8368abbf43983489c983096","urls":["bzz-raw://6137f01df7630527c985d85d2f7446359c678fcb933b66c55b51f583757b5c4a","dweb:/ipfs/QmeHo47WQm1V99xZHS4soMk68UdtXtZhtWhV3dQC5BtA7u"],"license":"MPL-2.0"},"src/modules/library/RuleInterfaceId.sol":{"keccak256":"0x0d86820eee4c92b21d6704bea8ce7bd2cc1b35f6e4a1ceabbcf2a10f1c6b02ec","urls":["bzz-raw://cfb560cb8588983b8c79a973d03c214a149bf1ac034fa9130ce93f0031a404d7","dweb:/ipfs/Qmc6qt4E4BHdDyLUegCsgxqhf7ZFUiX4ahj8FjM54V7wpY"],"license":"MPL-2.0"},"src/modules/library/RulesManagementModuleInvariantStorage.sol":{"keccak256":"0xb81ea3a54c6e8d47b87d6c3d9fb5aae80c3430021b8cd66d9adeef7f5fc95893","urls":["bzz-raw://cfcbadc2011f60de7189273c278dda1df2218aeeb153bee3b8a93447ec95df21","dweb:/ipfs/Qmem5FqCLEfBJQdJzS7Xzd3zSfyL8Muf9Wv5WvCiBVsqfh"],"license":"MPL-2.0"},"src/modules/library/TokenBindingModuleInvariantStorage.sol":{"keccak256":"0x9bab8e5b265068da356fd46e343a7c6c73776f3964fdeaeff056e8ce104d40a5","urls":["bzz-raw://e2e75d2d52b1e4f5cbb832d194266de9a1b3a8cc2101e875dce43a2664c31a05","dweb:/ipfs/QmUsd5cTPsE89WKm3kTUWsobR9JsBDUY8NdxDU5RPYpvP6"],"license":"MPL-2.0"}},"version":1},"ast":{"absolutePath":"src/deployment/ownable/RuleEngineOwnable.sol","id":10018,"exportedSymbols":{"Ownable":[1144],"RuleEngineOwnable":[10017],"RuleEngineOwnableShared":[9689]},"nodeType":"SourceUnit","src":"37:1790:32","nodes":[{"id":9946,"nodeType":"PragmaDirective","src":"37:24:32","nodes":[],"literals":["solidity","^","0.8",".27"]},{"id":9948,"nodeType":"ImportDirective","src":"63:67:32","nodes":[],"absolutePath":"lib/openzeppelin-contracts/contracts/access/Ownable.sol","file":"@openzeppelin/contracts/access/Ownable.sol","nameLocation":"-1:-1:-1","scope":10018,"sourceUnit":1145,"symbolAliases":[{"foreign":{"id":9947,"name":"Ownable","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":1144,"src":"71:7:32","typeDescriptions":{}},"nameLocation":"-1:-1:-1"}],"unitAlias":""},{"id":9950,"nodeType":"ImportDirective","src":"131:74:32","nodes":[],"absolutePath":"src/RuleEngineOwnableShared.sol","file":"../../RuleEngineOwnableShared.sol","nameLocation":"-1:-1:-1","scope":10018,"sourceUnit":9690,"symbolAliases":[{"foreign":{"id":9949,"name":"RuleEngineOwnableShared","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":9689,"src":"139:23:32","typeDescriptions":{}},"nameLocation":"-1:-1:-1"}],"unitAlias":""},{"id":10017,"nodeType":"ContractDefinition","src":"470:1356:32","nodes":[{"id":9970,"nodeType":"FunctionDefinition","src":"793:108:32","nodes":[],"body":{"id":9969,"nodeType":"Block","src":"899:2:32","nodes":[],"statements":[]},"documentation":{"id":9956,"nodeType":"StructuredDocumentation","src":"539:249:32","text":" @notice Deploys a RuleEngine with ERC-173 ownership, without a trusted forwarder.\n @param owner_ Address of the contract owner (ERC-173)\n @param tokenContract Address of the token contract to bind (can be zero address)"},"implemented":true,"kind":"constructor","modifiers":[{"arguments":[{"id":9963,"name":"tokenContract","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":9960,"src":"868:13:32","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"id":9964,"kind":"baseConstructorSpecifier","modifierName":{"id":9962,"name":"RuleEngineOwnableShared","nameLocations":["844:23:32"],"nodeType":"IdentifierPath","referencedDeclaration":9689,"src":"844:23:32"},"nodeType":"ModifierInvocation","src":"844:38:32"},{"arguments":[{"id":9966,"name":"owner_","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":9958,"src":"891:6:32","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"id":9967,"kind":"baseConstructorSpecifier","modifierName":{"id":9965,"name":"Ownable","nameLocations":["883:7:32"],"nodeType":"IdentifierPath","referencedDeclaration":1144,"src":"883:7:32"},"nodeType":"ModifierInvocation","src":"883:15:32"}],"name":"","nameLocation":"-1:-1:-1","parameters":{"id":9961,"nodeType":"ParameterList","parameters":[{"constant":false,"id":9958,"mutability":"mutable","name":"owner_","nameLocation":"813:6:32","nodeType":"VariableDeclaration","scope":9970,"src":"805:14:32","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":9957,"name":"address","nodeType":"ElementaryTypeName","src":"805:7:32","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"},{"constant":false,"id":9960,"mutability":"mutable","name":"tokenContract","nameLocation":"829:13:32","nodeType":"VariableDeclaration","scope":9970,"src":"821:21:32","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":9959,"name":"address","nodeType":"ElementaryTypeName","src":"821:7:32","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"src":"804:39:32"},"returnParameters":{"id":9968,"nodeType":"ParameterList","parameters":[],"src":"899:0:32"},"scope":10017,"stateMutability":"nonpayable","virtual":false,"visibility":"public"},{"id":9992,"nodeType":"FunctionDefinition","src":"1127:204:32","nodes":[],"body":{"id":9991,"nodeType":"Block","src":"1206:125:32","nodes":[],"statements":[{"expression":{"arguments":[{"id":9982,"name":"newOwner","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":9973,"src":"1270:8:32","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":9979,"name":"RuleEngineOwnableShared","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":9689,"src":"1216:23:32","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_RuleEngineOwnableShared_$9689_$","typeString":"type(contract RuleEngineOwnableShared)"}},"id":9981,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberLocation":"1240:29:32","memberName":"_checkOwnershipTransferTarget","nodeType":"MemberAccess","referencedDeclaration":9688,"src":"1216:53:32","typeDescriptions":{"typeIdentifier":"t_function_internal_view$_t_address_$returns$__$","typeString":"function (address) view"}},"id":9983,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"nameLocations":[],"names":[],"nodeType":"FunctionCall","src":"1216:63:32","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":9984,"nodeType":"ExpressionStatement","src":"1216:63:32"},{"expression":{"arguments":[{"id":9988,"name":"newOwner","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":9973,"src":"1315:8:32","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":9985,"name":"Ownable","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":1144,"src":"1289:7:32","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_Ownable_$1144_$","typeString":"type(contract Ownable)"}},"id":9987,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberLocation":"1297:17:32","memberName":"transferOwnership","nodeType":"MemberAccess","referencedDeclaration":1123,"src":"1289:25:32","typeDescriptions":{"typeIdentifier":"t_function_internal_nonpayable$_t_address_$returns$__$","typeString":"function (address)"}},"id":9989,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"nameLocations":[],"names":[],"nodeType":"FunctionCall","src":"1289:35:32","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":9990,"nodeType":"ExpressionStatement","src":"1289:35:32"}]},"baseFunctions":[1123],"documentation":{"id":9971,"nodeType":"StructuredDocumentation","src":"907:215:32","text":" @notice Transfers ownership of the contract to a new account (`newOwner`).\n @dev Reverts when `newOwner` is already configured as a rule.\n @param newOwner The address of the new owner."},"functionSelector":"f2fde38b","implemented":true,"kind":"function","modifiers":[{"id":9977,"kind":"modifierInvocation","modifierName":{"id":9976,"name":"onlyOwner","nameLocations":["1196:9:32"],"nodeType":"IdentifierPath","referencedDeclaration":1055,"src":"1196:9:32"},"nodeType":"ModifierInvocation","src":"1196:9:32"}],"name":"transferOwnership","nameLocation":"1136:17:32","overrides":{"id":9975,"nodeType":"OverrideSpecifier","overrides":[],"src":"1187:8:32"},"parameters":{"id":9974,"nodeType":"ParameterList","parameters":[{"constant":false,"id":9973,"mutability":"mutable","name":"newOwner","nameLocation":"1162:8:32","nodeType":"VariableDeclaration","scope":9992,"src":"1154:16:32","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":9972,"name":"address","nodeType":"ElementaryTypeName","src":"1154:7:32","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"src":"1153:18:32"},"returnParameters":{"id":9978,"nodeType":"ParameterList","parameters":[],"src":"1206:0:32"},"scope":10017,"stateMutability":"nonpayable","virtual":true,"visibility":"public"},{"id":10000,"nodeType":"FunctionDefinition","src":"1459:67:32","nodes":[],"body":{"id":9999,"nodeType":"Block","src":"1524:2:32","nodes":[],"statements":[]},"baseFunctions":[13890],"documentation":{"id":9993,"nodeType":"StructuredDocumentation","src":"1388:66:32","text":" @dev Access control check using Ownable pattern"},"implemented":true,"kind":"function","modifiers":[{"id":9997,"kind":"modifierInvocation","modifierName":{"id":9996,"name":"onlyOwner","nameLocations":["1514:9:32"],"nodeType":"IdentifierPath","referencedDeclaration":1055,"src":"1514:9:32"},"nodeType":"ModifierInvocation","src":"1514:9:32"}],"name":"_onlyRulesManager","nameLocation":"1468:17:32","overrides":{"id":9995,"nodeType":"OverrideSpecifier","overrides":[],"src":"1505:8:32"},"parameters":{"id":9994,"nodeType":"ParameterList","parameters":[],"src":"1485:2:32"},"returnParameters":{"id":9998,"nodeType":"ParameterList","parameters":[],"src":"1524:0:32"},"scope":10017,"stateMutability":"nonpayable","virtual":true,"visibility":"internal"},{"id":10008,"nodeType":"FunctionDefinition","src":"1603:72:32","nodes":[],"body":{"id":10007,"nodeType":"Block","src":"1673:2:32","nodes":[],"statements":[]},"baseFunctions":[13894],"documentation":{"id":10001,"nodeType":"StructuredDocumentation","src":"1532:66:32","text":" @dev Access control check using Ownable pattern"},"implemented":true,"kind":"function","modifiers":[{"id":10005,"kind":"modifierInvocation","modifierName":{"id":10004,"name":"onlyOwner","nameLocations":["1663:9:32"],"nodeType":"IdentifierPath","referencedDeclaration":1055,"src":"1663:9:32"},"nodeType":"ModifierInvocation","src":"1663:9:32"}],"name":"_onlyRulesLimitManager","nameLocation":"1612:22:32","overrides":{"id":10003,"nodeType":"OverrideSpecifier","overrides":[],"src":"1654:8:32"},"parameters":{"id":10002,"nodeType":"ParameterList","parameters":[],"src":"1634:2:32"},"returnParameters":{"id":10006,"nodeType":"ParameterList","parameters":[],"src":"1673:0:32"},"scope":10017,"stateMutability":"nonpayable","virtual":true,"visibility":"internal"},{"id":10016,"nodeType":"FunctionDefinition","src":"1752:72:32","nodes":[],"body":{"id":10015,"nodeType":"Block","src":"1822:2:32","nodes":[],"statements":[]},"baseFunctions":[13446],"documentation":{"id":10009,"nodeType":"StructuredDocumentation","src":"1681:66:32","text":" @dev Access control check using Ownable pattern"},"implemented":true,"kind":"function","modifiers":[{"id":10013,"kind":"modifierInvocation","modifierName":{"id":10012,"name":"onlyOwner","nameLocations":["1812:9:32"],"nodeType":"IdentifierPath","referencedDeclaration":1055,"src":"1812:9:32"},"nodeType":"ModifierInvocation","src":"1812:9:32"}],"name":"_onlyComplianceManager","nameLocation":"1761:22:32","overrides":{"id":10011,"nodeType":"OverrideSpecifier","overrides":[],"src":"1803:8:32"},"parameters":{"id":10010,"nodeType":"ParameterList","parameters":[],"src":"1783:2:32"},"returnParameters":{"id":10014,"nodeType":"ParameterList","parameters":[],"src":"1822:0:32"},"scope":10017,"stateMutability":"nonpayable","virtual":true,"visibility":"internal"}],"abstract":false,"baseContracts":[{"baseName":{"id":9952,"name":"RuleEngineOwnableShared","nameLocations":["500:23:32"],"nodeType":"IdentifierPath","referencedDeclaration":9689,"src":"500:23:32"},"id":9953,"nodeType":"InheritanceSpecifier","src":"500:23:32"},{"baseName":{"id":9954,"name":"Ownable","nameLocations":["525:7:32"],"nodeType":"IdentifierPath","referencedDeclaration":1144,"src":"525:7:32"},"id":9955,"nodeType":"InheritanceSpecifier","src":"525:7:32"}],"canonicalName":"RuleEngineOwnable","contractDependencies":[],"contractKind":"contract","documentation":{"id":9951,"nodeType":"StructuredDocumentation","src":"207:262:32","text":" @title Implementation of a ruleEngine with ERC-173 Ownable access control\n @dev No ERC-2771 support: every caller is the raw `msg.sender`. Deploy {RuleEngineOwnable2771} to\n administer the engine through a trusted forwarder (gasless transactions)."},"fullyImplemented":true,"linearizedBaseContracts":[10017,1144,9689,3578,9604,34,28,3800,14477,13390,10332,13447,14176,10545,10320,14356,14606,10476,262,464,251,311,285,3248,13913,10442,14580,14379,123],"name":"RuleEngineOwnable","nameLocation":"479:17:32","scope":10018,"usedErrors":[1010,1015,14474,14476,14545,14547,14549,14551,14555,14557,14559,14596,14599,14602,14605],"usedEvents":[1021,10450,10455,10490,10498,14565,14571,14574,14579]}],"license":"MPL-2.0"},"id":32} \ No newline at end of file diff --git a/doc/compilation/v3.0.0-rc7/foundry/RuleEngineOwnable2771.sol/RuleEngineOwnable2771.json b/doc/compilation/v3.0.0-rc7/foundry/RuleEngineOwnable2771.sol/RuleEngineOwnable2771.json new file mode 100644 index 00000000..55dde86d --- /dev/null +++ b/doc/compilation/v3.0.0-rc7/foundry/RuleEngineOwnable2771.sol/RuleEngineOwnable2771.json @@ -0,0 +1 @@ +{"abi":[{"type":"constructor","inputs":[{"name":"owner_","type":"address","internalType":"address"},{"name":"forwarderIrrevocable","type":"address","internalType":"address"},{"name":"tokenContract","type":"address","internalType":"address"}],"stateMutability":"nonpayable"},{"type":"function","name":"DEFAULT_MAX_RULES","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"addRule","inputs":[{"name":"rule_","type":"address","internalType":"contract IRule"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"bindToken","inputs":[{"name":"token","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"bindTokens","inputs":[{"name":"tokens","type":"address[]","internalType":"address[]"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"canTransfer","inputs":[{"name":"from","type":"address","internalType":"address"},{"name":"to","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"canTransferFrom","inputs":[{"name":"spender","type":"address","internalType":"address"},{"name":"from","type":"address","internalType":"address"},{"name":"to","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"clearRules","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"containsRule","inputs":[{"name":"rule_","type":"address","internalType":"contract IRule"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"created","inputs":[{"name":"to","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"destroyed","inputs":[{"name":"from","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"detectTransferRestriction","inputs":[{"name":"from","type":"address","internalType":"address"},{"name":"to","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint8","internalType":"uint8"}],"stateMutability":"view"},{"type":"function","name":"detectTransferRestrictionFrom","inputs":[{"name":"spender","type":"address","internalType":"address"},{"name":"from","type":"address","internalType":"address"},{"name":"to","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint8","internalType":"uint8"}],"stateMutability":"view"},{"type":"function","name":"getTokenBound","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"getTokenBounds","inputs":[],"outputs":[{"name":"","type":"address[]","internalType":"address[]"}],"stateMutability":"view"},{"type":"function","name":"isTokenBound","inputs":[{"name":"token","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"isTokenSelfBindingApproved","inputs":[{"name":"token","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"isTrustedForwarder","inputs":[{"name":"forwarder","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"maxRules","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"messageForTransferRestriction","inputs":[{"name":"restrictionCode","type":"uint8","internalType":"uint8"}],"outputs":[{"name":"","type":"string","internalType":"string"}],"stateMutability":"view"},{"type":"function","name":"owner","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"removeRule","inputs":[{"name":"rule_","type":"address","internalType":"contract IRule"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"renounceOwnership","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"rule","inputs":[{"name":"ruleId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"rules","inputs":[],"outputs":[{"name":"","type":"address[]","internalType":"address[]"}],"stateMutability":"view"},{"type":"function","name":"rulesCount","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"setMaxRules","inputs":[{"name":"maxRules_","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setRules","inputs":[{"name":"rules_","type":"address[]","internalType":"contract IRule[]"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setTokenSelfBindingApproval","inputs":[{"name":"token","type":"address","internalType":"address"},{"name":"approved","type":"bool","internalType":"bool"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setTokenSelfBindingApprovalBatch","inputs":[{"name":"tokens","type":"address[]","internalType":"address[]"},{"name":"approved","type":"bool","internalType":"bool"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"supportsInterface","inputs":[{"name":"interfaceId","type":"bytes4","internalType":"bytes4"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"transferOwnership","inputs":[{"name":"newOwner","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"transferred","inputs":[{"name":"spender","type":"address","internalType":"address"},{"name":"from","type":"address","internalType":"address"},{"name":"to","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"transferred","inputs":[{"name":"from","type":"address","internalType":"address"},{"name":"to","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"trustedForwarder","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"unbindToken","inputs":[{"name":"token","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"unbindTokens","inputs":[{"name":"tokens","type":"address[]","internalType":"address[]"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"version","inputs":[],"outputs":[{"name":"version_","type":"string","internalType":"string"}],"stateMutability":"view"},{"type":"event","name":"AddRule","inputs":[{"name":"rule","type":"address","indexed":true,"internalType":"contract IRule"}],"anonymous":false},{"type":"event","name":"ClearRules","inputs":[],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"name":"previousOwner","type":"address","indexed":true,"internalType":"address"},{"name":"newOwner","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"RemoveRule","inputs":[{"name":"rule","type":"address","indexed":true,"internalType":"contract IRule"}],"anonymous":false},{"type":"event","name":"SetMaxRules","inputs":[{"name":"maxRules","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"TokenBound","inputs":[{"name":"token","type":"address","indexed":false,"internalType":"address"}],"anonymous":false},{"type":"event","name":"TokenSelfBindingApprovalBatchSet","inputs":[{"name":"tokens","type":"address[]","indexed":false,"internalType":"address[]"},{"name":"approved","type":"bool","indexed":false,"internalType":"bool"}],"anonymous":false},{"type":"event","name":"TokenSelfBindingApprovalSet","inputs":[{"name":"token","type":"address","indexed":true,"internalType":"address"},{"name":"approved","type":"bool","indexed":false,"internalType":"bool"}],"anonymous":false},{"type":"event","name":"TokenUnbound","inputs":[{"name":"token","type":"address","indexed":false,"internalType":"address"}],"anonymous":false},{"type":"error","name":"OwnableInvalidOwner","inputs":[{"name":"owner","type":"address","internalType":"address"}]},{"type":"error","name":"OwnableUnauthorizedAccount","inputs":[{"name":"account","type":"address","internalType":"address"}]},{"type":"error","name":"RuleEngine_AdminWithAddressZeroNotAllowed","inputs":[]},{"type":"error","name":"RuleEngine_RuleInvalidInterface","inputs":[]},{"type":"error","name":"RuleEngine_RulesManagementModule_ArrayIsEmpty","inputs":[]},{"type":"error","name":"RuleEngine_RulesManagementModule_MaxRulesExceeded","inputs":[{"name":"maxRules","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"RuleEngine_RulesManagementModule_MaxRulesZeroNotAllowed","inputs":[]},{"type":"error","name":"RuleEngine_RulesManagementModule_RuleAccountCannotReceivePrivileges","inputs":[]},{"type":"error","name":"RuleEngine_RulesManagementModule_RuleAddressZeroNotAllowed","inputs":[]},{"type":"error","name":"RuleEngine_RulesManagementModule_RuleAlreadyExists","inputs":[]},{"type":"error","name":"RuleEngine_RulesManagementModule_RuleDoNotMatch","inputs":[]},{"type":"error","name":"TokenBinding_InvalidTokenAddress","inputs":[]},{"type":"error","name":"TokenBinding_TokenAlreadyBound","inputs":[]},{"type":"error","name":"TokenBinding_TokenNotBound","inputs":[]},{"type":"error","name":"TokenBinding_UnauthorizedCaller","inputs":[]}],"bytecode":{"object":"0x60a0604052600a600255348015610014575f5ffd5b50604051611fe1380380611fe1833981016040819052610033916102b3565b6001600160a01b03808316608052839082908290829081161561005957610059816100a5565b610063600a61013d565b506001600160a01b03811661009157604051631e4fbdf760e01b81525f600482015260240160405180910390fd5b61009a81610192565b5050505050506102f3565b6001600160a01b0381166100cc5760405163135217db60e21b815260040160405180910390fd5b6100d5816101e3565b6100e060038261020e565b6100fd576040516371b3c56560e11b815260040160405180910390fd5b6040516001600160a01b03821681527f2de35142b19ed5a07796cf30791959c592018f70b1d2d7c460eef8ffe713692b906020015b60405180910390a150565b805f0361015d57604051631e69e71760e21b815260040160405180910390fd5b60028190556040518181527f2292ad4720fff63e2bd104c6b1c0d72c2c729a6001c8ab4bb947cbcc5110986390602001610132565b600680546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b6101ed5f8261022b565b1561020b576040516302925f7360e11b815260040160405180910390fd5b50565b5f610222836001600160a01b03841661024c565b90505b92915050565b6001600160a01b0381165f9081526001830160205260408120541515610222565b5f81815260018301602052604081205461029157508154600181810184555f848152602080822090930184905584548482528286019093526040902091909155610225565b505f610225565b80516001600160a01b03811681146102ae575f5ffd5b919050565b5f5f5f606084860312156102c5575f5ffd5b6102ce84610298565b92506102dc60208501610298565b91506102ea60408501610298565b90509250925092565b608051611cc86103195f395f8181610324015281816103b601526115110152611cc85ff3fe608060405234801561000f575f5ffd5b506004361061021e575f3560e01c80638baf29b41161012a578063d32c7bb5116100b4578063e3c4602c11610079578063e3c4602c14610509578063e46638e61461051c578063e54621d21461052f578063f2fde38b14610537578063f76bf5501461054a575f5ffd5b8063d32c7bb514610480578063d4ce1415146104a5578063db18af6c146104b8578063db75d017146104cb578063df21950f146104f6575f5ffd5b8063b043572e116100fa578063b043572e14610437578063b27aef3a1461043f578063bb4b612114610452578063bc13eacc14610465578063c7c24b181461046d575f5ffd5b80638baf29b4146103ed5780638d2ea772146104005780638da5cb5b14610413578063993e8b9514610424575f5ffd5b806354fd4d50116101ab5780636ae728c61161017b5780636ae728c614610387578063715018a6146103995780637157797f146103a15780637da0a877146103b45780637f4ab1dd146103da575f5ffd5b806354fd4d50146102e6578063572b6c05146103145780635f8dead3146103545780636a3edf2814610367575f5ffd5b80633e5af4ca116101f15780633e5af4ca146102855780633ff5aa021461029857806340db3b50146102ab57806352f6747a146102be57806354e4b945146102d3575f5ffd5b806301ffc9a7146102225780631455d0e71461024a5780633284a9a51461025f5780633a56d6d514610272575b5f5ffd5b6102356102303660046117a5565b610552565b60405190151581526020015b60405180910390f35b61025d610258366004611814565b610598565b005b61025d61026d366004611874565b6105e6565b61025d6102803660046118ab565b610623565b61025d6102933660046118c2565b610637565b61025d6102a6366004611910565b610651565b61025d6102b9366004611910565b610663565b6102c6610675565b604051610241919061192b565b6102356102e1366004611910565b610685565b604080518082019091526009815268332e302e302d72633760b81b60208201525b6040516102419190611976565b610235610322366004611910565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0390811691161490565b61025d6103623660046119ab565b610690565b61036f6106a3565b6040516001600160a01b039091168152602001610241565b6002545b604051908152602001610241565b61025d6106c5565b6102356103af3660046118c2565b6106d8565b7f000000000000000000000000000000000000000000000000000000000000000061036f565b6103076103e83660046119e3565b6106f5565b61025d6103fb3660046119fe565b610700565b61025d61040e3660046119ab565b610713565b6006546001600160a01b031661036f565b610235610432366004611910565b610726565b61025d610732565b61025d61044d366004611814565b610742565b61025d610460366004611a3c565b6107f5565b61038b6108c3565b61025d61047b366004611814565b6108cd565b61049361048e3660046118c2565b610916565b60405160ff9091168152602001610241565b6104936104b33660046119fe565b61092c565b61036f6104c63660046118ab565b610942565b6102356104d9366004611910565b6001600160a01b03165f9081526005602052604090205460ff1690565b61025d610504366004611910565b610964565b61025d610517366004611910565b610975565b61023561052a3660046119fe565b6109b7565b6102c66109d0565b61025d610545366004611910565b6109dc565b61038b600a81565b5f61055c826109f6565b8061057757506001600160e01b031982166307f5828d60e41b145b8061059257506301ffc9a760e01b6001600160e01b03198316145b92915050565b6105a0610a97565b5f5b818110156105e1576105d98383838181106105bf576105bf611a8f565b90506020020160208101906105d49190611910565b610a9f565b6001016105a2565b505050565b6105ee610a97565b6001600160a01b0382166106155760405163135217db60e21b815260040160405180910390fd5b61061f8282610aa8565b5050565b61062b610b06565b61063481610b0e565b50565b61063f610b6a565b61064b84848484610b92565b50505050565b61065a81610c34565b61063481610c3d565b61066c81610c34565b61063481610a9f565b60606106805f610cce565b905090565b5f6105928183610cda565b610698610b6a565b61061f5f8383610cfa565b5f5f6106af6003610d93565b11156106c05761068060035f610d9c565b505f90565b6106cd610da7565b6106d65f610e05565b565b5f806106e686868686610916565b60ff161490505b949350505050565b606061059282610e56565b610708610b6a565b6105e1838383610cfa565b61071b610b6a565b61061f825f83610cfa565b5f610592600383610cda565b61073a610b06565b6106d6610fcb565b61074a610b06565b5f81900361076b576040516359203cb960e01b815260040160405180910390fd5b6002548082111561079b57604051630befc49d60e01b815260040161079291815260200190565b60405180910390fd5b505f6107a65f610d93565b11156107b4576107b4610fcb565b5f5b818110156105e1576107ed8383838181106107d3576107d3611a8f565b90506020020160208101906107e89190611910565b610ffc565b6001016107b6565b6107fd610a97565b5f5b82811015610882575f84848381811061081a5761081a611a8f565b905060200201602081019061082f9190611910565b90506001600160a01b0381166108585760405163135217db60e21b815260040160405180910390fd5b6001600160a01b03165f908152600560205260409020805460ff19168315151790556001016107ff565b507f430881f04f203566ee9b32d6444cf02e1b2a0f17ab6b4263a1ee2074d3d0f4838383836040516108b693929190611aa3565b60405180910390a1505050565b5f6106805f610d93565b6108d5610a97565b5f5b818110156105e15761090e8383838181106108f4576108f4611a8f565b90506020020160208101906109099190611910565b610c3d565b6001016108d7565b5f61092385858585611062565b95945050505050565b5f61093884848461112f565b90505b9392505050565b5f61094c5f610d93565b82101561095d576105925f83610d9c565b505f919050565b61096c610b06565b610634816111f3565b61097d610b06565b6002548061098a5f610d93565b1081906109ad57604051630befc49d60e01b815260040161079291815260200190565b5061061f82610ffc565b5f806109c485858561092c565b60ff1614949350505050565b60606106806003610cce565b6109e4610da7565b6109ed81611250565b61063481611277565b5f6001600160e01b031982166320c49ce760e01b1480610a2657506001600160e01b0319821663157094b960e31b145b80610a4157506001600160e01b031982166378a8de7d60e01b145b80610a5c57506001600160e01b03198216630c51264760e21b145b80610a7757506001600160e01b03198216633235d15f60e11b145b8061059257506001600160e01b03198216637157797f60e01b1492915050565b6106d6610b06565b610634816112b1565b6001600160a01b0382165f81815260056020908152604091829020805460ff191685151590811790915591519182527f407b412a9b6db334d48445ec9bcad46fb50bc4b2e97f73e963e397101957a729910160405180910390a25050565b6106d6610da7565b805f03610b2e57604051631e69e71760e21b815260040160405180910390fd5b60028190556040518181527f2292ad4720fff63e2bd104c6b1c0d72c2c729a6001c8ab4bb947cbcc51109863906020015b60405180910390a150565b610b75600333610cda565b6106d657604051630599c0e960e01b815260040160405180910390fd5b5f610b9c5f610d93565b90505f5b81811015610c2c57610bb25f82610d9c565b604051631f2d7a6560e11b81526001600160a01b03888116600483015287811660248301528681166044830152606482018690529190911690633e5af4ca906084015f604051808303815f87803b158015610c0b575f5ffd5b505af1158015610c1d573d5f5f3e3d5ffd5b50505050806001019050610ba0565b505050505050565b610634816112f9565b6001600160a01b038116610c645760405163135217db60e21b815260040160405180910390fd5b610c6d81611338565b610c78600382611342565b610c95576040516371b3c56560e11b815260040160405180910390fd5b6040516001600160a01b03821681527f2de35142b19ed5a07796cf30791959c592018f70b1d2d7c460eef8ffe713692b90602001610b5f565b60605f61093b83611356565b6001600160a01b03165f9081526001919091016020526040902054151590565b5f610d045f610d93565b90505f5b81811015610d8c57610d1a5f82610d9c565b6040516322ebca6d60e21b81526001600160a01b0387811660048301528681166024830152604482018690529190911690638baf29b4906064015f604051808303815f87803b158015610d6b575f5ffd5b505af1158015610d7d573d5f5f3e3d5ffd5b50505050806001019050610d08565b5050505050565b5f610592825490565b5f61093b83836113af565b610daf6113d5565b6001600160a01b0316610dca6006546001600160a01b031690565b6001600160a01b0316146106d657610de06113d5565b60405163118cdaa760e01b81526001600160a01b039091166004820152602401610792565b600680546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b606060ff8216610e8957505060408051808201909152600d81526c2737a932b9ba3934b1ba34b7b760991b602082015290565b5f610e935f610d93565b90505f5b81811015610f8f575f610eaa8183610d9c565b604051633e822efb60e11b815260ff871660048201529091506001600160a01b03821690637d045df690602401602060405180830381865afa158015610ef2573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f169190611afb565b15610f8657604051637f4ab1dd60e01b815260ff861660048201526001600160a01b03821690637f4ab1dd906024015f60405180830381865afa158015610f5f573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526109239190810190611b2a565b50600101610e97565b505060408051808201909152601881527f556e6b6e6f776e207265737472696374696f6e20636f64650000000000000000602082015292915050565b6040517fdbf61473843cd9be1c9791ce51ef66d0da6c9026d62ba80c1ca433b13fb729b2905f90a16106d65f6113de565b611005816113e7565b61100f5f82611342565b61102c5760405163cc790a4b60e01b815260040160405180910390fd5b6040516001600160a01b038216907f60305ce6c9104acd0969d358f926bf391174340660aaf5e6215261fd6847bf46905f90a250565b5f5f61106d5f610d93565b90505f5b81811015611123575f6110848183610d9c565b60405163d32c7bb560e01b81526001600160a01b038a811660048301528981166024830152888116604483015260648201889052919091169063d32c7bb590608401602060405180830381865afa1580156110e1573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111059190611bdd565b905060ff81161561111a5792506106ed915050565b50600101611071565b505f9695505050505050565b5f5f61113a5f610d93565b90505f5b818110156111e8575f6111518183610d9c565b60405163d4ce141560e01b81526001600160a01b038981166004830152888116602483015260448201889052919091169063d4ce141590606401602060405180830381865afa1580156111a6573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111ca9190611bdd565b905060ff8116156111df57925061093b915050565b5060010161113e565b505f95945050505050565b6111fd5f8261143f565b61121a57604051632cdc3a4160e21b815260040160405180910390fd5b6040516001600160a01b038216907f6d83315c9718799346b67584ec64301b1457e989c8e35a8e2982a7776c04bfc4905f90a250565b61125981610685565b15610634576040516302925f7360e11b815260040160405180910390fd5b61127f610da7565b6001600160a01b0381166112a857604051631e4fbdf760e01b81525f6004820152602401610792565b61063481610e05565b6112ba81611453565b336001600160a01b038216148015906112ea57506001600160a01b0381165f9081526005602052604090205460ff165b1561063457610634815f610aa8565b336001600160a01b03821614801561132857506001600160a01b0381165f9081526005602052604090205460ff165b156113305750565b610634610a97565b6112595f82610cda565b5f61093b836001600160a01b0384166114b4565b6060815f018054806020026020016040519081016040528092919081815260200182805480156113a357602002820191905f5260205f20905b81548152602001906001019080831161138f575b50505050509050919050565b5f825f0182815481106113c4576113c4611a8f565b905f5260205f200154905092915050565b5f610680611500565b6106348161156a565b6113f0816115c3565b6113fb600382610cda565b15611419576040516302925f7360e11b815260040160405180910390fd5b611422816115ea565b61063457604051639952e34360e01b815260040160405180910390fd5b5f61093b836001600160a01b038416611627565b61145e60038261143f565b61147b57604051633477dd1760e01b815260040160405180910390fd5b6040516001600160a01b03821681527f28a4ca7134a3b3f9aff286e79ad3daadb4a06d1b43d037a3a98bdc074edd9b7a90602001610b5f565b5f8181526001830160205260408120546114f957508154600181810184555f848152602080822090930184905584548482528286019093526040902091909155610592565b505f610592565b5f36601480821080159061153c57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031633145b156115625761154f36828403815f611bf8565b61155891611c1f565b60601c9250505090565b339250505090565b5f611573825490565b90505f5b818110156115bc57826001015f845f01838154811061159857611598611a8f565b905f5260205f20015481526020019081526020015f205f9055806001019050611577565b50505f9055565b6001600160a01b0381166106345760405163f9d152fb60e01b815260040160405180910390fd5b5f6115f482611711565b6115ff57505f919050565b611610826358d34ba960e11b611750565b80610592575061059282632497d6cb60e01b611750565b5f8181526001830160205260408120548015611701575f611649600183611c5f565b85549091505f9061165c90600190611c5f565b90508082146116bb575f865f01828154811061167a5761167a611a8f565b905f5260205f200154905080875f01848154811061169a5761169a611a8f565b5f918252602080832090910192909255918252600188019052604090208390555b85548690806116cc576116cc611c7e565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f905560019350505050610592565b5f915050610592565b5092915050565b5f611723826301ffc9a760e01b611750565b1561095d575f8061173c846001600160e01b0319611771565b915091508180156106ed5750159392505050565b5f5f5f61175d8585611771565b915091508180156109235750949350505050565b6301ffc9a760e01b5f818152600483905290819060208260248188617530fa92505f511515601f3d11169150509250929050565b5f602082840312156117b5575f5ffd5b81356001600160e01b03198116811461093b575f5ffd5b5f5f83601f8401126117dc575f5ffd5b50813567ffffffffffffffff8111156117f3575f5ffd5b6020830191508360208260051b850101111561180d575f5ffd5b9250929050565b5f5f60208385031215611825575f5ffd5b823567ffffffffffffffff81111561183b575f5ffd5b611847858286016117cc565b90969095509350505050565b6001600160a01b0381168114610634575f5ffd5b8015158114610634575f5ffd5b5f5f60408385031215611885575f5ffd5b823561189081611853565b915060208301356118a081611867565b809150509250929050565b5f602082840312156118bb575f5ffd5b5035919050565b5f5f5f5f608085870312156118d5575f5ffd5b84356118e081611853565b935060208501356118f081611853565b9250604085013561190081611853565b9396929550929360600135925050565b5f60208284031215611920575f5ffd5b813561093b81611853565b602080825282518282018190525f918401906040840190835b8181101561196b5783516001600160a01b0316835260209384019390920191600101611944565b509095945050505050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b5f5f604083850312156119bc575f5ffd5b82356119c781611853565b946020939093013593505050565b60ff81168114610634575f5ffd5b5f602082840312156119f3575f5ffd5b813561093b816119d5565b5f5f5f60608486031215611a10575f5ffd5b8335611a1b81611853565b92506020840135611a2b81611853565b929592945050506040919091013590565b5f5f5f60408486031215611a4e575f5ffd5b833567ffffffffffffffff811115611a64575f5ffd5b611a70868287016117cc565b9094509250506020840135611a8481611867565b809150509250925092565b634e487b7160e01b5f52603260045260245ffd5b604080825281018390525f8460608301825b86811015611ae5578235611ac881611853565b6001600160a01b0316825260209283019290910190600101611ab5565b5080925050508215156020830152949350505050565b5f60208284031215611b0b575f5ffd5b815161093b81611867565b634e487b7160e01b5f52604160045260245ffd5b5f60208284031215611b3a575f5ffd5b815167ffffffffffffffff811115611b50575f5ffd5b8201601f81018413611b60575f5ffd5b805167ffffffffffffffff811115611b7a57611b7a611b16565b604051601f8201601f19908116603f0116810167ffffffffffffffff81118282101715611ba957611ba9611b16565b604052818152828201602001861015611bc0575f5ffd5b8160208401602083015e5f91810160200191909152949350505050565b5f60208284031215611bed575f5ffd5b815161093b816119d5565b5f5f85851115611c06575f5ffd5b83861115611c12575f5ffd5b5050820193919092039150565b80356bffffffffffffffffffffffff19811690601484101561170a576bffffffffffffffffffffffff1960149490940360031b84901b1690921692915050565b8181038181111561059257634e487b7160e01b5f52601160045260245ffd5b634e487b7160e01b5f52603160045260245ffdfea2646970667358221220c1ef88b17c7886162aa38ab1f802fc53a0a4a25f6ebd61f416c3cd33c31bd49464736f6c63430008250033","sourceMap":"768:1885:33:-:0;;;537:2:80;1188:46:69;;1233:190:33;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;1542:37:15;;;;;1394:6:33;;1402:13;;1394:6;;1402:13;;1101:27:29;;;1097:83;;1144:25;1155:13;1144:10;:25::i;:::-;1279:31;537:2:80;1279:12:29;:31::i;:::-;-1:-1:-1;;;;;;1273:26:10;;1269:95;;1322:31;;-1:-1:-1;;;1322:31:10;;1350:1;1322:31;;;725:51:83;698:18;;1322:31:10;;;;;;;1269:95;1373:32;1392:12;1373:18;:32::i;:::-;1225:187;793:108:32;;1233:190:33;;;768:1885;;4440:400:71;-1:-1:-1;;;;;4510:19:71;;4502:64;;;;-1:-1:-1;;;4502:64:71;;;;;;;;;;;;4576:26;4596:5;4576:19;:26::i;:::-;4743:23;:12;4760:5;4743:16;:23::i;:::-;4735:66;;;;-1:-1:-1;;;4735:66:71;;;;;;;;;;;;4816:17;;-1:-1:-1;;;;;743:32:83;;725:51;;4816:17:71;;713:2:83;698:18;4816:17:71;;;;;;;;4440:400;:::o;6050:225:69:-;6126:9;6139:1;6126:14;6118:82;;;;-1:-1:-1;;;6118:82:69;;;;;;;;;;;;6210:9;:21;;;6246:22;;933:25:83;;;6246:22:69;;921:2:83;906:18;6246:22:69;787:177:83;2912:187:10;3004:6;;;-1:-1:-1;;;;;3020:17:10;;;-1:-1:-1;;;;;;3020:17:10;;;;;;;3052:40;;3004:6;;;3020:17;3004:6;;3052:40;;2985:16;;3052:40;2975:124;2912:187;:::o;9793:195:28:-;9887:22;:6;9903:5;9887:15;:22::i;:::-;9886:23;9878:103;;;;-1:-1:-1;;;9878:103:28;;;;;;;;;;;;9793:195;:::o;16462:150:27:-;16532:4;16555:50;16560:3;-1:-1:-1;;;;;16580:23:27;;16555:4;:50::i;:::-;16548:57;;16462:150;;;;;:::o;17414:165::-;-1:-1:-1;;;;;17547:23:27;;17494:4;5238:21;;;:14;;;:21;;;;;;:26;;17517:55;5142:129;2538:406;2601:4;5238:21;;;:14;;;:21;;;;;;2617:321;;-1:-1:-1;2659:23:27;;;;;;;;:11;:23;;;;;;;;;;;;;2841:18;;2817:21;;;:14;;;:21;;;;;;:42;;;;2873:11;;2617:321;-1:-1:-1;2922:5:27;2915:12;;14:177:83;93:13;;-1:-1:-1;;;;;135:31:83;;125:42;;115:70;;181:1;178;171:12;115:70;14:177;;;:::o;196:378::-;284:6;292;300;353:2;341:9;332:7;328:23;324:32;321:52;;;369:1;366;359:12;321:52;392:40;422:9;392:40;:::i;:::-;382:50;;451:49;496:2;485:9;481:18;451:49;:::i;:::-;441:59;;519:49;564:2;553:9;549:18;519:49;:::i;:::-;509:59;;196:378;;;;;:::o;787:177::-;768:1885:33;;;;;;;;;;;;;;;;;;;;;;","linkReferences":{}},"deployedBytecode":{"object":"0x608060405234801561000f575f5ffd5b506004361061021e575f3560e01c80638baf29b41161012a578063d32c7bb5116100b4578063e3c4602c11610079578063e3c4602c14610509578063e46638e61461051c578063e54621d21461052f578063f2fde38b14610537578063f76bf5501461054a575f5ffd5b8063d32c7bb514610480578063d4ce1415146104a5578063db18af6c146104b8578063db75d017146104cb578063df21950f146104f6575f5ffd5b8063b043572e116100fa578063b043572e14610437578063b27aef3a1461043f578063bb4b612114610452578063bc13eacc14610465578063c7c24b181461046d575f5ffd5b80638baf29b4146103ed5780638d2ea772146104005780638da5cb5b14610413578063993e8b9514610424575f5ffd5b806354fd4d50116101ab5780636ae728c61161017b5780636ae728c614610387578063715018a6146103995780637157797f146103a15780637da0a877146103b45780637f4ab1dd146103da575f5ffd5b806354fd4d50146102e6578063572b6c05146103145780635f8dead3146103545780636a3edf2814610367575f5ffd5b80633e5af4ca116101f15780633e5af4ca146102855780633ff5aa021461029857806340db3b50146102ab57806352f6747a146102be57806354e4b945146102d3575f5ffd5b806301ffc9a7146102225780631455d0e71461024a5780633284a9a51461025f5780633a56d6d514610272575b5f5ffd5b6102356102303660046117a5565b610552565b60405190151581526020015b60405180910390f35b61025d610258366004611814565b610598565b005b61025d61026d366004611874565b6105e6565b61025d6102803660046118ab565b610623565b61025d6102933660046118c2565b610637565b61025d6102a6366004611910565b610651565b61025d6102b9366004611910565b610663565b6102c6610675565b604051610241919061192b565b6102356102e1366004611910565b610685565b604080518082019091526009815268332e302e302d72633760b81b60208201525b6040516102419190611976565b610235610322366004611910565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0390811691161490565b61025d6103623660046119ab565b610690565b61036f6106a3565b6040516001600160a01b039091168152602001610241565b6002545b604051908152602001610241565b61025d6106c5565b6102356103af3660046118c2565b6106d8565b7f000000000000000000000000000000000000000000000000000000000000000061036f565b6103076103e83660046119e3565b6106f5565b61025d6103fb3660046119fe565b610700565b61025d61040e3660046119ab565b610713565b6006546001600160a01b031661036f565b610235610432366004611910565b610726565b61025d610732565b61025d61044d366004611814565b610742565b61025d610460366004611a3c565b6107f5565b61038b6108c3565b61025d61047b366004611814565b6108cd565b61049361048e3660046118c2565b610916565b60405160ff9091168152602001610241565b6104936104b33660046119fe565b61092c565b61036f6104c63660046118ab565b610942565b6102356104d9366004611910565b6001600160a01b03165f9081526005602052604090205460ff1690565b61025d610504366004611910565b610964565b61025d610517366004611910565b610975565b61023561052a3660046119fe565b6109b7565b6102c66109d0565b61025d610545366004611910565b6109dc565b61038b600a81565b5f61055c826109f6565b8061057757506001600160e01b031982166307f5828d60e41b145b8061059257506301ffc9a760e01b6001600160e01b03198316145b92915050565b6105a0610a97565b5f5b818110156105e1576105d98383838181106105bf576105bf611a8f565b90506020020160208101906105d49190611910565b610a9f565b6001016105a2565b505050565b6105ee610a97565b6001600160a01b0382166106155760405163135217db60e21b815260040160405180910390fd5b61061f8282610aa8565b5050565b61062b610b06565b61063481610b0e565b50565b61063f610b6a565b61064b84848484610b92565b50505050565b61065a81610c34565b61063481610c3d565b61066c81610c34565b61063481610a9f565b60606106805f610cce565b905090565b5f6105928183610cda565b610698610b6a565b61061f5f8383610cfa565b5f5f6106af6003610d93565b11156106c05761068060035f610d9c565b505f90565b6106cd610da7565b6106d65f610e05565b565b5f806106e686868686610916565b60ff161490505b949350505050565b606061059282610e56565b610708610b6a565b6105e1838383610cfa565b61071b610b6a565b61061f825f83610cfa565b5f610592600383610cda565b61073a610b06565b6106d6610fcb565b61074a610b06565b5f81900361076b576040516359203cb960e01b815260040160405180910390fd5b6002548082111561079b57604051630befc49d60e01b815260040161079291815260200190565b60405180910390fd5b505f6107a65f610d93565b11156107b4576107b4610fcb565b5f5b818110156105e1576107ed8383838181106107d3576107d3611a8f565b90506020020160208101906107e89190611910565b610ffc565b6001016107b6565b6107fd610a97565b5f5b82811015610882575f84848381811061081a5761081a611a8f565b905060200201602081019061082f9190611910565b90506001600160a01b0381166108585760405163135217db60e21b815260040160405180910390fd5b6001600160a01b03165f908152600560205260409020805460ff19168315151790556001016107ff565b507f430881f04f203566ee9b32d6444cf02e1b2a0f17ab6b4263a1ee2074d3d0f4838383836040516108b693929190611aa3565b60405180910390a1505050565b5f6106805f610d93565b6108d5610a97565b5f5b818110156105e15761090e8383838181106108f4576108f4611a8f565b90506020020160208101906109099190611910565b610c3d565b6001016108d7565b5f61092385858585611062565b95945050505050565b5f61093884848461112f565b90505b9392505050565b5f61094c5f610d93565b82101561095d576105925f83610d9c565b505f919050565b61096c610b06565b610634816111f3565b61097d610b06565b6002548061098a5f610d93565b1081906109ad57604051630befc49d60e01b815260040161079291815260200190565b5061061f82610ffc565b5f806109c485858561092c565b60ff1614949350505050565b60606106806003610cce565b6109e4610da7565b6109ed81611250565b61063481611277565b5f6001600160e01b031982166320c49ce760e01b1480610a2657506001600160e01b0319821663157094b960e31b145b80610a4157506001600160e01b031982166378a8de7d60e01b145b80610a5c57506001600160e01b03198216630c51264760e21b145b80610a7757506001600160e01b03198216633235d15f60e11b145b8061059257506001600160e01b03198216637157797f60e01b1492915050565b6106d6610b06565b610634816112b1565b6001600160a01b0382165f81815260056020908152604091829020805460ff191685151590811790915591519182527f407b412a9b6db334d48445ec9bcad46fb50bc4b2e97f73e963e397101957a729910160405180910390a25050565b6106d6610da7565b805f03610b2e57604051631e69e71760e21b815260040160405180910390fd5b60028190556040518181527f2292ad4720fff63e2bd104c6b1c0d72c2c729a6001c8ab4bb947cbcc51109863906020015b60405180910390a150565b610b75600333610cda565b6106d657604051630599c0e960e01b815260040160405180910390fd5b5f610b9c5f610d93565b90505f5b81811015610c2c57610bb25f82610d9c565b604051631f2d7a6560e11b81526001600160a01b03888116600483015287811660248301528681166044830152606482018690529190911690633e5af4ca906084015f604051808303815f87803b158015610c0b575f5ffd5b505af1158015610c1d573d5f5f3e3d5ffd5b50505050806001019050610ba0565b505050505050565b610634816112f9565b6001600160a01b038116610c645760405163135217db60e21b815260040160405180910390fd5b610c6d81611338565b610c78600382611342565b610c95576040516371b3c56560e11b815260040160405180910390fd5b6040516001600160a01b03821681527f2de35142b19ed5a07796cf30791959c592018f70b1d2d7c460eef8ffe713692b90602001610b5f565b60605f61093b83611356565b6001600160a01b03165f9081526001919091016020526040902054151590565b5f610d045f610d93565b90505f5b81811015610d8c57610d1a5f82610d9c565b6040516322ebca6d60e21b81526001600160a01b0387811660048301528681166024830152604482018690529190911690638baf29b4906064015f604051808303815f87803b158015610d6b575f5ffd5b505af1158015610d7d573d5f5f3e3d5ffd5b50505050806001019050610d08565b5050505050565b5f610592825490565b5f61093b83836113af565b610daf6113d5565b6001600160a01b0316610dca6006546001600160a01b031690565b6001600160a01b0316146106d657610de06113d5565b60405163118cdaa760e01b81526001600160a01b039091166004820152602401610792565b600680546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b606060ff8216610e8957505060408051808201909152600d81526c2737a932b9ba3934b1ba34b7b760991b602082015290565b5f610e935f610d93565b90505f5b81811015610f8f575f610eaa8183610d9c565b604051633e822efb60e11b815260ff871660048201529091506001600160a01b03821690637d045df690602401602060405180830381865afa158015610ef2573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f169190611afb565b15610f8657604051637f4ab1dd60e01b815260ff861660048201526001600160a01b03821690637f4ab1dd906024015f60405180830381865afa158015610f5f573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526109239190810190611b2a565b50600101610e97565b505060408051808201909152601881527f556e6b6e6f776e207265737472696374696f6e20636f64650000000000000000602082015292915050565b6040517fdbf61473843cd9be1c9791ce51ef66d0da6c9026d62ba80c1ca433b13fb729b2905f90a16106d65f6113de565b611005816113e7565b61100f5f82611342565b61102c5760405163cc790a4b60e01b815260040160405180910390fd5b6040516001600160a01b038216907f60305ce6c9104acd0969d358f926bf391174340660aaf5e6215261fd6847bf46905f90a250565b5f5f61106d5f610d93565b90505f5b81811015611123575f6110848183610d9c565b60405163d32c7bb560e01b81526001600160a01b038a811660048301528981166024830152888116604483015260648201889052919091169063d32c7bb590608401602060405180830381865afa1580156110e1573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111059190611bdd565b905060ff81161561111a5792506106ed915050565b50600101611071565b505f9695505050505050565b5f5f61113a5f610d93565b90505f5b818110156111e8575f6111518183610d9c565b60405163d4ce141560e01b81526001600160a01b038981166004830152888116602483015260448201889052919091169063d4ce141590606401602060405180830381865afa1580156111a6573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111ca9190611bdd565b905060ff8116156111df57925061093b915050565b5060010161113e565b505f95945050505050565b6111fd5f8261143f565b61121a57604051632cdc3a4160e21b815260040160405180910390fd5b6040516001600160a01b038216907f6d83315c9718799346b67584ec64301b1457e989c8e35a8e2982a7776c04bfc4905f90a250565b61125981610685565b15610634576040516302925f7360e11b815260040160405180910390fd5b61127f610da7565b6001600160a01b0381166112a857604051631e4fbdf760e01b81525f6004820152602401610792565b61063481610e05565b6112ba81611453565b336001600160a01b038216148015906112ea57506001600160a01b0381165f9081526005602052604090205460ff165b1561063457610634815f610aa8565b336001600160a01b03821614801561132857506001600160a01b0381165f9081526005602052604090205460ff165b156113305750565b610634610a97565b6112595f82610cda565b5f61093b836001600160a01b0384166114b4565b6060815f018054806020026020016040519081016040528092919081815260200182805480156113a357602002820191905f5260205f20905b81548152602001906001019080831161138f575b50505050509050919050565b5f825f0182815481106113c4576113c4611a8f565b905f5260205f200154905092915050565b5f610680611500565b6106348161156a565b6113f0816115c3565b6113fb600382610cda565b15611419576040516302925f7360e11b815260040160405180910390fd5b611422816115ea565b61063457604051639952e34360e01b815260040160405180910390fd5b5f61093b836001600160a01b038416611627565b61145e60038261143f565b61147b57604051633477dd1760e01b815260040160405180910390fd5b6040516001600160a01b03821681527f28a4ca7134a3b3f9aff286e79ad3daadb4a06d1b43d037a3a98bdc074edd9b7a90602001610b5f565b5f8181526001830160205260408120546114f957508154600181810184555f848152602080822090930184905584548482528286019093526040902091909155610592565b505f610592565b5f36601480821080159061153c57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031633145b156115625761154f36828403815f611bf8565b61155891611c1f565b60601c9250505090565b339250505090565b5f611573825490565b90505f5b818110156115bc57826001015f845f01838154811061159857611598611a8f565b905f5260205f20015481526020019081526020015f205f9055806001019050611577565b50505f9055565b6001600160a01b0381166106345760405163f9d152fb60e01b815260040160405180910390fd5b5f6115f482611711565b6115ff57505f919050565b611610826358d34ba960e11b611750565b80610592575061059282632497d6cb60e01b611750565b5f8181526001830160205260408120548015611701575f611649600183611c5f565b85549091505f9061165c90600190611c5f565b90508082146116bb575f865f01828154811061167a5761167a611a8f565b905f5260205f200154905080875f01848154811061169a5761169a611a8f565b5f918252602080832090910192909255918252600188019052604090208390555b85548690806116cc576116cc611c7e565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f905560019350505050610592565b5f915050610592565b5092915050565b5f611723826301ffc9a760e01b611750565b1561095d575f8061173c846001600160e01b0319611771565b915091508180156106ed5750159392505050565b5f5f5f61175d8585611771565b915091508180156109235750949350505050565b6301ffc9a760e01b5f818152600483905290819060208260248188617530fa92505f511515601f3d11169150509250929050565b5f602082840312156117b5575f5ffd5b81356001600160e01b03198116811461093b575f5ffd5b5f5f83601f8401126117dc575f5ffd5b50813567ffffffffffffffff8111156117f3575f5ffd5b6020830191508360208260051b850101111561180d575f5ffd5b9250929050565b5f5f60208385031215611825575f5ffd5b823567ffffffffffffffff81111561183b575f5ffd5b611847858286016117cc565b90969095509350505050565b6001600160a01b0381168114610634575f5ffd5b8015158114610634575f5ffd5b5f5f60408385031215611885575f5ffd5b823561189081611853565b915060208301356118a081611867565b809150509250929050565b5f602082840312156118bb575f5ffd5b5035919050565b5f5f5f5f608085870312156118d5575f5ffd5b84356118e081611853565b935060208501356118f081611853565b9250604085013561190081611853565b9396929550929360600135925050565b5f60208284031215611920575f5ffd5b813561093b81611853565b602080825282518282018190525f918401906040840190835b8181101561196b5783516001600160a01b0316835260209384019390920191600101611944565b509095945050505050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b5f5f604083850312156119bc575f5ffd5b82356119c781611853565b946020939093013593505050565b60ff81168114610634575f5ffd5b5f602082840312156119f3575f5ffd5b813561093b816119d5565b5f5f5f60608486031215611a10575f5ffd5b8335611a1b81611853565b92506020840135611a2b81611853565b929592945050506040919091013590565b5f5f5f60408486031215611a4e575f5ffd5b833567ffffffffffffffff811115611a64575f5ffd5b611a70868287016117cc565b9094509250506020840135611a8481611867565b809150509250925092565b634e487b7160e01b5f52603260045260245ffd5b604080825281018390525f8460608301825b86811015611ae5578235611ac881611853565b6001600160a01b0316825260209283019290910190600101611ab5565b5080925050508215156020830152949350505050565b5f60208284031215611b0b575f5ffd5b815161093b81611867565b634e487b7160e01b5f52604160045260245ffd5b5f60208284031215611b3a575f5ffd5b815167ffffffffffffffff811115611b50575f5ffd5b8201601f81018413611b60575f5ffd5b805167ffffffffffffffff811115611b7a57611b7a611b16565b604051601f8201601f19908116603f0116810167ffffffffffffffff81118282101715611ba957611ba9611b16565b604052818152828201602001861015611bc0575f5ffd5b8160208401602083015e5f91810160200191909152949350505050565b5f60208284031215611bed575f5ffd5b815161093b816119d5565b5f5f85851115611c06575f5ffd5b83861115611c12575f5ffd5b5050820193919092039150565b80356bffffffffffffffffffffffff19811690601484101561170a576bffffffffffffffffffffffff1960149490940360031b84901b1690921692915050565b8181038181111561059257634e487b7160e01b5f52601160045260245ffd5b634e487b7160e01b5f52603160045260245ffdfea2646970667358221220c1ef88b17c7886162aa38ab1f802fc53a0a4a25f6ebd61f416c3cd33c31bd49464736f6c63430008250033","sourceMap":"768:1885:33:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;1556:288:29;;;;;;:::i;:::-;;:::i;:::-;;;470:14:83;;463:22;445:41;;433:2;418:18;1556:288:29;;;;;;;;1872:205:70;;;;;;:::i;:::-;;:::i;:::-;;2125:251;;;;;;:::i;:::-;;:::i;3487:150:69:-;;;;;;:::i;:::-;;:::i;2583:330:28:-;;;;;;:::i;:::-;;:::i;2979:137:71:-;;;;;;:::i;:::-;;:::i;3404:141::-;;;;;;:::i;:::-;;:::i;5029:136:69:-;;;:::i;:::-;;;;;;;:::i;4333:158::-;;;;;;:::i;:::-;;:::i;737:129:72:-;852:7;;;;;;;;;;;;-1:-1:-1;;;852:7:72;;;;737:129;;;;;;;:::i;1874:137:15:-;;;;;;:::i;:::-;1749:17;-1:-1:-1;;;;;1973:31:15;;;;;;;1874:137;3239:155:28;;;;;;:::i;:::-;;:::i;2211:383:68:-;;;:::i;:::-;;;-1:-1:-1;;;;;4963:32:83;;;4945:51;;4933:2;4918:18;2211:383:68;4799:203:83;3949:124:69;4057:9;;3949:124;;;5153:25:83;;;5141:2;5126:18;3949:124:69;5007:177:83;2293:101:10;;;:::i;5266:311:28:-;;;;;;:::i;:::-;;:::i;1666:107:15:-;1749:17;1666:107;;4621:240:28;;;;;;:::i;:::-;;:::i;2982:212::-;;;;;;:::i;:::-;;:::i;3439:161::-;;;;;;:::i;:::-;;:::i;1638:85:10:-;1710:6;;-1:-1:-1;;;;;1710:6:10;1638:85;;3636:133:71;;;;;;:::i;:::-;;:::i;2691:117:69:-;;;:::i;2150:477::-;;;;;;:::i;:::-;;:::i;2424:478:70:-;;;;;;:::i;:::-;;:::i;4137:132:69:-;;;:::i;1623:201:70:-;;;;;;:::i;:::-;;:::i;4289:282:28:-;;;;;;:::i;:::-;;:::i;:::-;;;7269:4:83;7257:17;;;7239:36;;7227:2;7212:18;4289:282:28;7097:184:83;3991:242:28;;;;;;:::i;:::-;;:::i;4555:410:69:-;;;;;;:::i;:::-;;:::i;3001:151:70:-;;;;;;:::i;:::-;-1:-1:-1;;;;;3113:32:70;3090:4;3113:32;;;:25;:32;;;;;;;;;3001:151;3701:133:69;;;;;;:::i;:::-;;:::i;3040:383::-;;;;;;:::i;:::-;;:::i;4925:281:28:-;;;;;;:::i;:::-;;:::i;3200:127:70:-;;;:::i;1127:204:32:-;;;;;;:::i;:::-;;:::i;493:46:80:-;;537:2;493:46;;1556:288:29;1658:4;1681:45;1714:11;1681:32;:45::i;:::-;:103;;;-1:-1:-1;;;;;;;1730:54:29;;-1:-1:-1;;;1730:54:29;1681:103;:156;;;-1:-1:-1;;;;;;;;;;829:40:22;;;1800:37:29;1674:163;1556:288;-1:-1:-1;;1556:288:29:o;1872:205:70:-;2185:26:71;:24;:26::i;:::-;1984:9:70::1;1979:92;1999:17:::0;;::::1;1979:92;;;2037:23;2050:6;;2057:1;2050:9;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;2037:12;:23::i;:::-;2018:3;;1979:92;;;;1872:205:::0;;:::o;2125:251::-;2185:26:71;:24;:26::i;:::-;-1:-1:-1;;;;;2258:19:70;::::1;2250:64;;;;-1:-1:-1::0;;;2250:64:70::1;;;;;;;;;;;;2324:45;2353:5;2360:8;2324:28;:45::i;:::-;2125:251:::0;;:::o;3487:150:69:-;880:24;:22;:24::i;:::-;3607:23:::1;3620:9;3607:12;:23::i;:::-;3487:150:::0;:::o;2583:330:28:-;2002:18:71;:16;:18::i;:::-;2846:60:28::1;2881:7;2890:4;2896:2;2900:5;2846:34;:60::i;:::-;2583:330:::0;;;;:::o;2979:137:71:-;3047:35;3076:5;3047:28;:35::i;:::-;3092:17;3103:5;3092:10;:17::i;3404:141::-;3474:35;3503:5;3474:28;:35::i;:::-;3519:19;3532:5;3519:12;:19::i;5029:136:69:-;5108:16;5143:15;:6;:13;:15::i;:::-;5136:22;;5029:136;:::o;4333:158::-;4430:4;4453:31;4430:4;4477:5;4453:15;:31::i;3239:155:28:-;2002:18:71;:16;:18::i;:::-;3352:35:28::1;3373:1;3377:2;3381:5;3352:12;:35::i;2211:383:68:-:0;2274:7;2321:1;2297:21;:12;:19;:21::i;:::-;:25;2293:295;;;2510:19;:12;2527:1;2510:16;:19::i;2293:295::-;-1:-1:-1;2575:1:68;;2211:383::o;2293:101:10:-;1531:13;:11;:13::i;:::-;2357:30:::1;2384:1;2357:18;:30::i;:::-;2293:101::o:0;5266:311:28:-;5447:4;;5474:55;5504:7;5513:4;5519:2;5523:5;5474:29;:55::i;:::-;:96;;;5467:103;;5266:311;;;;;;;:::o;4621:240::-;4771:13;4807:47;4838:15;4807:30;:47::i;2982:212::-;2002:18:71;:16;:18::i;:::-;3158:29:28::1;3171:4;3177:2;3181:5;3158:12;:29::i;3439:161::-:0;2002:18:71;:16;:18::i;:::-;3556:37:28::1;3569:4;3583:1;3587:5;3556:12;:37::i;3636:133:71:-:0;3711:4;3734:28;:12;3756:5;3734:21;:28::i;2691:117:69:-;794:19;:17;:19::i;:::-;2788:13:::1;:11;:13::i;2150:477::-:0;794:19;:17;:19::i;:::-;2293:1:::1;2276:18:::0;;;2268:76:::1;;;;-1:-1:-1::0;;;2268:76:69::1;;;;;;;;;;;;2379:9;::::0;2362:26;;::::1;;2354:97;;;;-1:-1:-1::0;;;2354:97:69::1;;;;;;5153:25:83::0;;5141:2;5126:18;;5007:177;2354:97:69::1;;;;;;;;;;2483:1;2465:15;:6;:13;:15::i;:::-;:19;2461:63;;;2500:13;:11;:13::i;:::-;2538:9;2533:88;2553:17:::0;;::::1;2533:88;;;2591:19;2600:6;;2607:1;2600:9;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;2591:8;:19::i;:::-;2572:3;;2533:88;;2424:478:70::0;2185:26:71;:24;:26::i;:::-;2607:9:70::1;2602:229;2622:17:::0;;::::1;2602:229;;;2660:13;2676:6;;2683:1;2676:9;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;2660:25:::0;-1:-1:-1;;;;;;2707:19:70;::::1;2699:64;;;;-1:-1:-1::0;;;2699:64:70::1;;;;;;;;;;;;-1:-1:-1::0;;;;;2777:32:70::1;;::::0;;;:25:::1;:32;::::0;;;;:43;;-1:-1:-1;;2777:43:70::1;::::0;::::1;;;::::0;;-1:-1:-1;2641:3:70::1;2602:229;;;;2845:50;2878:6;;2886:8;2845:50;;;;;;;;:::i;:::-;;;;;;;;2424:478:::0;;;:::o;4137:132:69:-;4221:7;4247:15;:6;:13;:15::i;1623:201:70:-;2185:26:71;:24;:26::i;:::-;1733:9:70::1;1728:90;1748:17:::0;;::::1;1728:90;;;1786:21;1797:6;;1804:1;1797:9;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;1786:10;:21::i;:::-;1767:3;;1728:90;;4289:282:28::0;4480:5;4508:56;4539:7;4548:4;4554:2;4558:5;4508:30;:56::i;:::-;4501:63;4289:282;-1:-1:-1;;;;;4289:282:28:o;3991:242::-;4155:5;4183:43;4210:4;4216:2;4220:5;4183:26;:43::i;:::-;4176:50;;3991:242;;;;;;:::o;4555:410:69:-;4647:7;4679:15;:6;:13;:15::i;:::-;4670:6;:24;4666:293;;;4882:18;:6;4893;4882:10;:18::i;4666:293::-;-1:-1:-1;4946:1:69;;4555:410;-1:-1:-1;4555:410:69:o;3701:133::-;794:19;:17;:19::i;:::-;3809:18:::1;3821:5;3809:11;:18::i;3040:383::-:0;794:19;:17;:19::i;:::-;3274:9:::1;::::0;;3301:15:::1;3254:17;3301:13;:15::i;:::-;:27;3380:9;3293:98;;;;;-1:-1:-1::0;;;3293:98:69::1;;;;;;5153:25:83::0;;5141:2;5126:18;;5007:177;3293:98:69::1;;3401:15;3410:5;3401:8;:15::i;4925:281:28:-:0;5089:4;;5116:42;5142:4;5148:2;5152:5;5116:25;:42::i;:::-;:83;;;;4925:281;-1:-1:-1;;;;4925:281:28:o;3200:127:70:-;3264:16;3299:21;:12;:19;:21::i;1127:204:32:-;1531:13:10;:11;:13::i;:::-;1216:63:32::1;1270:8;1216:53;:63::i;:::-;1289:35;1315:8;1289:25;:35::i;11440:599:28:-:0;11533:4;-1:-1:-1;;;;;;11556:61:28;;-1:-1:-1;;;11556:61:28;;:132;;-1:-1:-1;;;;;;;11633:55:28;;-1:-1:-1;;;11633:55:28;11556:132;:214;;;-1:-1:-1;;;;;;;11704:66:28;;-1:-1:-1;;;11704:66:28;11556:214;:298;;;-1:-1:-1;;;;;;;11786:68:28;;-1:-1:-1;;;11786:68:28;11556:298;:391;;;-1:-1:-1;;;;;;;11870:77:28;;-1:-1:-1;;;11870:77:28;11556:391;:476;;;-1:-1:-1;;;;;;;11963:69:28;;-1:-1:-1;;;11963:69:28;11549:483;11440:599;-1:-1:-1;;11440:599:28:o;2998:103:68:-;3070:24;:22;:24::i;2008:174:67:-;2129:46;2169:5;2129:39;:46::i;4883:204:70:-;-1:-1:-1;;;;;4978:32:70;;;;;;:25;:32;;;;;;;;;:43;;-1:-1:-1;;4978:43:70;;;;;;;;;;5036:44;;445:41:83;;;5036:44:70;;418:18:83;5036:44:70;;;;;;;4883:204;;:::o;1603:72:32:-;1531:13:10;:11;:13::i;6050:225:69:-;6126:9;6139:1;6126:14;6118:82;;;;-1:-1:-1;;;6118:82:69;;;;;;;;;;;;6210:9;:21;;;6246:22;;5153:25:83;;;6246:22:69;;5141:2:83;5126:18;6246:22:69;;;;;;;;6050:225;:::o;6902:144:71:-;6970:33;:12;6992:10;6970:21;:33::i;:::-;6962:77;;;;-1:-1:-1;;;6962:77:71;;;;;;;;;;;9164:285:69;9271:19;9293:15;:6;:13;:15::i;:::-;9271:37;-1:-1:-1;9323:9:69;9318:125;9342:11;9338:1;:15;9318:125;;;9380:13;:6;9391:1;9380:10;:13::i;:::-;9374:58;;-1:-1:-1;;;9374:58:69;;-1:-1:-1;;;;;8575:32:83;;;9374:58:69;;;8557:51:83;8644:32;;;8624:18;;;8617:60;8713:32;;;8693:18;;;8686:60;8762:18;;;8755:34;;;9374:32:69;;;;;;;8529:19:83;;9374:58:69;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;9355:3;;;;;9318:125;;;;9261:188;9164:285;;;;:::o;1475:234:67:-;1640:62;1696:5;1640:55;:62::i;4440:400:71:-;-1:-1:-1;;;;;4510:19:71;;4502:64;;;;-1:-1:-1;;;4502:64:71;;;;;;;;;;;;4576:26;4596:5;4576:19;:26::i;:::-;4743:23;:12;4760:5;4743:16;:23::i;:::-;4735:66;;;;-1:-1:-1;;;4735:66:71;;;;;;;;;;;;4816:17;;-1:-1:-1;;;;;4963:32:83;;4945:51;;4816:17:71;;4933:2:83;4918:18;4816:17:71;4799:203:83;19500:273:27;19563:16;19591:22;19616:19;19624:3;19616:7;:19::i;17414:165::-;-1:-1:-1;;;;;17547:23:27;17494:4;5238:21;;;:14;;;;;:21;;;;;;:26;;;17414:165::o;8250:259:69:-;8340:19;8362:15;:6;:13;:15::i;:::-;8340:37;-1:-1:-1;8392:9:69;8387:116;8411:11;8407:1;:15;8387:116;;;8449:13;:6;8460:1;8449:10;:13::i;:::-;8443:49;;-1:-1:-1;;;8443:49:69;;-1:-1:-1;;;;;9020:32:83;;;8443:49:69;;;9002:51:83;9089:32;;;9069:18;;;9062:60;9138:18;;;9131:34;;;8443:32:69;;;;;;;8975:18:83;;8443:49:69;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8424:3;;;;;8387:116;;;;8330:179;8250:259;;;:::o;17660:115:27:-;17723:7;17749:19;17757:3;5434:18;;5352:107;18802:158;18877:7;18927:23;18932:3;18944:5;18927:4;:23::i;1796:162:10:-;1866:12;:10;:12::i;:::-;-1:-1:-1;;;;;1855:23:10;:7;1710:6;;-1:-1:-1;;;;;1710:6:10;;1638:85;1855:7;-1:-1:-1;;;;;1855:23:10;;1851:101;;1928:12;:10;:12::i;:::-;1901:40;;-1:-1:-1;;;1901:40:10;;-1:-1:-1;;;;;4963:32:83;;;1901:40:10;;;4945:51:83;4918:18;;1901:40:10;4799:203:83;2912:187:10;3004:6;;;-1:-1:-1;;;;;3020:17:10;;;-1:-1:-1;;;;;;3020:17:10;;;;;;;3052:40;;3004:6;;;3020:17;3004:6;;3052:40;;2985:16;;3052:40;2975:124;2912:187;:::o;8179:594:28:-;8273:13;8302:56;;;8298:110;;-1:-1:-1;;8381:16:28;;;;;;;;;;;;-1:-1:-1;;;8381:16:28;;;;;8179:594::o;8298:110::-;8417:19;8439:15;:6;:13;:15::i;:::-;8417:37;-1:-1:-1;8469:9:28;8464:267;8488:11;8484:1;:15;8464:267;;;8520:11;8540:13;8520:11;8551:1;8540:10;:13::i;:::-;8572:55;;-1:-1:-1;;;8572:55:28;;7269:4:83;7257:17;;8572:55:28;;;7239:36:83;8520:34:28;;-1:-1:-1;;;;;;8572:38:28;;;;;7212:18:83;;8572:55:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;8568:153;;;8654:52;;-1:-1:-1;;;8654:52:28;;7269:4:83;7257:17;;8654:52:28;;;7239:36:83;-1:-1:-1;;;;;8654:35:28;;;;;7212:18:83;;8654:52:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;8654:52:28;;;;;;;;;;;;:::i;8568:153::-;-1:-1:-1;8501:3:28;;8464:267;;;-1:-1:-1;;8747:19:28;;;;;;;;;;;;;;;;;;8179:594;-1:-1:-1;;8179:594:28:o;5444:98:69:-;5499:12;;;;;;;5521:14;:6;:12;:14::i;6762:312::-;6820:26;6839:5;6820:10;:26::i;:::-;6957;:6;6976:5;6957:10;:26::i;:::-;6949:89;;;;-1:-1:-1;;;6949:89:69;;;;;;;;;;;;7053:14;;-1:-1:-1;;;;;7053:14:69;;;;;;;;6762:312;:::o;6974:537:28:-;7135:5;7156:19;7178:15;:6;:13;:15::i;:::-;7156:37;-1:-1:-1;7208:9:28;7203:248;7227:11;7223:1;:15;7203:248;;;7259:17;7285:13;7259:17;7296:1;7285:10;:13::i;:::-;7279:76;;-1:-1:-1;;;7279:76:28;;-1:-1:-1;;;;;8575:32:83;;;7279:76:28;;;8557:51:83;8644:32;;;8624:18;;;8617:60;8713:32;;;8693:18;;;8686:60;8762:18;;;8755:34;;;7279:50:28;;;;;;;8529:19:83;;7279:76:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;7259:96;-1:-1:-1;7373:15:28;;;;7369:72;;7415:11;-1:-1:-1;7408:18:28;;-1:-1:-1;;7408:18:28;7369:72;-1:-1:-1;7240:3:28;;7203:248;;;-1:-1:-1;7473:30:28;7460:44;6974:537;-1:-1:-1;;;;;;6974:537:28:o;6110:467::-;6218:5;6235:19;6257:15;:6;:13;:15::i;:::-;6235:37;-1:-1:-1;6287:9:28;6282:235;6306:11;6302:1;:15;6282:235;;;6338:17;6364:13;6338:17;6375:1;6364:10;:13::i;:::-;6358:63;;-1:-1:-1;;;6358:63:28;;-1:-1:-1;;;;;9020:32:83;;;6358:63:28;;;9002:51:83;9089:32;;;9069:18;;;9062:60;9138:18;;;9131:34;;;6358:46:28;;;;;;;8975:18:83;;6358:63:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;6338:83;-1:-1:-1;6439:15:28;;;;6435:72;;6481:11;-1:-1:-1;6474:18:28;;-1:-1:-1;;6474:18:28;6435:72;-1:-1:-1;6319:3:28;;6282:235;;;-1:-1:-1;6539:30:28;6526:44;6110:467;-1:-1:-1;;;;;6110:467:28:o;7335:255:69:-;7470:29;:6;7492:5;7470:13;:29::i;:::-;7462:89;;;;-1:-1:-1;;;7462:89:69;;;;;;;;;;;;7566:17;;-1:-1:-1;;;;;7566:17:69;;;;;;;;7335:255;:::o;2022:206:29:-;2120:29;2139:8;2120:12;:29::i;:::-;2119:30;2111:110;;;;-1:-1:-1;;;2111:110:29;;;;;;;;;;;2543:215:10;1531:13;:11;:13::i;:::-;-1:-1:-1;;;;;2627:22:10;::::1;2623:91;;2672:31;::::0;-1:-1:-1;;;2672:31:10;;2700:1:::1;2672:31;::::0;::::1;4945:51:83::0;4918:18;;2672:31:10::1;4799:203:83::0;2623:91:10::1;2723:28;2742:8;2723:18;:28::i;4275:255:70:-:0;4348:38;4380:5;4348:31;:38::i;:::-;4400:10;-1:-1:-1;;;;;4400:19:70;;;;;;:55;;-1:-1:-1;;;;;;4423:32:70;;;;;;:25;:32;;;;;;;;4400:55;4396:128;;;4471:42;4500:5;4507;4471:28;:42::i;5759:223::-;5852:10;-1:-1:-1;;;;;5852:19:70;;;:55;;;;-1:-1:-1;;;;;;5875:32:70;;;;;;:25;:32;;;;;;;;5852:55;5848:92;;;5759:223;:::o;5848:92::-;5949:26;:24;:26::i;9793:195:28:-;9887:22;:6;9903:5;9887:15;:22::i;16462:150:27:-;16532:4;16555:50;16560:3;-1:-1:-1;;;;;16580:23:27;;16555:4;:50::i;6460:109::-;6516:16;6551:3;:11;;6544:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6460:109;;;:::o;5801:119::-;5869:7;5895:3;:11;;5907:5;5895:18;;;;;;;;:::i;:::-;;;;;;;;;5888:25;;5801:119;;;;:::o;1814:154:33:-;1901:14;1934:27;:25;:27::i;17250:83:27:-;17308:18;17315:3;17308:6;:18::i;9061:324:28:-;9137:39;9170:5;9137:32;:39::i;:::-;9195:28;:12;9217:5;9195:21;:28::i;:::-;9194:29;9186:109;;;;-1:-1:-1;;;9186:109:28;;;;;;;;;;;;9313:29;9336:5;9313:22;:29::i;:::-;9305:73;;;;-1:-1:-1;;;9305:73:28;;;;;;;;;;;16780:156:27;16853:4;16876:53;16884:3;-1:-1:-1;;;;;16904:23:27;;16876:7;:53::i;5410:294:71:-;5605:26;:12;5625:5;5605:19;:26::i;:::-;5597:65;;;;-1:-1:-1;;;5597:65:71;;;;;;;;;;;;5678:19;;-1:-1:-1;;;;;4963:32:83;;4945:51;;5678:19:71;;4933:2:83;4918:18;5678:19:71;4799:203:83;2538:406:27;2601:4;5238:21;;;:14;;;:21;;;;;;2617:321;;-1:-1:-1;2659:23:27;;;;;;;;:11;:23;;;;;;;;;;;;;2841:18;;2817:21;;;:14;;;:21;;;;;;:42;;;;2873:11;;2617:321;-1:-1:-1;2922:5:27;2915:12;;2248:471:15;2310:7;2354:8;3609:2;2445:37;;;;;;:71;;-1:-1:-1;1749:17:15;-1:-1:-1;;;;;1973:31:15;2505:10;1973:31;2486:30;2441:272;;;2583:47;:8;2592:36;;;2583:8;;:47;:::i;:::-;2575:56;;;:::i;:::-;2567:65;;2560:72;;;;2248:471;:::o;2441:272::-;735:10:18;2677:25:15;;;;2248:471;:::o;4824:237:27:-;4875:11;4889:12;4897:3;5434:18;;5352:107;4889:12;4875:26;-1:-1:-1;4916:9:27;4911:96;4935:3;4931:1;:7;4911:96;;;4966:3;:14;;:30;4981:3;:11;;4993:1;4981:14;;;;;;;;:::i;:::-;;;;;;;;;4966:30;;;;;;;;;;;4959:37;;;4940:3;;;;;4911:96;;;-1:-1:-1;;5039:11:27;34209:23:16;;2125:251:70:o;9974:164:69:-;-1:-1:-1;;;;;10049:19:69;;10041:90;;;;-1:-1:-1;;;10041:90:69;;;;;;;;;;;10702:397:28;10780:4;10801:35;10830:5;10801:28;:35::i;:::-;10796:79;;-1:-1:-1;10859:5:28;;10702:397;-1:-1:-1;10702:397:28:o;10796:79::-;10891:89;10938:5;-1:-1:-1;;;10891:46:28;:89::i;:::-;:201;;;-1:-1:-1;10996:96:28;11043:5;-1:-1:-1;;;10996:46:28;:96::i;3112:1368:27:-;3178:4;3307:21;;;:14;;;:21;;;;;;3343:13;;3339:1135;;3710:18;3731:12;3742:1;3731:8;:12;:::i;:::-;3777:18;;3710:33;;-1:-1:-1;3757:17:27;;3777:22;;3798:1;;3777:22;:::i;:::-;3757:42;;3832:9;3818:10;:23;3814:378;;3861:17;3881:3;:11;;3893:9;3881:22;;;;;;;;:::i;:::-;;;;;;;;;3861:42;;4028:9;4002:3;:11;;4014:10;4002:23;;;;;;;;:::i;:::-;;;;;;;;;;;;:35;;;;4141:25;;;:14;;;:25;;;;;:36;;;3814:378;4270:17;;:3;;:17;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;4373:3;:14;;:21;4388:5;4373:21;;;;;;;;;;;4366:28;;;4416:4;4409:11;;;;;;;3339:1135;4458:5;4451:12;;;;;3339:1135;3184:1296;3112:1368;;;;:::o;719:528:23:-;783:4;976:68;1009:7;-1:-1:-1;;;976:32:23;:68::i;:::-;972:269;;;1061:12;;1093:52;1115:7;-1:-1:-1;;;;;;1093:21:23;:52::i;:::-;1060:85;;;;1166:7;:21;;;;-1:-1:-1;1177:10:23;;1159:28;-1:-1:-1;;;719:528:23:o;4504:238::-;4606:4;4623:12;4637:14;4655:43;4677:7;4686:11;4655:21;:43::i;:::-;4622:76;;;;4715:7;:20;;;;-1:-1:-1;4726:9:23;4708:27;-1:-1:-1;;;;4504:238:23:o;5198:628::-;-1:-1:-1;;;5310:12:23;5452:22;;;5494:4;5487:25;;;5310:12;;;5581:4;5310:12;5569:4;5310:12;5554:7;5547:5;5536:50;5525:61;;5740:4;5734:11;5727:19;5720:27;5654:4;5636:16;5633:26;5612:198;5599:211;;5438:382;5198:628;;;;;:::o;14:286:83:-;72:6;125:2;113:9;104:7;100:23;96:32;93:52;;;141:1;138;131:12;93:52;167:23;;-1:-1:-1;;;;;;219:32:83;;209:43;;199:71;;266:1;263;256:12;497:367;560:8;570:6;624:3;617:4;609:6;605:17;601:27;591:55;;642:1;639;632:12;591:55;-1:-1:-1;665:20:83;;708:18;697:30;;694:50;;;740:1;737;730:12;694:50;777:4;769:6;765:17;753:29;;837:3;830:4;820:6;817:1;813:14;805:6;801:27;797:38;794:47;791:67;;;854:1;851;844:12;791:67;497:367;;;;;:::o;869:437::-;955:6;963;1016:2;1004:9;995:7;991:23;987:32;984:52;;;1032:1;1029;1022:12;984:52;1072:9;1059:23;1105:18;1097:6;1094:30;1091:50;;;1137:1;1134;1127:12;1091:50;1176:70;1238:7;1229:6;1218:9;1214:22;1176:70;:::i;:::-;1265:8;;1150:96;;-1:-1:-1;869:437:83;-1:-1:-1;;;;869:437:83:o;1311:131::-;-1:-1:-1;;;;;1386:31:83;;1376:42;;1366:70;;1432:1;1429;1422:12;1447:118;1533:5;1526:13;1519:21;1512:5;1509:32;1499:60;;1555:1;1552;1545:12;1570:382;1635:6;1643;1696:2;1684:9;1675:7;1671:23;1667:32;1664:52;;;1712:1;1709;1702:12;1664:52;1751:9;1738:23;1770:31;1795:5;1770:31;:::i;:::-;1820:5;-1:-1:-1;1877:2:83;1862:18;;1849:32;1890:30;1849:32;1890:30;:::i;:::-;1939:7;1929:17;;;1570:382;;;;;:::o;1957:226::-;2016:6;2069:2;2057:9;2048:7;2044:23;2040:32;2037:52;;;2085:1;2082;2075:12;2037:52;-1:-1:-1;2130:23:83;;1957:226;-1:-1:-1;1957:226:83:o;2188:650::-;2274:6;2282;2290;2298;2351:3;2339:9;2330:7;2326:23;2322:33;2319:53;;;2368:1;2365;2358:12;2319:53;2407:9;2394:23;2426:31;2451:5;2426:31;:::i;:::-;2476:5;-1:-1:-1;2533:2:83;2518:18;;2505:32;2546:33;2505:32;2546:33;:::i;:::-;2598:7;-1:-1:-1;2657:2:83;2642:18;;2629:32;2670:33;2629:32;2670:33;:::i;:::-;2188:650;;;;-1:-1:-1;2722:7:83;;2802:2;2787:18;2774:32;;-1:-1:-1;;2188:650:83:o;2843:247::-;2902:6;2955:2;2943:9;2934:7;2930:23;2926:32;2923:52;;;2971:1;2968;2961:12;2923:52;3010:9;2997:23;3029:31;3054:5;3029:31;:::i;3095:637::-;3285:2;3297:21;;;3367:13;;3270:18;;;3389:22;;;3237:4;;3468:15;;;3442:2;3427:18;;;3237:4;3511:195;3525:6;3522:1;3519:13;3511:195;;;3590:13;;-1:-1:-1;;;;;3586:39:83;3574:52;;3655:2;3681:15;;;;3646:12;;;;3622:1;3540:9;3511:195;;;-1:-1:-1;3723:3:83;;3095:637;-1:-1:-1;;;;;3095:637:83:o;4004:418::-;4153:2;4142:9;4135:21;4116:4;4185:6;4179:13;4228:6;4223:2;4212:9;4208:18;4201:34;4287:6;4282:2;4274:6;4270:15;4265:2;4254:9;4250:18;4244:50;4343:1;4338:2;4329:6;4318:9;4314:22;4310:31;4303:42;4413:2;4406;4402:7;4397:2;4389:6;4385:15;4381:29;4370:9;4366:45;4362:54;4354:62;;;4004:418;;;;:::o;4427:367::-;4495:6;4503;4556:2;4544:9;4535:7;4531:23;4527:32;4524:52;;;4572:1;4569;4562:12;4524:52;4611:9;4598:23;4630:31;4655:5;4630:31;:::i;:::-;4680:5;4758:2;4743:18;;;;4730:32;;-1:-1:-1;;;4427:367:83:o;5189:114::-;5273:4;5266:5;5262:16;5255:5;5252:27;5242:55;;5293:1;5290;5283:12;5308:243;5365:6;5418:2;5406:9;5397:7;5393:23;5389:32;5386:52;;;5434:1;5431;5424:12;5386:52;5473:9;5460:23;5492:29;5515:5;5492:29;:::i;5556:508::-;5633:6;5641;5649;5702:2;5690:9;5681:7;5677:23;5673:32;5670:52;;;5718:1;5715;5708:12;5670:52;5757:9;5744:23;5776:31;5801:5;5776:31;:::i;:::-;5826:5;-1:-1:-1;5883:2:83;5868:18;;5855:32;5896:33;5855:32;5896:33;:::i;:::-;5556:508;;5948:7;;-1:-1:-1;;;6028:2:83;6013:18;;;;6000:32;;5556:508::o;6526:566::-;6618:6;6626;6634;6687:2;6675:9;6666:7;6662:23;6658:32;6655:52;;;6703:1;6700;6693:12;6655:52;6743:9;6730:23;6776:18;6768:6;6765:30;6762:50;;;6808:1;6805;6798:12;6762:50;6847:70;6909:7;6900:6;6889:9;6885:22;6847:70;:::i;:::-;6936:8;;-1:-1:-1;6821:96:83;-1:-1:-1;;7021:2:83;7006:18;;6993:32;7034:28;6993:32;7034:28;:::i;:::-;7081:5;7071:15;;;6526:566;;;;;:::o;7286:127::-;7347:10;7342:3;7338:20;7335:1;7328:31;7378:4;7375:1;7368:15;7402:4;7399:1;7392:15;7550:771;7772:2;7784:21;;;7757:18;;7840:22;;;7724:4;7919:6;7893:2;7878:18;;7724:4;7953:281;7967:6;7964:1;7961:13;7953:281;;;8042:6;8029:20;8062:31;8087:5;8062:31;:::i;:::-;-1:-1:-1;;;;;8118:31:83;8106:44;;8179:4;8207:17;;;;8170:14;;;;8146:1;7982:9;7953:281;;;7957:3;8251;8243:11;;;;8306:6;8299:14;8292:22;8285:4;8274:9;8270:20;8263:52;7550:771;;;;;;:::o;9176:245::-;9243:6;9296:2;9284:9;9275:7;9271:23;9267:32;9264:52;;;9312:1;9309;9302:12;9264:52;9344:9;9338:16;9363:28;9385:5;9363:28;:::i;9426:127::-;9487:10;9482:3;9478:20;9475:1;9468:31;9518:4;9515:1;9508:15;9542:4;9539:1;9532:15;9558:935;9638:6;9691:2;9679:9;9670:7;9666:23;9662:32;9659:52;;;9707:1;9704;9697:12;9659:52;9740:9;9734:16;9773:18;9765:6;9762:30;9759:50;;;9805:1;9802;9795:12;9759:50;9828:22;;9881:4;9873:13;;9869:27;-1:-1:-1;9859:55:83;;9910:1;9907;9900:12;9859:55;9943:2;9937:9;9969:18;9961:6;9958:30;9955:56;;;9991:18;;:::i;:::-;10040:2;10034:9;10132:2;10094:17;;-1:-1:-1;;10090:31:83;;;10123:2;10086:40;10082:54;10070:67;;10167:18;10152:34;;10188:22;;;10149:62;10146:88;;;10214:18;;:::i;:::-;10250:2;10243:22;10274;;;10315:15;;;10332:2;10311:24;10308:37;-1:-1:-1;10305:57:83;;;10358:1;10355;10348:12;10305:57;10407:6;10402:2;10398;10394:11;10389:2;10381:6;10377:15;10371:43;10460:1;10434:19;;;10455:2;10430:28;10423:39;;;;10438:6;9558:935;-1:-1:-1;;;;9558:935:83:o;10498:247::-;10566:6;10619:2;10607:9;10598:7;10594:23;10590:32;10587:52;;;10635:1;10632;10625:12;10587:52;10667:9;10661:16;10686:29;10709:5;10686:29;:::i;10750:331::-;10855:9;10866;10908:8;10896:10;10893:24;10890:44;;;10930:1;10927;10920:12;10890:44;10959:6;10949:8;10946:20;10943:40;;;10979:1;10976;10969:12;10943:40;-1:-1:-1;;11005:23:83;;;11050:25;;;;;-1:-1:-1;10750:331:83:o;11086:374::-;11207:19;;-1:-1:-1;;11244:40:83;;;11304:2;11296:11;;11293:161;;;-1:-1:-1;;11366:2:83;11362:12;;;;11359:1;11355:20;11351:58;;;11343:67;11339:105;;;;11086:374;-1:-1:-1;;11086:374:83:o;11465:225::-;11532:9;;;11553:11;;;11550:134;;;11606:10;11601:3;11597:20;11594:1;11587:31;11641:4;11638:1;11631:15;11669:4;11666:1;11659:15;11695:127;11756:10;11751:3;11747:20;11744:1;11737:31;11787:4;11784:1;11777:15;11811:4;11808:1;11801:15","linkReferences":{},"immutableReferences":{"1430":[{"start":804,"length":32},{"start":950,"length":32},{"start":5393,"length":32}]}},"methodIdentifiers":{"DEFAULT_MAX_RULES()":"f76bf550","addRule(address)":"e3c4602c","bindToken(address)":"3ff5aa02","bindTokens(address[])":"c7c24b18","canTransfer(address,address,uint256)":"e46638e6","canTransferFrom(address,address,address,uint256)":"7157797f","clearRules()":"b043572e","containsRule(address)":"54e4b945","created(address,uint256)":"5f8dead3","destroyed(address,uint256)":"8d2ea772","detectTransferRestriction(address,address,uint256)":"d4ce1415","detectTransferRestrictionFrom(address,address,address,uint256)":"d32c7bb5","getTokenBound()":"6a3edf28","getTokenBounds()":"e54621d2","isTokenBound(address)":"993e8b95","isTokenSelfBindingApproved(address)":"db75d017","isTrustedForwarder(address)":"572b6c05","maxRules()":"6ae728c6","messageForTransferRestriction(uint8)":"7f4ab1dd","owner()":"8da5cb5b","removeRule(address)":"df21950f","renounceOwnership()":"715018a6","rule(uint256)":"db18af6c","rules()":"52f6747a","rulesCount()":"bc13eacc","setMaxRules(uint256)":"3a56d6d5","setRules(address[])":"b27aef3a","setTokenSelfBindingApproval(address,bool)":"3284a9a5","setTokenSelfBindingApprovalBatch(address[],bool)":"bb4b6121","supportsInterface(bytes4)":"01ffc9a7","transferOwnership(address)":"f2fde38b","transferred(address,address,address,uint256)":"3e5af4ca","transferred(address,address,uint256)":"8baf29b4","trustedForwarder()":"7da0a877","unbindToken(address)":"40db3b50","unbindTokens(address[])":"1455d0e7","version()":"54fd4d50"},"rawMetadata":"{\"compiler\":{\"version\":\"0.8.37+commit.f401782d\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"forwarderIrrevocable\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenContract\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"OwnableInvalidOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"OwnableUnauthorizedAccount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_AdminWithAddressZeroNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_RuleInvalidInterface\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_RulesManagementModule_ArrayIsEmpty\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"maxRules\",\"type\":\"uint256\"}],\"name\":\"RuleEngine_RulesManagementModule_MaxRulesExceeded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_RulesManagementModule_MaxRulesZeroNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_RulesManagementModule_RuleAccountCannotReceivePrivileges\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_RulesManagementModule_RuleAddressZeroNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_RulesManagementModule_RuleAlreadyExists\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_RulesManagementModule_RuleDoNotMatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TokenBinding_InvalidTokenAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TokenBinding_TokenAlreadyBound\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TokenBinding_TokenNotBound\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TokenBinding_UnauthorizedCaller\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract IRule\",\"name\":\"rule\",\"type\":\"address\"}],\"name\":\"AddRule\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"ClearRules\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract IRule\",\"name\":\"rule\",\"type\":\"address\"}],\"name\":\"RemoveRule\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"maxRules\",\"type\":\"uint256\"}],\"name\":\"SetMaxRules\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"TokenBound\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"tokens\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"TokenSelfBindingApprovalBatchSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"TokenSelfBindingApprovalSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"TokenUnbound\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DEFAULT_MAX_RULES\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IRule\",\"name\":\"rule_\",\"type\":\"address\"}],\"name\":\"addRule\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"bindToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"tokens\",\"type\":\"address[]\"}],\"name\":\"bindTokens\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"canTransfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"canTransferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"clearRules\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IRule\",\"name\":\"rule_\",\"type\":\"address\"}],\"name\":\"containsRule\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"created\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"destroyed\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"detectTransferRestriction\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"detectTransferRestrictionFrom\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTokenBound\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTokenBounds\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"isTokenBound\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"isTokenSelfBindingApproved\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"}],\"name\":\"isTrustedForwarder\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"maxRules\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"restrictionCode\",\"type\":\"uint8\"}],\"name\":\"messageForTransferRestriction\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IRule\",\"name\":\"rule_\",\"type\":\"address\"}],\"name\":\"removeRule\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"ruleId\",\"type\":\"uint256\"}],\"name\":\"rule\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"rules\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"rulesCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"maxRules_\",\"type\":\"uint256\"}],\"name\":\"setMaxRules\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IRule[]\",\"name\":\"rules_\",\"type\":\"address[]\"}],\"name\":\"setRules\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"setTokenSelfBindingApproval\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"tokens\",\"type\":\"address[]\"},{\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"setTokenSelfBindingApprovalBatch\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"transferred\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"transferred\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"trustedForwarder\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"unbindToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"tokens\",\"type\":\"address[]\"}],\"name\":\"unbindTokens\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"version_\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"{RuleEngineOwnable} plus an immutable trusted forwarder: administrative calls (owner-only functions) may be relayed by the forwarder (gasless transactions). Token identity is never resolved through the forwarder: the bound-token gate and token self-binding compare the raw `msg.sender`.\",\"errors\":{\"OwnableInvalidOwner(address)\":[{\"details\":\"The owner is not a valid owner account. (eg. `address(0)`)\"}],\"OwnableUnauthorizedAccount(address)\":[{\"details\":\"The caller account is not authorized to perform an operation.\"}]},\"events\":{\"AddRule(address)\":{\"params\":{\"rule\":\"The address of the rule contract that was added.\"}},\"RemoveRule(address)\":{\"params\":{\"rule\":\"The address of the rule contract that was removed.\"}},\"SetMaxRules(uint256)\":{\"params\":{\"maxRules\":\"The new rule cap.\"}},\"TokenBound(address)\":{\"details\":\"Same declaration as ERC-3643 `TokenBound(address _token)`, which does not index the token. Keep it non-indexed: `indexed` would move `token` from the data to a topic and break consumers decoding with the standard ERC-3643 ABI.\",\"params\":{\"token\":\"The address of the token that was bound.\"}},\"TokenSelfBindingApprovalBatchSet(address[],bool)\":{\"details\":\"`tokens` is the array as passed: it may contain tokens already at `approved` and duplicates, and is empty for an empty batch, so it lists the tokens that were set, not only those that changed. No {TokenSelfBindingApprovalSet} is emitted per token, so a filter on that event's indexed `token` does not see batch updates. `tokens` is not indexed: an indexed array is stored as a hash and cannot be filtered per token.\",\"params\":{\"approved\":\"True if token self-bind/unbind is allowed, false otherwise.\",\"tokens\":\"The token addresses whose self-binding permission was set, as passed to the call.\"}},\"TokenSelfBindingApprovalSet(address,bool)\":{\"details\":\"Emitted on every call, also when `approved` equals the current value. Not emitted by {setTokenSelfBindingApprovalBatch}, which emits {TokenSelfBindingApprovalBatchSet} instead: a consumer reconstructing the approvals, or filtering on `token`, must handle both events, or read {isTokenSelfBindingApproved}, which is authoritative.\",\"params\":{\"approved\":\"True if token self-bind/unbind is allowed, false otherwise.\",\"token\":\"The token address whose self-binding permission was set.\"}},\"TokenUnbound(address)\":{\"details\":\"Same declaration as ERC-3643 `TokenUnbound(address _token)`; kept non-indexed for the same reason as {TokenBound}.\",\"params\":{\"token\":\"The address of the token that was unbound.\"}}},\"kind\":\"dev\",\"methods\":{\"addRule(address)\":{\"details\":\"Reverts when the configured maximum number of rules is already reached. Security convention: do not grant {RULES_MANAGEMENT_ROLE} to rule contracts.\",\"params\":{\"rule_\":\"The IRule contract to add.\"}},\"bindToken(address)\":{\"custom:security-note\":\"\\\"Multi-tenant\\\" means one instance is shared by multiple token contracts. Downstream state (for the RuleEngine: the per-address accounting held by stateful rules) is shared across all bound tokens, so binding tokens from different issuers silently cross-contaminates it. Only bind tokens that are equally trusted and governed together.\",\"details\":\"Authorized by {_authorizeTokenBindingChange}.\",\"params\":{\"token\":\"The address of the token to bind.\"}},\"bindTokens(address[])\":{\"custom:security-note\":\"See {bindToken} for multi-tenant state risks. All tokens bound in this batch share the same downstream state. Only bind tokens that are equally trusted and governed together.\",\"details\":\"Must be restricted by implementation-specific access control. Atomic: reverts if any token is invalid or already bound (or listed twice), and then binds none of them. This deliberately departs from the usual batch convention of skipping elements already in the target state: a binding change is security-relevant, and a token that is already bound in the list is most likely an operator mistake that should stop the whole operation. An empty array is a no-op.\",\"params\":{\"tokens\":\"The token addresses to bind.\"}},\"canTransfer(address,address,uint256)\":{\"details\":\"Don't check the balance and the user's right (access control)\",\"params\":{\"from\":\"The address sending tokens.\",\"to\":\"The address receiving tokens.\",\"value\":\"The amount of tokens to transfer.\"},\"returns\":{\"_0\":\"True if the transfer is valid, false otherwise.\"}},\"canTransferFrom(address,address,address,uint256)\":{\"details\":\"Does not check balances or access rights (Access Control).\",\"params\":{\"from\":\"The source address.\",\"spender\":\"The address performing the transfer.\",\"to\":\"The destination address.\",\"value\":\"The number of tokens to transfer.\"},\"returns\":{\"_0\":\"isCompliant True if the transfer complies with policy.\"}},\"clearRules()\":{\"details\":\"After calling this function, no rules will remain set. Cost is O(n) in the number of configured rules. With the default cap of 10 this is negligible, but a high {maxRules} setting re-exposes unbounded cost here even though per-transfer cost remains bounded.\"},\"constructor\":{\"params\":{\"forwarderIrrevocable\":\"Address of the trusted ERC-2771 forwarder, immutable after construction.\",\"owner_\":\"Address of the initial contract owner (ERC-173).\",\"tokenContract\":\"Token to bind at deployment, or the zero address to bind none.\"}},\"containsRule(address)\":{\"details\":\"Complexity: O(1).\",\"params\":{\"rule_\":\"The IRule contract to check for membership.\"},\"returns\":{\"_0\":\"True if the rule is present, false otherwise.\"}},\"created(address,uint256)\":{\"details\":\"Called by the token contract when new tokens are issued to an account. Reverts if the minting does not comply with the rules.\",\"params\":{\"to\":\"The address receiving the minted tokens.\",\"value\":\"The number of tokens created.\"}},\"destroyed(address,uint256)\":{\"details\":\"Called by the token contract when tokens are redeemed or burned. Reverts if the burning does not comply with the rules.\",\"params\":{\"from\":\"The address whose tokens are being destroyed.\",\"value\":\"The number of tokens destroyed.\"}},\"detectTransferRestriction(address,address,uint256)\":{\"params\":{\"from\":\"the origin address\",\"to\":\"the destination address\",\"value\":\"to transfer\"},\"returns\":{\"_0\":\"The restriction code or REJECTED_CODE_BASE.TRANSFER_OK (0) if the transfer is valid\"}},\"detectTransferRestrictionFrom(address,address,address,uint256)\":{\"details\":\" See {ERC-1404} Add an additionnal argument `spender` This function is where an issuer enforces the restriction logic of their token transfers. Some examples of this might include: - checking if the token recipient is whitelisted, - checking if a sender's tokens are frozen in a lock-up period, etc.\",\"params\":{\"from\":\"The address sending tokens.\",\"spender\":\"The address initiating the delegated transfer.\",\"to\":\"The address receiving tokens.\",\"value\":\"amount of tokens to transfer\"},\"returns\":{\"_0\":\"uint8 restricted code, 0 means the transfer is authorized\"}},\"getTokenBound()\":{\"details\":\"If multiple tokens are supported, consider using getTokenBounds().\",\"returns\":{\"_0\":\"The address of the currently bound token.\"}},\"getTokenBounds()\":{\"details\":\"This operation copies the entire storage set to memory and is mainly intended for off-chain reads.\",\"returns\":{\"_0\":\"An array of bound token addresses.\"}},\"isTokenBound(address)\":{\"details\":\"Complexity: O(1).\",\"params\":{\"token\":\"The token address to verify.\"},\"returns\":{\"_0\":\"True if the token is bound, false otherwise.\"}},\"isTokenSelfBindingApproved(address)\":{\"params\":{\"token\":\"The token address to query.\"},\"returns\":{\"_0\":\"True if self-binding is approved for `token`, false otherwise.\"}},\"isTrustedForwarder(address)\":{\"details\":\"Indicates whether any particular address is the trusted forwarder.\"},\"maxRules()\":{\"returns\":{\"_0\":\"The maximum number of rules that can be configured.\"}},\"messageForTransferRestriction(uint8)\":{\"details\":\"See {ERC-1404} This function is effectively an accessor for the \\\"message\\\", a human-readable explanation as to why a transaction is restricted.\",\"params\":{\"restrictionCode\":\"The restriction code to translate into a message.\"},\"returns\":{\"_0\":\"The human-readable message corresponding to `restrictionCode`.\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"removeRule(address)\":{\"details\":\"Reverts if the provided rule is not found or does not match the stored rule at its index. Complexity: O(1).\",\"params\":{\"rule_\":\"The IRule contract to remove.\"}},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.\"},\"rule(uint256)\":{\"details\":\"Reverts if `ruleId` is out of bounds. Complexity: O(1). Note that there are no guarantees on the ordering of values inside the array, and it may change when more values are added or removed.\",\"params\":{\"ruleId\":\"The index of the desired rule in the array.\"},\"returns\":{\"_0\":\"The address of the corresponding IRule contract, return the `zero address` is out of bounds.\"}},\"rules()\":{\"details\":\"This is a view-only function that does not modify state. This operation will copy the entire storage to memory, which can be quite expensive. This is designed to mostly be used by view accessors that are queried without any gas fees.\",\"returns\":{\"_0\":\"An array of all active rule contract addresses.\"}},\"rulesCount()\":{\"details\":\"Equivalent to the length of the internal rules array. Complexity: O(1)\",\"returns\":{\"_0\":\"The number of active rules.\"}},\"setMaxRules(uint256)\":{\"details\":\"Access control is implementation specific (admin/owner). Setting a very high cap re-exposes unbounded gas cost for administrative operations such as {clearRules} even though normal per-transfer cost remains bounded.\",\"params\":{\"maxRules_\":\"New maximum number of rules.\"}},\"setRules(address[])\":{\"details\":\"Replaces the entire rule set atomically. Reverts if `rules_` is empty. Use {clearRules} to remove all rules explicitly. To transition from one non-empty set to another without an enforcement gap, call this function directly with the new set. Emits {ClearRules} when the existing rule set is non-empty, then emits {AddRule} for each new rule. Off-chain indexers must handle both events to reconstruct state. Security convention: rule contracts should be treated as trusted business logic, but should not also be granted {RULES_MANAGEMENT_ROLE}.\",\"params\":{\"rules_\":\"The array of addresses representing the new rules to be set.\"}},\"setTokenSelfBindingApproval(address,bool)\":{\"details\":\"Must be restricted by implementation-specific access control. An approval stays in force until it is revoked here or until the binding manager unbinds the token ({unbindToken} or {unbindTokens}), which revokes it and emits {TokenSelfBindingApprovalSet} with `false`. A token that unbinds itself keeps its approval, so it can bind itself again later.\",\"params\":{\"approved\":\"Whether self-binding is approved for `token`.\",\"token\":\"The token address to configure.\"}},\"setTokenSelfBindingApprovalBatch(address[],bool)\":{\"details\":\"Must be restricted by implementation-specific access control. Reverts if any token in `tokens` is the zero address. Emits a single {TokenSelfBindingApprovalBatchSet} with the input array, not one {TokenSelfBindingApprovalSet} per token.\",\"params\":{\"approved\":\"Whether self-binding is approved for all provided tokens.\",\"tokens\":\"The token addresses to configure.\"}},\"supportsInterface(bytes4)\":{\"params\":{\"interfaceId\":\"The interface identifier to check.\"},\"returns\":{\"_0\":\"True if the interface is supported, false otherwise.\"}},\"transferOwnership(address)\":{\"details\":\"Reverts when `newOwner` is already configured as a rule.\",\"params\":{\"newOwner\":\"The address of the new owner.\"}},\"transferred(address,address,address,uint256)\":{\"details\":\"Must revert if the transfer is invalid Same name as ERC-3643 but with one supplementary argument `spender` This function can be used to update state variables of the RuleEngine contract This function can be called ONLY by the token contract bound to the RuleEngine Which overload the token calls (since CMTAT v3.3.0): - this 4-argument overload for `transferFrom` (`spender` = approved spender) and for every operation initiated by an operator, with the operator as `spender`: mint (`from == address(0)`), burn (`to == address(0)`), including `burnFrom`, self-burn and cross-chain mint/burn, and the minter `batchTransfer`; - the 3-argument ERC-3643 overload `transferred(from, to, value)`, inherited from {IERC3643IComplianceContract}, only for a direct `transfer`. Up to CMTAT v3.2.0, mint, burn and the minter transfer used the 3-argument overload. WARNING - zero-value calls are permissionless. ERC-20 requires transfers of `0` to be treated as normal transfers, and OpenZeppelin's `_spendAllowance` consumes no allowance when `value == 0`. Any address can therefore call `transferFrom(victim, anyone, 0)` on the token and reach this callback for an arbitrary `from`, with itself as `spender`, without ever having been approved. The token deliberately does not suppress the notification, because doing so would make its compliance notifications inconsistent with its own ERC-20 transfer semantics. Implementations MUST therefore treat `value == 0` as carrying no economic meaning: any stateful rule (cooldown, holding period, quota, tax bucket, counter, holder tracking, ...) MUST be a no-op for a zero value, otherwise an attacker can desynchronize policy state from balances, or keep a holder permanently restricted, at no cost. The same applies to the 3-argument ERC-3643 overload, which a zero-value `transfer(to, 0)` reaches the same way.\",\"params\":{\"from\":\"token holder address\",\"spender\":\"spender address (sender)\",\"to\":\"receiver address\",\"value\":\"value of tokens involved in the transfer; MAY be `0` \\u2014 see the warning above\"}},\"transferred(address,address,uint256)\":{\"details\":\" This function can be used to update state variables of the compliance contract This function can be called ONLY by the token contract bound to the compliance\",\"params\":{\"from\":\"The address of the sender\",\"to\":\"The address of the receiver\",\"value\":\"value of tokens involved in the transfer\"}},\"trustedForwarder()\":{\"details\":\"Returns the address of the trusted forwarder.\"},\"unbindToken(address)\":{\"details\":\"Authorized by {_authorizeTokenBindingChange}. Operator warning: unbinding is an administrative operation and does not erase any state already stored downstream in a previously shared (\\\"multi-tenant\\\") setup.\",\"params\":{\"token\":\"The address of the token to unbind.\"}},\"unbindTokens(address[])\":{\"details\":\"Must be restricted by implementation-specific access control. Atomic: reverts if any token is not currently bound, and then unbinds none of them. Deliberately not the skip-if-already-done batch convention, for the same reason as {bindTokens}. An empty array is a no-op. Like a manager's {unbindToken}, revokes each token's self-binding approval (see {setTokenSelfBindingApproval}).\",\"params\":{\"tokens\":\"The token addresses to unbind.\"}},\"version()\":{\"details\":\"This value is useful to know which smart contract version has been used\",\"returns\":{\"version_\":\"A string representing the version of the token implementation (e.g., \\\"1.0.0\\\").\"}}},\"title\":\"Implementation of a ruleEngine with ERC-173 Ownable access control and ERC-2771\",\"version\":1},\"userdoc\":{\"errors\":{\"TokenBinding_InvalidTokenAddress()\":[{\"notice\":\"Thrown when the zero address is passed as a token to bind or to approve.\"}],\"TokenBinding_TokenAlreadyBound()\":[{\"notice\":\"Thrown when binding a token that is already bound.\"}],\"TokenBinding_TokenNotBound()\":[{\"notice\":\"Thrown when unbinding a token that is not currently bound.\"}],\"TokenBinding_UnauthorizedCaller()\":[{\"notice\":\"Thrown when a caller that is not a bound token calls a bound-token entry point.\"}]},\"events\":{\"AddRule(address)\":{\"notice\":\"Emitted when a new rule is added to the rule set.\"},\"ClearRules()\":{\"notice\":\"Emitted when all rules are cleared from the rule set.\"},\"RemoveRule(address)\":{\"notice\":\"Emitted when a rule is removed from the rule set.\"},\"SetMaxRules(uint256)\":{\"notice\":\"Emitted when the maximum allowed number of rules is updated.\"},\"TokenBound(address)\":{\"notice\":\"Emitted when a token is successfully bound.\"},\"TokenSelfBindingApprovalBatchSet(address[],bool)\":{\"notice\":\"Emitted once by {setTokenSelfBindingApprovalBatch}, with the input array.\"},\"TokenSelfBindingApprovalSet(address,bool)\":{\"notice\":\"Emitted by {setTokenSelfBindingApproval} when self-binding permission is set for a token.\"},\"TokenUnbound(address)\":{\"notice\":\"Emitted when a token is successfully unbound.\"}},\"kind\":\"user\",\"methods\":{\"DEFAULT_MAX_RULES()\":{\"notice\":\"Default upper bound on the number of rules a RuleEngine may hold.\"},\"addRule(address)\":{\"notice\":\"Adds a new rule to the current rule set.\"},\"bindToken(address)\":{\"notice\":\"Binds a token contract, allowing it to call the bound-token entry points.\"},\"bindTokens(address[])\":{\"notice\":\"Binds several token contracts in a single call.\"},\"canTransfer(address,address,uint256)\":{\"notice\":\"Returns true if the transfer is valid, and false otherwise.\"},\"canTransferFrom(address,address,address,uint256)\":{\"notice\":\"Checks if `spender` can transfer `value` tokens from `from` to `to` under compliance rules.\"},\"clearRules()\":{\"notice\":\"Removes all configured rules.\"},\"constructor\":{\"notice\":\"Deploys a RuleEngine with ERC-173 Ownable access control and a trusted forwarder.\"},\"containsRule(address)\":{\"notice\":\"Checks whether a specific rule is currently configured.\"},\"created(address,uint256)\":{\"notice\":\"Updates the compliance contract state when tokens are created (minted).\"},\"destroyed(address,uint256)\":{\"notice\":\"Updates the compliance contract state when tokens are destroyed (burned).\"},\"detectTransferRestriction(address,address,uint256)\":{\"notice\":\"Queries every rule, in order, and returns the first restriction code that is not zero\"},\"detectTransferRestrictionFrom(address,address,address,uint256)\":{\"notice\":\"Returns a uint8 code to indicate if a transfer is restricted or not\"},\"getTokenBound()\":{\"notice\":\"Returns the single token currently bound to this compliance contract.\"},\"getTokenBounds()\":{\"notice\":\"Returns all tokens currently bound.\"},\"isTokenBound(address)\":{\"notice\":\"Checks whether a token is currently bound.\"},\"isTokenSelfBindingApproved(address)\":{\"notice\":\"Returns whether a token is approved to bind and unbind itself.\"},\"maxRules()\":{\"notice\":\"Returns the maximum number of rules allowed in the engine.\"},\"removeRule(address)\":{\"notice\":\"Removes a specific rule from the current rule set.\"},\"rule(uint256)\":{\"notice\":\"Retrieves the rule address at a specific index.\"},\"rules()\":{\"notice\":\"Returns the full list of currently configured rules.\"},\"rulesCount()\":{\"notice\":\"Returns the total number of currently configured rules.\"},\"setMaxRules(uint256)\":{\"notice\":\"Updates the maximum number of rules allowed in the engine.\"},\"setRules(address[])\":{\"notice\":\"Defines the rules for the rule engine.\"},\"setTokenSelfBindingApproval(address,bool)\":{\"notice\":\"Sets whether a token is allowed to bind and unbind itself.\"},\"setTokenSelfBindingApprovalBatch(address[],bool)\":{\"notice\":\"Sets self-binding approval for multiple tokens in one transaction.\"},\"supportsInterface(bytes4)\":{\"notice\":\"ERC-165 interface detection.\"},\"transferOwnership(address)\":{\"notice\":\"Transfers ownership of the contract to a new account (`newOwner`).\"},\"transferred(address,address,address,uint256)\":{\"notice\":\"Function called whenever tokens are transferred from one wallet to another, minted or burned, when the token knows the account that initiated the operation (`spender`).\"},\"transferred(address,address,uint256)\":{\"notice\":\"Function called whenever tokens are transferred from one wallet to another\"},\"unbindToken(address)\":{\"notice\":\"Unbinds a token contract, revoking its access to the bound-token entry points.\"},\"unbindTokens(address[])\":{\"notice\":\"Unbinds several token contracts in a single call.\"},\"version()\":{\"notice\":\"Returns the current version of the token contract.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/deployment/ownable/RuleEngineOwnable2771.sol\":\"RuleEngineOwnable2771\"},\"evmVersion\":\"osaka\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[\":@chainlink/contracts-ccip/=lib/Rules/lib/chainlink-ace/node_modules/@chainlink/contracts-ccip/chains/evm/contracts/\",\":@chainlink/contracts/=lib/Rules/lib/chainlink-ace/node_modules/@chainlink/contracts/\",\":@chainlink/contracts@1.4.0/=lib/Rules/lib/chainlink-doc/node_modules/@chainlink/contracts-1.4.0/\",\":@chainlink/cross-chain-identity/=lib/Rules/lib/chainlink-ace/packages/cross-chain-identity/src/\",\":@chainlink/local/=lib/Rules/lib/chainlink-doc/node_modules/@chainlink/local/\",\":@chainlink/policy-management/=lib/Rules/lib/chainlink-ace/packages/policy-management/src/\",\":@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\":@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\":@openzeppelin/contracts@4.7.3/=lib/Rules/lib/chainlink-doc/node_modules/@openzeppelin/contracts-4.7.3/\",\":@openzeppelin/contracts@4.8.3/=lib/Rules/lib/chainlink-ace/node_modules/@openzeppelin/contracts-4.8.3/\",\":@openzeppelin/contracts@4.9.6/=lib/Rules/lib/chainlink-doc/node_modules/@openzeppelin/contracts-4.9.6/\",\":@openzeppelin/contracts@5.0.2/=lib/Rules/lib/chainlink-ace/node_modules/@openzeppelin/contracts/\",\":@openzeppelin/contracts@5.1.0/=lib/Rules/lib/chainlink-doc/node_modules/@openzeppelin/contracts-5.1.0/\",\":@openzeppelin/contracts@5.3.0/=lib/Rules/lib/chainlink-ace/node_modules/@openzeppelin/contracts-5.3.0/\",\":CMTAT/=lib/CMTAT/contracts/\",\":CMTATv3.0.0/=lib/CMTATv3.0.0/contracts/\",\":ERC-3643/=lib/ERC-3643/contracts/\",\":ERC3643/=lib/Rules/lib/ERC-3643/contracts/\",\":RuleEngine/=lib/Rules/lib/RuleEngine/\",\":Rules/=lib/Rules/\",\":chainlink-ace/=lib/Rules/lib/chainlink-ace/\",\":chainlink-doc/=lib/Rules/lib/\",\":erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/\",\":forge-std/=lib/forge-std/src/\",\":halmos-cheatcodes/=lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/\",\":openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\":openzeppelin-contracts/=lib/openzeppelin-contracts/\"]},\"sources\":{\"lib/CMTAT/contracts/interfaces/engine/IRuleEngine.sol\":{\"keccak256\":\"0xeda899e2e46a9b9c3516acb61a7f7e92ed098928379010655c330da721aaffa7\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://60f8555330fc531dff7d0d71a862696fb286a0ba3290e41efbbbf4dd25947a3c\",\"dweb:/ipfs/QmWvbsBGWPtNMNN2EEedwdzzvQG7NtSj9VD2fmNgqVtCXN\"]},\"lib/CMTAT/contracts/interfaces/technical/IERC5679.sol\":{\"keccak256\":\"0x5bee30750c9a65438469a6c5bd8465e1603eec3aeeb94c07bd64ba3e9ee766e1\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://ef7a5c5f0d47135c97ab5d7456d31e513a71c849ae7f2f5395f860be125c4fbc\",\"dweb:/ipfs/Qmezem3qqSjij6ggyB34wC2S15KrY9fu42oymyS9epAYCQ\"]},\"lib/CMTAT/contracts/interfaces/tokenization/IERC3643Partial.sol\":{\"keccak256\":\"0x5c84c2e2442824e98625c471482fb3c9502f43f4c345e7c0fb07fa549be02e26\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://19071f2d12fb580d37eeee07885461f193568df34f3f69d2c5d65ce655d84435\",\"dweb:/ipfs/QmRqHwC7LksE3YPohMtxFieiPerhWdoDNUUMMLbB4XYvhK\"]},\"lib/CMTAT/contracts/interfaces/tokenization/draft-IERC1404.sol\":{\"keccak256\":\"0xc27cdac182d930a94391d589bdafa15364b6f8d9bf211175781dba661f1c0336\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://b509fa7f3cfd785632569f6ae3bec846aa0beefd73c1d5bde233440cae919f0f\",\"dweb:/ipfs/QmPCAdiEun8gaMqS8KhwPpRZV2zXAPfURRaF4C2KjX5Kby\"]},\"lib/CMTAT/contracts/interfaces/tokenization/draft-IERC7551.sol\":{\"keccak256\":\"0x84b73eb77ec82d6d7b313eff2d87f58d3b795840d004aaa10c611b360b827e30\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://a5b8c99fb3600369065a422d3821ba441dc06fc64f50ce0f33950a76ad82b51b\",\"dweb:/ipfs/QmbviJsZPY3xuLU3cHUWJx11aJCPAuN4WKnCufN4kVLm2U\"]},\"lib/CMTAT/contracts/interfaces/tokenization/draft-IERC7943.sol\":{\"keccak256\":\"0xc69588a72da81057ee278e961e8e3bb61a28d64c3c6cebe494ce00809c1cef15\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://148f117d9c463de441f81e6c0a67e95f1f14a61db209492dd0a1767b5572f21a\",\"dweb:/ipfs/QmUjT5uyJfNSYgUWn5Dxhf6Sx9Y1z8CNf3PuTEaGoAx3za\"]},\"lib/CMTAT/contracts/library/ERC1404ExtendInterfaceId.sol\":{\"keccak256\":\"0xf8268f4eb3a6b2e26c32cf76c5c76b6c17df3385c150f05953538a2472149247\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://05108de7a7ba2a0a67978bdfe8e500360674db6d894f42970bb1016b36639056\",\"dweb:/ipfs/QmRux9Qj1GomATseS6Tyq9uiPPNNipuxg2HjdjnPjgSQds\"]},\"lib/CMTAT/contracts/library/RuleEngineInterfaceId.sol\":{\"keccak256\":\"0x1152a49cba4232d943e295d259eb8a1b216d815067367410a5729a256dae4051\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://470f4435a5e62b0ba0ad70f8657b2db0e4cc3b7f2561772adb944ce010551ee6\",\"dweb:/ipfs/QmXECahRr8rK9XJPZwBCnemLDVPdFvPEBusezhaBqbLBqp\"]},\"lib/openzeppelin-contracts/contracts/access/Ownable.sol\":{\"keccak256\":\"0xff6d0bb2e285473e5311d9d3caacb525ae3538a80758c10649a4d61029b017bb\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://8ed324d3920bb545059d66ab97d43e43ee85fd3bd52e03e401f020afb0b120f6\",\"dweb:/ipfs/QmfEckWLmZkDDcoWrkEvMWhms66xwTLff9DDhegYpvHo1a\"]},\"lib/openzeppelin-contracts/contracts/interfaces/IERC165.sol\":{\"keccak256\":\"0x0afcb7e740d1537b252cb2676f600465ce6938398569f09ba1b9ca240dde2dfc\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://1c299900ac4ec268d4570ecef0d697a3013cd11a6eb74e295ee3fbc945056037\",\"dweb:/ipfs/Qmab9owJoxcA7vJT5XNayCMaUR1qxqj1NDzzisduwaJMcZ\"]},\"lib/openzeppelin-contracts/contracts/metatx/ERC2771Context.sol\":{\"keccak256\":\"0x9695d220b99dcf62910533bdf5d40d4cf6a4e04d5b106b6803a80586486dc7f7\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://83b7aecd65882d8953643dce144efe91367082cc01830c9c4ed3c8a4837fb558\",\"dweb:/ipfs/QmQ5HxGavcCKjuhd8buv177qjG6A4kvxx4pZviceKdspdM\"]},\"lib/openzeppelin-contracts/contracts/utils/Arrays.sol\":{\"keccak256\":\"0x772f0c778626a7bdcbcbabca74b825ae9b9dc89d2a47a98b402b1187fbaa63a4\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://eba1d46e58e8880b45c6d51245dc94585b81d6d7290ca77ef50037a6193ed301\",\"dweb:/ipfs/Qme3CWun5qQACjGEerT2MCvhs6brKGFfJirGnzV1ypKTXA\"]},\"lib/openzeppelin-contracts/contracts/utils/Comparators.sol\":{\"keccak256\":\"0x302eecd8cf323b4690e3494a7d960b3cbce077032ab8ef655b323cdd136cec58\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://49ba706f1bc476d68fe6c1fad75517acea4e9e275be0989b548e292eb3a3eacd\",\"dweb:/ipfs/QmeBpvcdGWzWMKTQESUCEhHgnEQYYATVwPxLMxa6vMT7jC\"]},\"lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"keccak256\":\"0x493033a8d1b176a037b2cc6a04dad01a5c157722049bbecf632ca876224dd4b2\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6a708e8a5bdb1011c2c381c9a5cfd8a9a956d7d0a9dc1bd8bcdaf52f76ef2f12\",\"dweb:/ipfs/Qmax9WHBnVsZP46ZxEMNRQpLQnrdE4dK8LehML1Py8FowF\"]},\"lib/openzeppelin-contracts/contracts/utils/Panic.sol\":{\"keccak256\":\"0xf7fe324703a64fc51702311dc51562d5cb1497734f074e4f483bfb6717572d7a\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c6a5ff4f9fd8649b7ee20800b7fa387d3465bd77cf20c2d1068cd5c98e1ed57a\",\"dweb:/ipfs/QmVSaVJf9FXFhdYEYeCEfjMVHrxDh5qL4CGkxdMWpQCrqG\"]},\"lib/openzeppelin-contracts/contracts/utils/SlotDerivation.sol\":{\"keccak256\":\"0x94045fd4f268edf2b2d01ef119268548c320366d6f5294ad30c1b8f9d4f5225f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://edfda81f426f8948b3834115c21e83c48180e6db0d2a8cd2debb2185ed349337\",\"dweb:/ipfs/QmdYZneFyDAux1BuWQxLAdqtABrGS2k9WYCa7C9dvpKkWv\"]},\"lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol\":{\"keccak256\":\"0xcf74f855663ce2ae00ed8352666b7935f6cddea2932fdf2c3ecd30a9b1cd0e97\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://9f660b1f351b757dfe01438e59888f31f33ded3afcf5cb5b0d9bf9aa6f320a8b\",\"dweb:/ipfs/QmarDJ5hZEgBtCmmrVzEZWjub9769eD686jmzb2XpSU1cM\"]},\"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\":{\"keccak256\":\"0x2d9dc2fe26180f74c11c13663647d38e259e45f95eb88f57b61d2160b0109d3e\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://81233d1f98060113d9922180bb0f14f8335856fe9f339134b09335e9f678c377\",\"dweb:/ipfs/QmWh6R35SarhAn4z2wH8SU456jJSYL2FgucfTFgbHJJN4E\"]},\"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165Checker.sol\":{\"keccak256\":\"0x7c7ad70641a7f8cd44def0857ec97b0e40bfd073b2d6037a5f57ce9527ee9bc5\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://e05c6572dfe769f7aea6f3a8002951cc12d143d980dad29f6c5feedf9408bc14\",\"dweb:/ipfs/QmXM7C8YEptxisZiEefXUrwdXt3zMaCobmkCchxTtDg1oK\"]},\"lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"keccak256\":\"0x8891738ffe910f0cf2da09566928589bf5d63f4524dd734fd9cedbac3274dd5c\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://971f954442df5c2ef5b5ebf1eb245d7105d9fbacc7386ee5c796df1d45b21617\",\"dweb:/ipfs/QmadRjHbkicwqwwh61raUEapaVEtaLMcYbQZWs9gUkgj3u\"]},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"keccak256\":\"0x59973a93b1f983f94e10529f46ca46544a9fec2b5f56fb1390bbe9e0dc79f857\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c55ef8f0b9719790c2ae6f81d80a59ffb89f2f0abe6bc065585bd79edce058c5\",\"dweb:/ipfs/QmNNmCbX9NjPXKqHJN8R1WC2rNeZSQrPZLd6FF6AKLyH5Y\"]},\"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\":{\"keccak256\":\"0xc8cae21c9ae4a46e5162ff9bf5b351d6fa6a6eba72d515f3bc1bdfeda7fdf083\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://ce830ebcf28e31643caba318996db3763c36d52cd0f23798ba83c135355d45e9\",\"dweb:/ipfs/QmdGPcvptHN7UBCbUYBbRX3hiRVRFLRwno8b4uga6uFNif\"]},\"lib/openzeppelin-contracts/contracts/utils/structs/EnumerableSet.sol\":{\"keccak256\":\"0xd553ff8b7d55679f0711f1598600ac292dbd8cfdf4b2419b9cabe4c931172895\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://7905ccb27e2308fd0d90dc1212161003ab6964e1c176593db1ccedef705bcc09\",\"dweb:/ipfs/QmW37vm2PcrWLKnN74sKkvAzqSwntCEfCp4EoSEvbBHWkj\"]},\"src/RuleEngineBase.sol\":{\"keccak256\":\"0xb3d832fa55b615574d80b0e0ad76620ad236aa046523617ed5daa46ae07bf853\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://7be31bf5dbd3fa1be025cdc4b7674b76bf40e1c14ce89ec78f792cb3d7ed804e\",\"dweb:/ipfs/QmPq4xBiB3XwXerWtuonZLGiWHMqvz5tKvjhTh9AiWkbww\"]},\"src/RuleEngineOwnableShared.sol\":{\"keccak256\":\"0xa78493398d8b0554e72def7f14d7439109bd4dbd5e07f1466b40acea2bb7dc02\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://ebd87d69b4f6eb193c5d03476381ac132f9587248422d3306dda95b79fd4e470\",\"dweb:/ipfs/QmWYDLvPWjRcfxdR2KhXAij8U9TrFjeM77fsJRX25jWQmY\"]},\"src/deployment/ownable/RuleEngineOwnable.sol\":{\"keccak256\":\"0x9f34713fce49bbc841ed5f0d24c5b53455359a11d904f7ceb3c7ef210494c6c5\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://71875cc9f3a8f9f35b5ec06273cc1c83a23b2cb775ab2974610ca0dc4ac74945\",\"dweb:/ipfs/QmQUVtngskTrnPjv85BLJhEDxYVwp7WFhBHPBpRL4cvn27\"]},\"src/deployment/ownable/RuleEngineOwnable2771.sol\":{\"keccak256\":\"0x96fb410c95da0baccbd6603c7170ca27e5ac70c46df424aa1b56d2b003da428e\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://766ba437433c84ba105a061734a8c3c00b8e2c765b538b8d66851a6595d1ddca\",\"dweb:/ipfs/QmXqXebApRMp2FhMrhadC7svV74zcGfejfWkEuCdLeuTJq\"]},\"src/interfaces/IERC3643Compliance.sol\":{\"keccak256\":\"0xd0edd6697d67135853576ac6a40cadaffd787cedea98071708bbfb189c7ee5bc\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://4ed3cd3af64fccff17a1f33989cdfbdacbc0e4f32a56de11a072cf9e2277a1f6\",\"dweb:/ipfs/QmenRqRw1Yy39yDv1pJgBmnHtwuZhDdHE4omchL41CjXjb\"]},\"src/interfaces/IERC3643ComplianceExtended.sol\":{\"keccak256\":\"0x4a43bf330c7a904cba110acf52f519718d8409514c377912d5bd063c9d963729\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://c671879c591760ecbc2691e2f24adfb215a658c9fe6eb0c05dd1ca980054e585\",\"dweb:/ipfs/QmdbA19PFpJgHraF46YrcMNzUgswbTRA92atL2Lha63JLY\"]},\"src/interfaces/IRule.sol\":{\"keccak256\":\"0x81580b67f7be09049aa64d93cc1d8d691a87c639adc1cf169dc6073e1e543a5c\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://6f1808c3ed18ef1acbccdd9b30011b6e7220d388cfd66cba40b1ef0b485306a1\",\"dweb:/ipfs/QmcUCQ5MYcf7KTtoeqMKsTutPPSJhNTaK1ntHV21ioS9Fm\"]},\"src/interfaces/IRulesManagementModule.sol\":{\"keccak256\":\"0x082dd58070e83b02f275584afa872c4583ac4ca8ad12eb329fc11301470147f9\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://e2d0ad78dc323881864f406acd44976f5de39cdc97a6c99a724d8458b993e2e2\",\"dweb:/ipfs/QmRFfMbXbdiAYV3vQyNppXG7tHTji6mV1Y5Cu3ZzEQm5ng\"]},\"src/interfaces/ITokenBinding.sol\":{\"keccak256\":\"0x34dfea4e118c966adf867c0899844515566251819b4e4510fd8ee424555493fd\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://1d054ed49874816688a6e71f76d611bbdefd492d122ae386cb804c6f5af677a7\",\"dweb:/ipfs/QmRaYX4aJWYSNWNa1D4Nich3k7hkGM9rTfc9s2XaVqyRjy\"]},\"src/interfaces/ITokenBindingExtended.sol\":{\"keccak256\":\"0x01f3ab56dffce860d03e72d10e9f2d13b6bfc9004cf058c63a0b23e3b226da99\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://521e0c9651632b70d61c4c3bd0b14c6f05d818166fe65dbed8e3253158b7637e\",\"dweb:/ipfs/QmY2xEVvfV1dgtFYw6coHX3Z7Fm7yRhzPaGyt6cYBMVf76\"]},\"src/modules/ERC2771ModuleStandalone.sol\":{\"keccak256\":\"0x2135408cd37646f3a27b4a2cdb6f1b9b622541fed4f4b6311a06f986f6eb75d1\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://82229782c9664a8c039fd5a3ecedca8a827fcec190be6c527c1236c864c0418f\",\"dweb:/ipfs/QmXQmX1BFFupTPB27uJweT1tSc6nce3JXDSDa9Ztpf6cKk\"]},\"src/modules/ERC3643ComplianceExtendedModule.sol\":{\"keccak256\":\"0x6f808b068517e9e15f09fc6a9d4190001ec8c2314a10e27a85a2d43e44c84fb1\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://c62c0b77fdd8b6e7bf7aa5bf8134a78ff024d6489a23f746874a99df38a8a265\",\"dweb:/ipfs/QmV7PG3ZUUzwDs9tpooC3hmBu5e39buJnJ4TRditojJ3hu\"]},\"src/modules/ERC3643ComplianceModule.sol\":{\"keccak256\":\"0x7cda81af8687328ac2089f9d1d78352e0e75d0f70a4ba8e2b3ac82896f22863f\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://50711cb94d69ea63d787a8bb19c38c0b99539029ec8fb957a8eff00880fc11fc\",\"dweb:/ipfs/QmSapDWh5mpvWn1q6JteZisJfVGPrCz47WP2BBrJCccEjV\"]},\"src/modules/RulesManagementModule.sol\":{\"keccak256\":\"0xe4d9425613284e71a5e3d590d5433167a9751d9496f57efa914baa81f493e66d\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://d07a16e6869df86c526ef89e7e359e34a9553dc4288b262abd2979359ecf720e\",\"dweb:/ipfs/QmRy2JEsyhkv1mxv7eFaSbEWN4A3gtpPSUnnV48W2KiV4u\"]},\"src/modules/TokenBindingExtendedModule.sol\":{\"keccak256\":\"0x4e1ca7b2ec78608c3a7960bec7102a1780bdf3ec7ff544b612bafaf738b34d05\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://657bcdd303fd5a7fbe733b283f69d8e8aa73efeeeaf95c0ae7479769ac573693\",\"dweb:/ipfs/QmXiWPrv8pEqvBQck8jxC7NwB1MUdGQfLjihK6etYcZ54j\"]},\"src/modules/TokenBindingModule.sol\":{\"keccak256\":\"0xf65f46311d0078f60c30e3359dca988e39cba45b9eee53a09d618bfa70e6ef9b\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://e8c458ecfd41df5fb4a391e7ef837fd5ed5c999e61ccc0e6b4bd23023a739832\",\"dweb:/ipfs/Qmdsr765aw9fPFN2M9cSCP69o1o41FNCqhrXjHgEXNwbXV\"]},\"src/modules/VersionModule.sol\":{\"keccak256\":\"0x35daf007be8b9bb1cb9196ae2decb3e5ad4b574f6390f8fc010b78796ac42f73\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://b1b29d75e1c5023a0c6cb8c56638a17d855a3fdc051a60b9d2f304b99f7876d2\",\"dweb:/ipfs/QmXSCVjLuViC8916LwNpKtw8hqyH78Ptag3xH1n7F1fY4g\"]},\"src/modules/library/ComplianceInterfaceId.sol\":{\"keccak256\":\"0xd54bed5328e732f753d2886aeaa2761b2d66536d5247d4548e0ac1c83c7a0dac\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://ad695339fdfe72446a69d2dfbe39373affe2f37299ad921e57016069a7bc3592\",\"dweb:/ipfs/QmWathGt3E85hLfy5rrAYdb291W8VoTa4gpGPoxtWGvNNA\"]},\"src/modules/library/ERC1404InterfaceId.sol\":{\"keccak256\":\"0x07dc6905e137096cd0ae88be29b112d0e54a83ddf8ca527a281718010f6abcce\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://9249dce67cb59432bdbc9e49978c6cac0346cda3d3fca97c5a310e0f424e1600\",\"dweb:/ipfs/QmRi5awH3hjwvd3k3td48y5Cf64n1wvX9wCWy6fQLayuKs\"]},\"src/modules/library/OwnableInterfaceId.sol\":{\"keccak256\":\"0xdbe06b3203e21e41d1fd2a3ef373a80727193443dfd981de6821422158015d4f\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://ebe8699ae8af81c5cd82f25a1609d9396d72ae957647c33aaa745aadcdac8d18\",\"dweb:/ipfs/QmV73gwDJPFthn8VspdYE6GsoAcQMAR7TachUK8YrPonuT\"]},\"src/modules/library/RuleEngineInvariantStorage.sol\":{\"keccak256\":\"0x50a212f09f1695662965e5fba643b42a1978bec2a8368abbf43983489c983096\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://6137f01df7630527c985d85d2f7446359c678fcb933b66c55b51f583757b5c4a\",\"dweb:/ipfs/QmeHo47WQm1V99xZHS4soMk68UdtXtZhtWhV3dQC5BtA7u\"]},\"src/modules/library/RuleInterfaceId.sol\":{\"keccak256\":\"0x0d86820eee4c92b21d6704bea8ce7bd2cc1b35f6e4a1ceabbcf2a10f1c6b02ec\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://cfb560cb8588983b8c79a973d03c214a149bf1ac034fa9130ce93f0031a404d7\",\"dweb:/ipfs/Qmc6qt4E4BHdDyLUegCsgxqhf7ZFUiX4ahj8FjM54V7wpY\"]},\"src/modules/library/RulesManagementModuleInvariantStorage.sol\":{\"keccak256\":\"0xb81ea3a54c6e8d47b87d6c3d9fb5aae80c3430021b8cd66d9adeef7f5fc95893\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://cfcbadc2011f60de7189273c278dda1df2218aeeb153bee3b8a93447ec95df21\",\"dweb:/ipfs/Qmem5FqCLEfBJQdJzS7Xzd3zSfyL8Muf9Wv5WvCiBVsqfh\"]},\"src/modules/library/TokenBindingModuleInvariantStorage.sol\":{\"keccak256\":\"0x9bab8e5b265068da356fd46e343a7c6c73776f3964fdeaeff056e8ce104d40a5\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://e2e75d2d52b1e4f5cbb832d194266de9a1b3a8cc2101e875dce43a2664c31a05\",\"dweb:/ipfs/QmUsd5cTPsE89WKm3kTUWsobR9JsBDUY8NdxDU5RPYpvP6\"]}},\"version\":1}","metadata":{"compiler":{"version":"0.8.37+commit.f401782d"},"language":"Solidity","output":{"abi":[{"inputs":[{"internalType":"address","name":"owner_","type":"address"},{"internalType":"address","name":"forwarderIrrevocable","type":"address"},{"internalType":"address","name":"tokenContract","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"type":"error","name":"OwnableInvalidOwner"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"type":"error","name":"OwnableUnauthorizedAccount"},{"inputs":[],"type":"error","name":"RuleEngine_AdminWithAddressZeroNotAllowed"},{"inputs":[],"type":"error","name":"RuleEngine_RuleInvalidInterface"},{"inputs":[],"type":"error","name":"RuleEngine_RulesManagementModule_ArrayIsEmpty"},{"inputs":[{"internalType":"uint256","name":"maxRules","type":"uint256"}],"type":"error","name":"RuleEngine_RulesManagementModule_MaxRulesExceeded"},{"inputs":[],"type":"error","name":"RuleEngine_RulesManagementModule_MaxRulesZeroNotAllowed"},{"inputs":[],"type":"error","name":"RuleEngine_RulesManagementModule_RuleAccountCannotReceivePrivileges"},{"inputs":[],"type":"error","name":"RuleEngine_RulesManagementModule_RuleAddressZeroNotAllowed"},{"inputs":[],"type":"error","name":"RuleEngine_RulesManagementModule_RuleAlreadyExists"},{"inputs":[],"type":"error","name":"RuleEngine_RulesManagementModule_RuleDoNotMatch"},{"inputs":[],"type":"error","name":"TokenBinding_InvalidTokenAddress"},{"inputs":[],"type":"error","name":"TokenBinding_TokenAlreadyBound"},{"inputs":[],"type":"error","name":"TokenBinding_TokenNotBound"},{"inputs":[],"type":"error","name":"TokenBinding_UnauthorizedCaller"},{"inputs":[{"internalType":"contract IRule","name":"rule","type":"address","indexed":true}],"type":"event","name":"AddRule","anonymous":false},{"inputs":[],"type":"event","name":"ClearRules","anonymous":false},{"inputs":[{"internalType":"address","name":"previousOwner","type":"address","indexed":true},{"internalType":"address","name":"newOwner","type":"address","indexed":true}],"type":"event","name":"OwnershipTransferred","anonymous":false},{"inputs":[{"internalType":"contract IRule","name":"rule","type":"address","indexed":true}],"type":"event","name":"RemoveRule","anonymous":false},{"inputs":[{"internalType":"uint256","name":"maxRules","type":"uint256","indexed":false}],"type":"event","name":"SetMaxRules","anonymous":false},{"inputs":[{"internalType":"address","name":"token","type":"address","indexed":false}],"type":"event","name":"TokenBound","anonymous":false},{"inputs":[{"internalType":"address[]","name":"tokens","type":"address[]","indexed":false},{"internalType":"bool","name":"approved","type":"bool","indexed":false}],"type":"event","name":"TokenSelfBindingApprovalBatchSet","anonymous":false},{"inputs":[{"internalType":"address","name":"token","type":"address","indexed":true},{"internalType":"bool","name":"approved","type":"bool","indexed":false}],"type":"event","name":"TokenSelfBindingApprovalSet","anonymous":false},{"inputs":[{"internalType":"address","name":"token","type":"address","indexed":false}],"type":"event","name":"TokenUnbound","anonymous":false},{"inputs":[],"stateMutability":"view","type":"function","name":"DEFAULT_MAX_RULES","outputs":[{"internalType":"uint256","name":"","type":"uint256"}]},{"inputs":[{"internalType":"contract IRule","name":"rule_","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"addRule"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"bindToken"},{"inputs":[{"internalType":"address[]","name":"tokens","type":"address[]"}],"stateMutability":"nonpayable","type":"function","name":"bindTokens"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"view","type":"function","name":"canTransfer","outputs":[{"internalType":"bool","name":"","type":"bool"}]},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"view","type":"function","name":"canTransferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}]},{"inputs":[],"stateMutability":"nonpayable","type":"function","name":"clearRules"},{"inputs":[{"internalType":"contract IRule","name":"rule_","type":"address"}],"stateMutability":"view","type":"function","name":"containsRule","outputs":[{"internalType":"bool","name":"","type":"bool"}]},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"nonpayable","type":"function","name":"created"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"nonpayable","type":"function","name":"destroyed"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"view","type":"function","name":"detectTransferRestriction","outputs":[{"internalType":"uint8","name":"","type":"uint8"}]},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"view","type":"function","name":"detectTransferRestrictionFrom","outputs":[{"internalType":"uint8","name":"","type":"uint8"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"getTokenBound","outputs":[{"internalType":"address","name":"","type":"address"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"getTokenBounds","outputs":[{"internalType":"address[]","name":"","type":"address[]"}]},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"stateMutability":"view","type":"function","name":"isTokenBound","outputs":[{"internalType":"bool","name":"","type":"bool"}]},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"stateMutability":"view","type":"function","name":"isTokenSelfBindingApproved","outputs":[{"internalType":"bool","name":"","type":"bool"}]},{"inputs":[{"internalType":"address","name":"forwarder","type":"address"}],"stateMutability":"view","type":"function","name":"isTrustedForwarder","outputs":[{"internalType":"bool","name":"","type":"bool"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"maxRules","outputs":[{"internalType":"uint256","name":"","type":"uint256"}]},{"inputs":[{"internalType":"uint8","name":"restrictionCode","type":"uint8"}],"stateMutability":"view","type":"function","name":"messageForTransferRestriction","outputs":[{"internalType":"string","name":"","type":"string"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}]},{"inputs":[{"internalType":"contract IRule","name":"rule_","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"removeRule"},{"inputs":[],"stateMutability":"nonpayable","type":"function","name":"renounceOwnership"},{"inputs":[{"internalType":"uint256","name":"ruleId","type":"uint256"}],"stateMutability":"view","type":"function","name":"rule","outputs":[{"internalType":"address","name":"","type":"address"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"rules","outputs":[{"internalType":"address[]","name":"","type":"address[]"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"rulesCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}]},{"inputs":[{"internalType":"uint256","name":"maxRules_","type":"uint256"}],"stateMutability":"nonpayable","type":"function","name":"setMaxRules"},{"inputs":[{"internalType":"contract IRule[]","name":"rules_","type":"address[]"}],"stateMutability":"nonpayable","type":"function","name":"setRules"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"stateMutability":"nonpayable","type":"function","name":"setTokenSelfBindingApproval"},{"inputs":[{"internalType":"address[]","name":"tokens","type":"address[]"},{"internalType":"bool","name":"approved","type":"bool"}],"stateMutability":"nonpayable","type":"function","name":"setTokenSelfBindingApprovalBatch"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"stateMutability":"view","type":"function","name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}]},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"transferOwnership"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"nonpayable","type":"function","name":"transferred"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"nonpayable","type":"function","name":"transferred"},{"inputs":[],"stateMutability":"view","type":"function","name":"trustedForwarder","outputs":[{"internalType":"address","name":"","type":"address"}]},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"unbindToken"},{"inputs":[{"internalType":"address[]","name":"tokens","type":"address[]"}],"stateMutability":"nonpayable","type":"function","name":"unbindTokens"},{"inputs":[],"stateMutability":"view","type":"function","name":"version","outputs":[{"internalType":"string","name":"version_","type":"string"}]}],"devdoc":{"kind":"dev","methods":{"addRule(address)":{"details":"Reverts when the configured maximum number of rules is already reached. Security convention: do not grant {RULES_MANAGEMENT_ROLE} to rule contracts.","params":{"rule_":"The IRule contract to add."}},"bindToken(address)":{"custom:security-note":"\"Multi-tenant\" means one instance is shared by multiple token contracts. Downstream state (for the RuleEngine: the per-address accounting held by stateful rules) is shared across all bound tokens, so binding tokens from different issuers silently cross-contaminates it. Only bind tokens that are equally trusted and governed together.","details":"Authorized by {_authorizeTokenBindingChange}.","params":{"token":"The address of the token to bind."}},"bindTokens(address[])":{"custom:security-note":"See {bindToken} for multi-tenant state risks. All tokens bound in this batch share the same downstream state. Only bind tokens that are equally trusted and governed together.","details":"Must be restricted by implementation-specific access control. Atomic: reverts if any token is invalid or already bound (or listed twice), and then binds none of them. This deliberately departs from the usual batch convention of skipping elements already in the target state: a binding change is security-relevant, and a token that is already bound in the list is most likely an operator mistake that should stop the whole operation. An empty array is a no-op.","params":{"tokens":"The token addresses to bind."}},"canTransfer(address,address,uint256)":{"details":"Don't check the balance and the user's right (access control)","params":{"from":"The address sending tokens.","to":"The address receiving tokens.","value":"The amount of tokens to transfer."},"returns":{"_0":"True if the transfer is valid, false otherwise."}},"canTransferFrom(address,address,address,uint256)":{"details":"Does not check balances or access rights (Access Control).","params":{"from":"The source address.","spender":"The address performing the transfer.","to":"The destination address.","value":"The number of tokens to transfer."},"returns":{"_0":"isCompliant True if the transfer complies with policy."}},"clearRules()":{"details":"After calling this function, no rules will remain set. Cost is O(n) in the number of configured rules. With the default cap of 10 this is negligible, but a high {maxRules} setting re-exposes unbounded cost here even though per-transfer cost remains bounded."},"constructor":{"params":{"forwarderIrrevocable":"Address of the trusted ERC-2771 forwarder, immutable after construction.","owner_":"Address of the initial contract owner (ERC-173).","tokenContract":"Token to bind at deployment, or the zero address to bind none."}},"containsRule(address)":{"details":"Complexity: O(1).","params":{"rule_":"The IRule contract to check for membership."},"returns":{"_0":"True if the rule is present, false otherwise."}},"created(address,uint256)":{"details":"Called by the token contract when new tokens are issued to an account. Reverts if the minting does not comply with the rules.","params":{"to":"The address receiving the minted tokens.","value":"The number of tokens created."}},"destroyed(address,uint256)":{"details":"Called by the token contract when tokens are redeemed or burned. Reverts if the burning does not comply with the rules.","params":{"from":"The address whose tokens are being destroyed.","value":"The number of tokens destroyed."}},"detectTransferRestriction(address,address,uint256)":{"params":{"from":"the origin address","to":"the destination address","value":"to transfer"},"returns":{"_0":"The restriction code or REJECTED_CODE_BASE.TRANSFER_OK (0) if the transfer is valid"}},"detectTransferRestrictionFrom(address,address,address,uint256)":{"details":" See {ERC-1404} Add an additionnal argument `spender` This function is where an issuer enforces the restriction logic of their token transfers. Some examples of this might include: - checking if the token recipient is whitelisted, - checking if a sender's tokens are frozen in a lock-up period, etc.","params":{"from":"The address sending tokens.","spender":"The address initiating the delegated transfer.","to":"The address receiving tokens.","value":"amount of tokens to transfer"},"returns":{"_0":"uint8 restricted code, 0 means the transfer is authorized"}},"getTokenBound()":{"details":"If multiple tokens are supported, consider using getTokenBounds().","returns":{"_0":"The address of the currently bound token."}},"getTokenBounds()":{"details":"This operation copies the entire storage set to memory and is mainly intended for off-chain reads.","returns":{"_0":"An array of bound token addresses."}},"isTokenBound(address)":{"details":"Complexity: O(1).","params":{"token":"The token address to verify."},"returns":{"_0":"True if the token is bound, false otherwise."}},"isTokenSelfBindingApproved(address)":{"params":{"token":"The token address to query."},"returns":{"_0":"True if self-binding is approved for `token`, false otherwise."}},"isTrustedForwarder(address)":{"details":"Indicates whether any particular address is the trusted forwarder."},"maxRules()":{"returns":{"_0":"The maximum number of rules that can be configured."}},"messageForTransferRestriction(uint8)":{"details":"See {ERC-1404} This function is effectively an accessor for the \"message\", a human-readable explanation as to why a transaction is restricted.","params":{"restrictionCode":"The restriction code to translate into a message."},"returns":{"_0":"The human-readable message corresponding to `restrictionCode`."}},"owner()":{"details":"Returns the address of the current owner."},"removeRule(address)":{"details":"Reverts if the provided rule is not found or does not match the stored rule at its index. Complexity: O(1).","params":{"rule_":"The IRule contract to remove."}},"renounceOwnership()":{"details":"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner."},"rule(uint256)":{"details":"Reverts if `ruleId` is out of bounds. Complexity: O(1). Note that there are no guarantees on the ordering of values inside the array, and it may change when more values are added or removed.","params":{"ruleId":"The index of the desired rule in the array."},"returns":{"_0":"The address of the corresponding IRule contract, return the `zero address` is out of bounds."}},"rules()":{"details":"This is a view-only function that does not modify state. This operation will copy the entire storage to memory, which can be quite expensive. This is designed to mostly be used by view accessors that are queried without any gas fees.","returns":{"_0":"An array of all active rule contract addresses."}},"rulesCount()":{"details":"Equivalent to the length of the internal rules array. Complexity: O(1)","returns":{"_0":"The number of active rules."}},"setMaxRules(uint256)":{"details":"Access control is implementation specific (admin/owner). Setting a very high cap re-exposes unbounded gas cost for administrative operations such as {clearRules} even though normal per-transfer cost remains bounded.","params":{"maxRules_":"New maximum number of rules."}},"setRules(address[])":{"details":"Replaces the entire rule set atomically. Reverts if `rules_` is empty. Use {clearRules} to remove all rules explicitly. To transition from one non-empty set to another without an enforcement gap, call this function directly with the new set. Emits {ClearRules} when the existing rule set is non-empty, then emits {AddRule} for each new rule. Off-chain indexers must handle both events to reconstruct state. Security convention: rule contracts should be treated as trusted business logic, but should not also be granted {RULES_MANAGEMENT_ROLE}.","params":{"rules_":"The array of addresses representing the new rules to be set."}},"setTokenSelfBindingApproval(address,bool)":{"details":"Must be restricted by implementation-specific access control. An approval stays in force until it is revoked here or until the binding manager unbinds the token ({unbindToken} or {unbindTokens}), which revokes it and emits {TokenSelfBindingApprovalSet} with `false`. A token that unbinds itself keeps its approval, so it can bind itself again later.","params":{"approved":"Whether self-binding is approved for `token`.","token":"The token address to configure."}},"setTokenSelfBindingApprovalBatch(address[],bool)":{"details":"Must be restricted by implementation-specific access control. Reverts if any token in `tokens` is the zero address. Emits a single {TokenSelfBindingApprovalBatchSet} with the input array, not one {TokenSelfBindingApprovalSet} per token.","params":{"approved":"Whether self-binding is approved for all provided tokens.","tokens":"The token addresses to configure."}},"supportsInterface(bytes4)":{"params":{"interfaceId":"The interface identifier to check."},"returns":{"_0":"True if the interface is supported, false otherwise."}},"transferOwnership(address)":{"details":"Reverts when `newOwner` is already configured as a rule.","params":{"newOwner":"The address of the new owner."}},"transferred(address,address,address,uint256)":{"details":"Must revert if the transfer is invalid Same name as ERC-3643 but with one supplementary argument `spender` This function can be used to update state variables of the RuleEngine contract This function can be called ONLY by the token contract bound to the RuleEngine Which overload the token calls (since CMTAT v3.3.0): - this 4-argument overload for `transferFrom` (`spender` = approved spender) and for every operation initiated by an operator, with the operator as `spender`: mint (`from == address(0)`), burn (`to == address(0)`), including `burnFrom`, self-burn and cross-chain mint/burn, and the minter `batchTransfer`; - the 3-argument ERC-3643 overload `transferred(from, to, value)`, inherited from {IERC3643IComplianceContract}, only for a direct `transfer`. Up to CMTAT v3.2.0, mint, burn and the minter transfer used the 3-argument overload. WARNING - zero-value calls are permissionless. ERC-20 requires transfers of `0` to be treated as normal transfers, and OpenZeppelin's `_spendAllowance` consumes no allowance when `value == 0`. Any address can therefore call `transferFrom(victim, anyone, 0)` on the token and reach this callback for an arbitrary `from`, with itself as `spender`, without ever having been approved. The token deliberately does not suppress the notification, because doing so would make its compliance notifications inconsistent with its own ERC-20 transfer semantics. Implementations MUST therefore treat `value == 0` as carrying no economic meaning: any stateful rule (cooldown, holding period, quota, tax bucket, counter, holder tracking, ...) MUST be a no-op for a zero value, otherwise an attacker can desynchronize policy state from balances, or keep a holder permanently restricted, at no cost. The same applies to the 3-argument ERC-3643 overload, which a zero-value `transfer(to, 0)` reaches the same way.","params":{"from":"token holder address","spender":"spender address (sender)","to":"receiver address","value":"value of tokens involved in the transfer; MAY be `0` — see the warning above"}},"transferred(address,address,uint256)":{"details":" This function can be used to update state variables of the compliance contract This function can be called ONLY by the token contract bound to the compliance","params":{"from":"The address of the sender","to":"The address of the receiver","value":"value of tokens involved in the transfer"}},"trustedForwarder()":{"details":"Returns the address of the trusted forwarder."},"unbindToken(address)":{"details":"Authorized by {_authorizeTokenBindingChange}. Operator warning: unbinding is an administrative operation and does not erase any state already stored downstream in a previously shared (\"multi-tenant\") setup.","params":{"token":"The address of the token to unbind."}},"unbindTokens(address[])":{"details":"Must be restricted by implementation-specific access control. Atomic: reverts if any token is not currently bound, and then unbinds none of them. Deliberately not the skip-if-already-done batch convention, for the same reason as {bindTokens}. An empty array is a no-op. Like a manager's {unbindToken}, revokes each token's self-binding approval (see {setTokenSelfBindingApproval}).","params":{"tokens":"The token addresses to unbind."}},"version()":{"details":"This value is useful to know which smart contract version has been used","returns":{"version_":"A string representing the version of the token implementation (e.g., \"1.0.0\")."}}},"version":1},"userdoc":{"kind":"user","methods":{"DEFAULT_MAX_RULES()":{"notice":"Default upper bound on the number of rules a RuleEngine may hold."},"addRule(address)":{"notice":"Adds a new rule to the current rule set."},"bindToken(address)":{"notice":"Binds a token contract, allowing it to call the bound-token entry points."},"bindTokens(address[])":{"notice":"Binds several token contracts in a single call."},"canTransfer(address,address,uint256)":{"notice":"Returns true if the transfer is valid, and false otherwise."},"canTransferFrom(address,address,address,uint256)":{"notice":"Checks if `spender` can transfer `value` tokens from `from` to `to` under compliance rules."},"clearRules()":{"notice":"Removes all configured rules."},"constructor":{"notice":"Deploys a RuleEngine with ERC-173 Ownable access control and a trusted forwarder."},"containsRule(address)":{"notice":"Checks whether a specific rule is currently configured."},"created(address,uint256)":{"notice":"Updates the compliance contract state when tokens are created (minted)."},"destroyed(address,uint256)":{"notice":"Updates the compliance contract state when tokens are destroyed (burned)."},"detectTransferRestriction(address,address,uint256)":{"notice":"Queries every rule, in order, and returns the first restriction code that is not zero"},"detectTransferRestrictionFrom(address,address,address,uint256)":{"notice":"Returns a uint8 code to indicate if a transfer is restricted or not"},"getTokenBound()":{"notice":"Returns the single token currently bound to this compliance contract."},"getTokenBounds()":{"notice":"Returns all tokens currently bound."},"isTokenBound(address)":{"notice":"Checks whether a token is currently bound."},"isTokenSelfBindingApproved(address)":{"notice":"Returns whether a token is approved to bind and unbind itself."},"maxRules()":{"notice":"Returns the maximum number of rules allowed in the engine."},"removeRule(address)":{"notice":"Removes a specific rule from the current rule set."},"rule(uint256)":{"notice":"Retrieves the rule address at a specific index."},"rules()":{"notice":"Returns the full list of currently configured rules."},"rulesCount()":{"notice":"Returns the total number of currently configured rules."},"setMaxRules(uint256)":{"notice":"Updates the maximum number of rules allowed in the engine."},"setRules(address[])":{"notice":"Defines the rules for the rule engine."},"setTokenSelfBindingApproval(address,bool)":{"notice":"Sets whether a token is allowed to bind and unbind itself."},"setTokenSelfBindingApprovalBatch(address[],bool)":{"notice":"Sets self-binding approval for multiple tokens in one transaction."},"supportsInterface(bytes4)":{"notice":"ERC-165 interface detection."},"transferOwnership(address)":{"notice":"Transfers ownership of the contract to a new account (`newOwner`)."},"transferred(address,address,address,uint256)":{"notice":"Function called whenever tokens are transferred from one wallet to another, minted or burned, when the token knows the account that initiated the operation (`spender`)."},"transferred(address,address,uint256)":{"notice":"Function called whenever tokens are transferred from one wallet to another"},"unbindToken(address)":{"notice":"Unbinds a token contract, revoking its access to the bound-token entry points."},"unbindTokens(address[])":{"notice":"Unbinds several token contracts in a single call."},"version()":{"notice":"Returns the current version of the token contract."}},"version":1}},"settings":{"remappings":["@chainlink/contracts-ccip/=lib/Rules/lib/chainlink-ace/node_modules/@chainlink/contracts-ccip/chains/evm/contracts/","@chainlink/contracts/=lib/Rules/lib/chainlink-ace/node_modules/@chainlink/contracts/","@chainlink/contracts@1.4.0/=lib/Rules/lib/chainlink-doc/node_modules/@chainlink/contracts-1.4.0/","@chainlink/cross-chain-identity/=lib/Rules/lib/chainlink-ace/packages/cross-chain-identity/src/","@chainlink/local/=lib/Rules/lib/chainlink-doc/node_modules/@chainlink/local/","@chainlink/policy-management/=lib/Rules/lib/chainlink-ace/packages/policy-management/src/","@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/","@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/","@openzeppelin/contracts@4.7.3/=lib/Rules/lib/chainlink-doc/node_modules/@openzeppelin/contracts-4.7.3/","@openzeppelin/contracts@4.8.3/=lib/Rules/lib/chainlink-ace/node_modules/@openzeppelin/contracts-4.8.3/","@openzeppelin/contracts@4.9.6/=lib/Rules/lib/chainlink-doc/node_modules/@openzeppelin/contracts-4.9.6/","@openzeppelin/contracts@5.0.2/=lib/Rules/lib/chainlink-ace/node_modules/@openzeppelin/contracts/","@openzeppelin/contracts@5.1.0/=lib/Rules/lib/chainlink-doc/node_modules/@openzeppelin/contracts-5.1.0/","@openzeppelin/contracts@5.3.0/=lib/Rules/lib/chainlink-ace/node_modules/@openzeppelin/contracts-5.3.0/","CMTAT/=lib/CMTAT/contracts/","CMTATv3.0.0/=lib/CMTATv3.0.0/contracts/","ERC-3643/=lib/ERC-3643/contracts/","ERC3643/=lib/Rules/lib/ERC-3643/contracts/","RuleEngine/=lib/Rules/lib/RuleEngine/","Rules/=lib/Rules/","chainlink-ace/=lib/Rules/lib/chainlink-ace/","chainlink-doc/=lib/Rules/lib/","erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/","forge-std/=lib/forge-std/src/","halmos-cheatcodes/=lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/","openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/","openzeppelin-contracts/=lib/openzeppelin-contracts/"],"optimizer":{"enabled":true,"runs":200},"metadata":{"bytecodeHash":"ipfs"},"compilationTarget":{"src/deployment/ownable/RuleEngineOwnable2771.sol":"RuleEngineOwnable2771"},"evmVersion":"osaka","libraries":{}},"sources":{"lib/CMTAT/contracts/interfaces/engine/IRuleEngine.sol":{"keccak256":"0xeda899e2e46a9b9c3516acb61a7f7e92ed098928379010655c330da721aaffa7","urls":["bzz-raw://60f8555330fc531dff7d0d71a862696fb286a0ba3290e41efbbbf4dd25947a3c","dweb:/ipfs/QmWvbsBGWPtNMNN2EEedwdzzvQG7NtSj9VD2fmNgqVtCXN"],"license":"MPL-2.0"},"lib/CMTAT/contracts/interfaces/technical/IERC5679.sol":{"keccak256":"0x5bee30750c9a65438469a6c5bd8465e1603eec3aeeb94c07bd64ba3e9ee766e1","urls":["bzz-raw://ef7a5c5f0d47135c97ab5d7456d31e513a71c849ae7f2f5395f860be125c4fbc","dweb:/ipfs/Qmezem3qqSjij6ggyB34wC2S15KrY9fu42oymyS9epAYCQ"],"license":"MPL-2.0"},"lib/CMTAT/contracts/interfaces/tokenization/IERC3643Partial.sol":{"keccak256":"0x5c84c2e2442824e98625c471482fb3c9502f43f4c345e7c0fb07fa549be02e26","urls":["bzz-raw://19071f2d12fb580d37eeee07885461f193568df34f3f69d2c5d65ce655d84435","dweb:/ipfs/QmRqHwC7LksE3YPohMtxFieiPerhWdoDNUUMMLbB4XYvhK"],"license":"MPL-2.0"},"lib/CMTAT/contracts/interfaces/tokenization/draft-IERC1404.sol":{"keccak256":"0xc27cdac182d930a94391d589bdafa15364b6f8d9bf211175781dba661f1c0336","urls":["bzz-raw://b509fa7f3cfd785632569f6ae3bec846aa0beefd73c1d5bde233440cae919f0f","dweb:/ipfs/QmPCAdiEun8gaMqS8KhwPpRZV2zXAPfURRaF4C2KjX5Kby"],"license":"MPL-2.0"},"lib/CMTAT/contracts/interfaces/tokenization/draft-IERC7551.sol":{"keccak256":"0x84b73eb77ec82d6d7b313eff2d87f58d3b795840d004aaa10c611b360b827e30","urls":["bzz-raw://a5b8c99fb3600369065a422d3821ba441dc06fc64f50ce0f33950a76ad82b51b","dweb:/ipfs/QmbviJsZPY3xuLU3cHUWJx11aJCPAuN4WKnCufN4kVLm2U"],"license":"MPL-2.0"},"lib/CMTAT/contracts/interfaces/tokenization/draft-IERC7943.sol":{"keccak256":"0xc69588a72da81057ee278e961e8e3bb61a28d64c3c6cebe494ce00809c1cef15","urls":["bzz-raw://148f117d9c463de441f81e6c0a67e95f1f14a61db209492dd0a1767b5572f21a","dweb:/ipfs/QmUjT5uyJfNSYgUWn5Dxhf6Sx9Y1z8CNf3PuTEaGoAx3za"],"license":"MPL-2.0"},"lib/CMTAT/contracts/library/ERC1404ExtendInterfaceId.sol":{"keccak256":"0xf8268f4eb3a6b2e26c32cf76c5c76b6c17df3385c150f05953538a2472149247","urls":["bzz-raw://05108de7a7ba2a0a67978bdfe8e500360674db6d894f42970bb1016b36639056","dweb:/ipfs/QmRux9Qj1GomATseS6Tyq9uiPPNNipuxg2HjdjnPjgSQds"],"license":"MPL-2.0"},"lib/CMTAT/contracts/library/RuleEngineInterfaceId.sol":{"keccak256":"0x1152a49cba4232d943e295d259eb8a1b216d815067367410a5729a256dae4051","urls":["bzz-raw://470f4435a5e62b0ba0ad70f8657b2db0e4cc3b7f2561772adb944ce010551ee6","dweb:/ipfs/QmXECahRr8rK9XJPZwBCnemLDVPdFvPEBusezhaBqbLBqp"],"license":"MPL-2.0"},"lib/openzeppelin-contracts/contracts/access/Ownable.sol":{"keccak256":"0xff6d0bb2e285473e5311d9d3caacb525ae3538a80758c10649a4d61029b017bb","urls":["bzz-raw://8ed324d3920bb545059d66ab97d43e43ee85fd3bd52e03e401f020afb0b120f6","dweb:/ipfs/QmfEckWLmZkDDcoWrkEvMWhms66xwTLff9DDhegYpvHo1a"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/interfaces/IERC165.sol":{"keccak256":"0x0afcb7e740d1537b252cb2676f600465ce6938398569f09ba1b9ca240dde2dfc","urls":["bzz-raw://1c299900ac4ec268d4570ecef0d697a3013cd11a6eb74e295ee3fbc945056037","dweb:/ipfs/Qmab9owJoxcA7vJT5XNayCMaUR1qxqj1NDzzisduwaJMcZ"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/metatx/ERC2771Context.sol":{"keccak256":"0x9695d220b99dcf62910533bdf5d40d4cf6a4e04d5b106b6803a80586486dc7f7","urls":["bzz-raw://83b7aecd65882d8953643dce144efe91367082cc01830c9c4ed3c8a4837fb558","dweb:/ipfs/QmQ5HxGavcCKjuhd8buv177qjG6A4kvxx4pZviceKdspdM"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/Arrays.sol":{"keccak256":"0x772f0c778626a7bdcbcbabca74b825ae9b9dc89d2a47a98b402b1187fbaa63a4","urls":["bzz-raw://eba1d46e58e8880b45c6d51245dc94585b81d6d7290ca77ef50037a6193ed301","dweb:/ipfs/Qme3CWun5qQACjGEerT2MCvhs6brKGFfJirGnzV1ypKTXA"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/Comparators.sol":{"keccak256":"0x302eecd8cf323b4690e3494a7d960b3cbce077032ab8ef655b323cdd136cec58","urls":["bzz-raw://49ba706f1bc476d68fe6c1fad75517acea4e9e275be0989b548e292eb3a3eacd","dweb:/ipfs/QmeBpvcdGWzWMKTQESUCEhHgnEQYYATVwPxLMxa6vMT7jC"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/Context.sol":{"keccak256":"0x493033a8d1b176a037b2cc6a04dad01a5c157722049bbecf632ca876224dd4b2","urls":["bzz-raw://6a708e8a5bdb1011c2c381c9a5cfd8a9a956d7d0a9dc1bd8bcdaf52f76ef2f12","dweb:/ipfs/Qmax9WHBnVsZP46ZxEMNRQpLQnrdE4dK8LehML1Py8FowF"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/Panic.sol":{"keccak256":"0xf7fe324703a64fc51702311dc51562d5cb1497734f074e4f483bfb6717572d7a","urls":["bzz-raw://c6a5ff4f9fd8649b7ee20800b7fa387d3465bd77cf20c2d1068cd5c98e1ed57a","dweb:/ipfs/QmVSaVJf9FXFhdYEYeCEfjMVHrxDh5qL4CGkxdMWpQCrqG"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/SlotDerivation.sol":{"keccak256":"0x94045fd4f268edf2b2d01ef119268548c320366d6f5294ad30c1b8f9d4f5225f","urls":["bzz-raw://edfda81f426f8948b3834115c21e83c48180e6db0d2a8cd2debb2185ed349337","dweb:/ipfs/QmdYZneFyDAux1BuWQxLAdqtABrGS2k9WYCa7C9dvpKkWv"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol":{"keccak256":"0xcf74f855663ce2ae00ed8352666b7935f6cddea2932fdf2c3ecd30a9b1cd0e97","urls":["bzz-raw://9f660b1f351b757dfe01438e59888f31f33ded3afcf5cb5b0d9bf9aa6f320a8b","dweb:/ipfs/QmarDJ5hZEgBtCmmrVzEZWjub9769eD686jmzb2XpSU1cM"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol":{"keccak256":"0x2d9dc2fe26180f74c11c13663647d38e259e45f95eb88f57b61d2160b0109d3e","urls":["bzz-raw://81233d1f98060113d9922180bb0f14f8335856fe9f339134b09335e9f678c377","dweb:/ipfs/QmWh6R35SarhAn4z2wH8SU456jJSYL2FgucfTFgbHJJN4E"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165Checker.sol":{"keccak256":"0x7c7ad70641a7f8cd44def0857ec97b0e40bfd073b2d6037a5f57ce9527ee9bc5","urls":["bzz-raw://e05c6572dfe769f7aea6f3a8002951cc12d143d980dad29f6c5feedf9408bc14","dweb:/ipfs/QmXM7C8YEptxisZiEefXUrwdXt3zMaCobmkCchxTtDg1oK"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol":{"keccak256":"0x8891738ffe910f0cf2da09566928589bf5d63f4524dd734fd9cedbac3274dd5c","urls":["bzz-raw://971f954442df5c2ef5b5ebf1eb245d7105d9fbacc7386ee5c796df1d45b21617","dweb:/ipfs/QmadRjHbkicwqwwh61raUEapaVEtaLMcYbQZWs9gUkgj3u"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/math/Math.sol":{"keccak256":"0x59973a93b1f983f94e10529f46ca46544a9fec2b5f56fb1390bbe9e0dc79f857","urls":["bzz-raw://c55ef8f0b9719790c2ae6f81d80a59ffb89f2f0abe6bc065585bd79edce058c5","dweb:/ipfs/QmNNmCbX9NjPXKqHJN8R1WC2rNeZSQrPZLd6FF6AKLyH5Y"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol":{"keccak256":"0xc8cae21c9ae4a46e5162ff9bf5b351d6fa6a6eba72d515f3bc1bdfeda7fdf083","urls":["bzz-raw://ce830ebcf28e31643caba318996db3763c36d52cd0f23798ba83c135355d45e9","dweb:/ipfs/QmdGPcvptHN7UBCbUYBbRX3hiRVRFLRwno8b4uga6uFNif"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/structs/EnumerableSet.sol":{"keccak256":"0xd553ff8b7d55679f0711f1598600ac292dbd8cfdf4b2419b9cabe4c931172895","urls":["bzz-raw://7905ccb27e2308fd0d90dc1212161003ab6964e1c176593db1ccedef705bcc09","dweb:/ipfs/QmW37vm2PcrWLKnN74sKkvAzqSwntCEfCp4EoSEvbBHWkj"],"license":"MIT"},"src/RuleEngineBase.sol":{"keccak256":"0xb3d832fa55b615574d80b0e0ad76620ad236aa046523617ed5daa46ae07bf853","urls":["bzz-raw://7be31bf5dbd3fa1be025cdc4b7674b76bf40e1c14ce89ec78f792cb3d7ed804e","dweb:/ipfs/QmPq4xBiB3XwXerWtuonZLGiWHMqvz5tKvjhTh9AiWkbww"],"license":"MPL-2.0"},"src/RuleEngineOwnableShared.sol":{"keccak256":"0xa78493398d8b0554e72def7f14d7439109bd4dbd5e07f1466b40acea2bb7dc02","urls":["bzz-raw://ebd87d69b4f6eb193c5d03476381ac132f9587248422d3306dda95b79fd4e470","dweb:/ipfs/QmWYDLvPWjRcfxdR2KhXAij8U9TrFjeM77fsJRX25jWQmY"],"license":"MPL-2.0"},"src/deployment/ownable/RuleEngineOwnable.sol":{"keccak256":"0x9f34713fce49bbc841ed5f0d24c5b53455359a11d904f7ceb3c7ef210494c6c5","urls":["bzz-raw://71875cc9f3a8f9f35b5ec06273cc1c83a23b2cb775ab2974610ca0dc4ac74945","dweb:/ipfs/QmQUVtngskTrnPjv85BLJhEDxYVwp7WFhBHPBpRL4cvn27"],"license":"MPL-2.0"},"src/deployment/ownable/RuleEngineOwnable2771.sol":{"keccak256":"0x96fb410c95da0baccbd6603c7170ca27e5ac70c46df424aa1b56d2b003da428e","urls":["bzz-raw://766ba437433c84ba105a061734a8c3c00b8e2c765b538b8d66851a6595d1ddca","dweb:/ipfs/QmXqXebApRMp2FhMrhadC7svV74zcGfejfWkEuCdLeuTJq"],"license":"MPL-2.0"},"src/interfaces/IERC3643Compliance.sol":{"keccak256":"0xd0edd6697d67135853576ac6a40cadaffd787cedea98071708bbfb189c7ee5bc","urls":["bzz-raw://4ed3cd3af64fccff17a1f33989cdfbdacbc0e4f32a56de11a072cf9e2277a1f6","dweb:/ipfs/QmenRqRw1Yy39yDv1pJgBmnHtwuZhDdHE4omchL41CjXjb"],"license":"MPL-2.0"},"src/interfaces/IERC3643ComplianceExtended.sol":{"keccak256":"0x4a43bf330c7a904cba110acf52f519718d8409514c377912d5bd063c9d963729","urls":["bzz-raw://c671879c591760ecbc2691e2f24adfb215a658c9fe6eb0c05dd1ca980054e585","dweb:/ipfs/QmdbA19PFpJgHraF46YrcMNzUgswbTRA92atL2Lha63JLY"],"license":"MPL-2.0"},"src/interfaces/IRule.sol":{"keccak256":"0x81580b67f7be09049aa64d93cc1d8d691a87c639adc1cf169dc6073e1e543a5c","urls":["bzz-raw://6f1808c3ed18ef1acbccdd9b30011b6e7220d388cfd66cba40b1ef0b485306a1","dweb:/ipfs/QmcUCQ5MYcf7KTtoeqMKsTutPPSJhNTaK1ntHV21ioS9Fm"],"license":"MPL-2.0"},"src/interfaces/IRulesManagementModule.sol":{"keccak256":"0x082dd58070e83b02f275584afa872c4583ac4ca8ad12eb329fc11301470147f9","urls":["bzz-raw://e2d0ad78dc323881864f406acd44976f5de39cdc97a6c99a724d8458b993e2e2","dweb:/ipfs/QmRFfMbXbdiAYV3vQyNppXG7tHTji6mV1Y5Cu3ZzEQm5ng"],"license":"MPL-2.0"},"src/interfaces/ITokenBinding.sol":{"keccak256":"0x34dfea4e118c966adf867c0899844515566251819b4e4510fd8ee424555493fd","urls":["bzz-raw://1d054ed49874816688a6e71f76d611bbdefd492d122ae386cb804c6f5af677a7","dweb:/ipfs/QmRaYX4aJWYSNWNa1D4Nich3k7hkGM9rTfc9s2XaVqyRjy"],"license":"MPL-2.0"},"src/interfaces/ITokenBindingExtended.sol":{"keccak256":"0x01f3ab56dffce860d03e72d10e9f2d13b6bfc9004cf058c63a0b23e3b226da99","urls":["bzz-raw://521e0c9651632b70d61c4c3bd0b14c6f05d818166fe65dbed8e3253158b7637e","dweb:/ipfs/QmY2xEVvfV1dgtFYw6coHX3Z7Fm7yRhzPaGyt6cYBMVf76"],"license":"MPL-2.0"},"src/modules/ERC2771ModuleStandalone.sol":{"keccak256":"0x2135408cd37646f3a27b4a2cdb6f1b9b622541fed4f4b6311a06f986f6eb75d1","urls":["bzz-raw://82229782c9664a8c039fd5a3ecedca8a827fcec190be6c527c1236c864c0418f","dweb:/ipfs/QmXQmX1BFFupTPB27uJweT1tSc6nce3JXDSDa9Ztpf6cKk"],"license":"MPL-2.0"},"src/modules/ERC3643ComplianceExtendedModule.sol":{"keccak256":"0x6f808b068517e9e15f09fc6a9d4190001ec8c2314a10e27a85a2d43e44c84fb1","urls":["bzz-raw://c62c0b77fdd8b6e7bf7aa5bf8134a78ff024d6489a23f746874a99df38a8a265","dweb:/ipfs/QmV7PG3ZUUzwDs9tpooC3hmBu5e39buJnJ4TRditojJ3hu"],"license":"MPL-2.0"},"src/modules/ERC3643ComplianceModule.sol":{"keccak256":"0x7cda81af8687328ac2089f9d1d78352e0e75d0f70a4ba8e2b3ac82896f22863f","urls":["bzz-raw://50711cb94d69ea63d787a8bb19c38c0b99539029ec8fb957a8eff00880fc11fc","dweb:/ipfs/QmSapDWh5mpvWn1q6JteZisJfVGPrCz47WP2BBrJCccEjV"],"license":"MPL-2.0"},"src/modules/RulesManagementModule.sol":{"keccak256":"0xe4d9425613284e71a5e3d590d5433167a9751d9496f57efa914baa81f493e66d","urls":["bzz-raw://d07a16e6869df86c526ef89e7e359e34a9553dc4288b262abd2979359ecf720e","dweb:/ipfs/QmRy2JEsyhkv1mxv7eFaSbEWN4A3gtpPSUnnV48W2KiV4u"],"license":"MPL-2.0"},"src/modules/TokenBindingExtendedModule.sol":{"keccak256":"0x4e1ca7b2ec78608c3a7960bec7102a1780bdf3ec7ff544b612bafaf738b34d05","urls":["bzz-raw://657bcdd303fd5a7fbe733b283f69d8e8aa73efeeeaf95c0ae7479769ac573693","dweb:/ipfs/QmXiWPrv8pEqvBQck8jxC7NwB1MUdGQfLjihK6etYcZ54j"],"license":"MPL-2.0"},"src/modules/TokenBindingModule.sol":{"keccak256":"0xf65f46311d0078f60c30e3359dca988e39cba45b9eee53a09d618bfa70e6ef9b","urls":["bzz-raw://e8c458ecfd41df5fb4a391e7ef837fd5ed5c999e61ccc0e6b4bd23023a739832","dweb:/ipfs/Qmdsr765aw9fPFN2M9cSCP69o1o41FNCqhrXjHgEXNwbXV"],"license":"MPL-2.0"},"src/modules/VersionModule.sol":{"keccak256":"0x35daf007be8b9bb1cb9196ae2decb3e5ad4b574f6390f8fc010b78796ac42f73","urls":["bzz-raw://b1b29d75e1c5023a0c6cb8c56638a17d855a3fdc051a60b9d2f304b99f7876d2","dweb:/ipfs/QmXSCVjLuViC8916LwNpKtw8hqyH78Ptag3xH1n7F1fY4g"],"license":"MPL-2.0"},"src/modules/library/ComplianceInterfaceId.sol":{"keccak256":"0xd54bed5328e732f753d2886aeaa2761b2d66536d5247d4548e0ac1c83c7a0dac","urls":["bzz-raw://ad695339fdfe72446a69d2dfbe39373affe2f37299ad921e57016069a7bc3592","dweb:/ipfs/QmWathGt3E85hLfy5rrAYdb291W8VoTa4gpGPoxtWGvNNA"],"license":"MPL-2.0"},"src/modules/library/ERC1404InterfaceId.sol":{"keccak256":"0x07dc6905e137096cd0ae88be29b112d0e54a83ddf8ca527a281718010f6abcce","urls":["bzz-raw://9249dce67cb59432bdbc9e49978c6cac0346cda3d3fca97c5a310e0f424e1600","dweb:/ipfs/QmRi5awH3hjwvd3k3td48y5Cf64n1wvX9wCWy6fQLayuKs"],"license":"MPL-2.0"},"src/modules/library/OwnableInterfaceId.sol":{"keccak256":"0xdbe06b3203e21e41d1fd2a3ef373a80727193443dfd981de6821422158015d4f","urls":["bzz-raw://ebe8699ae8af81c5cd82f25a1609d9396d72ae957647c33aaa745aadcdac8d18","dweb:/ipfs/QmV73gwDJPFthn8VspdYE6GsoAcQMAR7TachUK8YrPonuT"],"license":"MPL-2.0"},"src/modules/library/RuleEngineInvariantStorage.sol":{"keccak256":"0x50a212f09f1695662965e5fba643b42a1978bec2a8368abbf43983489c983096","urls":["bzz-raw://6137f01df7630527c985d85d2f7446359c678fcb933b66c55b51f583757b5c4a","dweb:/ipfs/QmeHo47WQm1V99xZHS4soMk68UdtXtZhtWhV3dQC5BtA7u"],"license":"MPL-2.0"},"src/modules/library/RuleInterfaceId.sol":{"keccak256":"0x0d86820eee4c92b21d6704bea8ce7bd2cc1b35f6e4a1ceabbcf2a10f1c6b02ec","urls":["bzz-raw://cfb560cb8588983b8c79a973d03c214a149bf1ac034fa9130ce93f0031a404d7","dweb:/ipfs/Qmc6qt4E4BHdDyLUegCsgxqhf7ZFUiX4ahj8FjM54V7wpY"],"license":"MPL-2.0"},"src/modules/library/RulesManagementModuleInvariantStorage.sol":{"keccak256":"0xb81ea3a54c6e8d47b87d6c3d9fb5aae80c3430021b8cd66d9adeef7f5fc95893","urls":["bzz-raw://cfcbadc2011f60de7189273c278dda1df2218aeeb153bee3b8a93447ec95df21","dweb:/ipfs/Qmem5FqCLEfBJQdJzS7Xzd3zSfyL8Muf9Wv5WvCiBVsqfh"],"license":"MPL-2.0"},"src/modules/library/TokenBindingModuleInvariantStorage.sol":{"keccak256":"0x9bab8e5b265068da356fd46e343a7c6c73776f3964fdeaeff056e8ce104d40a5","urls":["bzz-raw://e2e75d2d52b1e4f5cbb832d194266de9a1b3a8cc2101e875dce43a2664c31a05","dweb:/ipfs/QmUsd5cTPsE89WKm3kTUWsobR9JsBDUY8NdxDU5RPYpvP6"],"license":"MPL-2.0"}},"version":1},"ast":{"absolutePath":"src/deployment/ownable/RuleEngineOwnable2771.sol","id":10093,"exportedSymbols":{"Context":[3248],"ERC2771Context":[1565],"ERC2771ModuleStandalone":[13340],"RuleEngineOwnable":[10017],"RuleEngineOwnable2771":[10092]},"nodeType":"SourceUnit","src":"37:2617:33","nodes":[{"id":10019,"nodeType":"PragmaDirective","src":"37:24:33","nodes":[],"literals":["solidity","^","0.8",".27"]},{"id":10021,"nodeType":"ImportDirective","src":"91:66:33","nodes":[],"absolutePath":"lib/openzeppelin-contracts/contracts/utils/Context.sol","file":"@openzeppelin/contracts/utils/Context.sol","nameLocation":"-1:-1:-1","scope":10093,"sourceUnit":3249,"symbolAliases":[{"foreign":{"id":10020,"name":"Context","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":3248,"src":"99:7:33","typeDescriptions":{}},"nameLocation":"-1:-1:-1"}],"unitAlias":""},{"id":10024,"nodeType":"ImportDirective","src":"181:98:33","nodes":[],"absolutePath":"src/modules/ERC2771ModuleStandalone.sol","file":"../../modules/ERC2771ModuleStandalone.sol","nameLocation":"-1:-1:-1","scope":10093,"sourceUnit":13341,"symbolAliases":[{"foreign":{"id":10022,"name":"ERC2771ModuleStandalone","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":13340,"src":"189:23:33","typeDescriptions":{}},"nameLocation":"-1:-1:-1"},{"foreign":{"id":10023,"name":"ERC2771Context","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":1565,"src":"214:14:33","typeDescriptions":{}},"nameLocation":"-1:-1:-1"}],"unitAlias":""},{"id":10026,"nodeType":"ImportDirective","src":"309:58:33","nodes":[],"absolutePath":"src/deployment/ownable/RuleEngineOwnable.sol","file":"./RuleEngineOwnable.sol","nameLocation":"-1:-1:-1","scope":10093,"sourceUnit":10018,"symbolAliases":[{"foreign":{"id":10025,"name":"RuleEngineOwnable","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":10017,"src":"317:17:33","typeDescriptions":{}},"nameLocation":"-1:-1:-1"}],"unitAlias":""},{"id":10092,"nodeType":"ContractDefinition","src":"768:1885:33","nodes":[{"id":10049,"nodeType":"FunctionDefinition","src":"1233:190:33","nodes":[],"body":{"id":10048,"nodeType":"Block","src":"1421:2:33","nodes":[],"statements":[]},"documentation":{"id":10032,"nodeType":"StructuredDocumentation","src":"851:377:33","text":" @notice Deploys a RuleEngine with ERC-173 Ownable access control and a trusted forwarder.\n @param owner_ Address of the initial contract owner (ERC-173).\n @param forwarderIrrevocable Address of the trusted ERC-2771 forwarder, immutable after construction.\n @param tokenContract Token to bind at deployment, or the zero address to bind none."},"implemented":true,"kind":"constructor","modifiers":[{"arguments":[{"id":10041,"name":"forwarderIrrevocable","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":10036,"src":"1346:20:33","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"id":10042,"kind":"baseConstructorSpecifier","modifierName":{"id":10040,"name":"ERC2771ModuleStandalone","nameLocations":["1322:23:33"],"nodeType":"IdentifierPath","referencedDeclaration":13340,"src":"1322:23:33"},"nodeType":"ModifierInvocation","src":"1322:45:33"},{"arguments":[{"id":10044,"name":"owner_","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":10034,"src":"1394:6:33","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},{"id":10045,"name":"tokenContract","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":10038,"src":"1402:13:33","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"id":10046,"kind":"baseConstructorSpecifier","modifierName":{"id":10043,"name":"RuleEngineOwnable","nameLocations":["1376:17:33"],"nodeType":"IdentifierPath","referencedDeclaration":10017,"src":"1376:17:33"},"nodeType":"ModifierInvocation","src":"1376:40:33"}],"name":"","nameLocation":"-1:-1:-1","parameters":{"id":10039,"nodeType":"ParameterList","parameters":[{"constant":false,"id":10034,"mutability":"mutable","name":"owner_","nameLocation":"1253:6:33","nodeType":"VariableDeclaration","scope":10049,"src":"1245:14:33","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":10033,"name":"address","nodeType":"ElementaryTypeName","src":"1245:7:33","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"},{"constant":false,"id":10036,"mutability":"mutable","name":"forwarderIrrevocable","nameLocation":"1269:20:33","nodeType":"VariableDeclaration","scope":10049,"src":"1261:28:33","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":10035,"name":"address","nodeType":"ElementaryTypeName","src":"1261:7:33","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"},{"constant":false,"id":10038,"mutability":"mutable","name":"tokenContract","nameLocation":"1299:13:33","nodeType":"VariableDeclaration","scope":10049,"src":"1291:21:33","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":10037,"name":"address","nodeType":"ElementaryTypeName","src":"1291:7:33","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"src":"1244:69:33"},"returnParameters":{"id":10047,"nodeType":"ParameterList","parameters":[],"src":"1421:0:33"},"scope":10092,"stateMutability":"nonpayable","virtual":false,"visibility":"public"},{"id":10063,"nodeType":"FunctionDefinition","src":"1814:154:33","nodes":[],"body":{"id":10062,"nodeType":"Block","src":"1917:51:33","nodes":[],"statements":[{"expression":{"arguments":[],"expression":{"argumentTypes":[],"expression":{"id":10058,"name":"ERC2771Context","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":1565,"src":"1934:14:33","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_ERC2771Context_$1565_$","typeString":"type(contract ERC2771Context)"}},"id":10059,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberLocation":"1949:10:33","memberName":"_msgSender","nodeType":"MemberAccess","referencedDeclaration":1512,"src":"1934:25:33","typeDescriptions":{"typeIdentifier":"t_function_internal_view$__$returns$_t_address_$","typeString":"function () view returns (address)"}},"id":10060,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"nameLocations":[],"names":[],"nodeType":"FunctionCall","src":"1934:27:33","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"functionReturnParameters":10057,"id":10061,"nodeType":"Return","src":"1927:34:33"}]},"baseFunctions":[1512,3230],"documentation":{"id":10050,"nodeType":"StructuredDocumentation","src":"1603:206:33","text":" @dev Resolves the sender through ERC-2771 when the call comes from the trusted forwarder.\n @return sender The transaction sender, unwrapped from the forwarder calldata when relayed."},"implemented":true,"kind":"function","modifiers":[],"name":"_msgSender","nameLocation":"1823:10:33","overrides":{"id":10054,"nodeType":"OverrideSpecifier","overrides":[{"id":10052,"name":"ERC2771Context","nameLocations":["1867:14:33"],"nodeType":"IdentifierPath","referencedDeclaration":1565,"src":"1867:14:33"},{"id":10053,"name":"Context","nameLocations":["1883:7:33"],"nodeType":"IdentifierPath","referencedDeclaration":3248,"src":"1883:7:33"}],"src":"1858:33:33"},"parameters":{"id":10051,"nodeType":"ParameterList","parameters":[],"src":"1833:2:33"},"returnParameters":{"id":10057,"nodeType":"ParameterList","parameters":[{"constant":false,"id":10056,"mutability":"mutable","name":"sender","nameLocation":"1909:6:33","nodeType":"VariableDeclaration","scope":10063,"src":"1901:14:33","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":10055,"name":"address","nodeType":"ElementaryTypeName","src":"1901:7:33","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"src":"1900:16:33"},"scope":10092,"stateMutability":"view","virtual":true,"visibility":"internal"},{"id":10077,"nodeType":"FunctionDefinition","src":"2178:150:33","nodes":[],"body":{"id":10076,"nodeType":"Block","src":"2279:49:33","nodes":[],"statements":[{"expression":{"arguments":[],"expression":{"argumentTypes":[],"expression":{"id":10072,"name":"ERC2771Context","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":1565,"src":"2296:14:33","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_ERC2771Context_$1565_$","typeString":"type(contract ERC2771Context)"}},"id":10073,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberLocation":"2311:8:33","memberName":"_msgData","nodeType":"MemberAccess","referencedDeclaration":1554,"src":"2296:23:33","typeDescriptions":{"typeIdentifier":"t_function_internal_view$__$returns$_t_bytes_calldata_ptr_$","typeString":"function () view returns (bytes calldata)"}},"id":10074,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"nameLocations":[],"names":[],"nodeType":"FunctionCall","src":"2296:25:33","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes_calldata_ptr","typeString":"bytes calldata"}},"functionReturnParameters":10071,"id":10075,"nodeType":"Return","src":"2289:32:33"}]},"baseFunctions":[1554,3239],"documentation":{"id":10064,"nodeType":"StructuredDocumentation","src":"1974:199:33","text":" @dev Resolves the calldata through ERC-2771 when the call comes from the trusted forwarder.\n @return The transaction calldata, with the appended sender stripped when relayed."},"implemented":true,"kind":"function","modifiers":[],"name":"_msgData","nameLocation":"2187:8:33","overrides":{"id":10068,"nodeType":"OverrideSpecifier","overrides":[{"id":10066,"name":"ERC2771Context","nameLocations":["2229:14:33"],"nodeType":"IdentifierPath","referencedDeclaration":1565,"src":"2229:14:33"},{"id":10067,"name":"Context","nameLocations":["2245:7:33"],"nodeType":"IdentifierPath","referencedDeclaration":3248,"src":"2245:7:33"}],"src":"2220:33:33"},"parameters":{"id":10065,"nodeType":"ParameterList","parameters":[],"src":"2195:2:33"},"returnParameters":{"id":10071,"nodeType":"ParameterList","parameters":[{"constant":false,"id":10070,"mutability":"mutable","name":"","nameLocation":"-1:-1:-1","nodeType":"VariableDeclaration","scope":10077,"src":"2263:14:33","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_bytes_calldata_ptr","typeString":"bytes"},"typeName":{"id":10069,"name":"bytes","nodeType":"ElementaryTypeName","src":"2263:5:33","typeDescriptions":{"typeIdentifier":"t_bytes_storage_ptr","typeString":"bytes"}},"visibility":"internal"}],"src":"2262:16:33"},"scope":10092,"stateMutability":"view","virtual":true,"visibility":"internal"},{"id":10091,"nodeType":"FunctionDefinition","src":"2484:167:33","nodes":[],"body":{"id":10090,"nodeType":"Block","src":"2590:61:33","nodes":[],"statements":[{"expression":{"arguments":[],"expression":{"argumentTypes":[],"expression":{"id":10086,"name":"ERC2771Context","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":1565,"src":"2607:14:33","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_ERC2771Context_$1565_$","typeString":"type(contract ERC2771Context)"}},"id":10087,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberLocation":"2622:20:33","memberName":"_contextSuffixLength","nodeType":"MemberAccess","referencedDeclaration":1564,"src":"2607:35:33","typeDescriptions":{"typeIdentifier":"t_function_internal_view$__$returns$_t_uint256_$","typeString":"function () view returns (uint256)"}},"id":10088,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"nameLocations":[],"names":[],"nodeType":"FunctionCall","src":"2607:37:33","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"functionReturnParameters":10085,"id":10089,"nodeType":"Return","src":"2600:44:33"}]},"baseFunctions":[1564,3247],"documentation":{"id":10078,"nodeType":"StructuredDocumentation","src":"2334:145:33","text":" @dev Length of the sender suffix appended by the trusted forwarder.\n @return The length of the ERC-2771 calldata suffix."},"implemented":true,"kind":"function","modifiers":[],"name":"_contextSuffixLength","nameLocation":"2493:20:33","overrides":{"id":10082,"nodeType":"OverrideSpecifier","overrides":[{"id":10080,"name":"ERC2771Context","nameLocations":["2547:14:33"],"nodeType":"IdentifierPath","referencedDeclaration":1565,"src":"2547:14:33"},{"id":10081,"name":"Context","nameLocations":["2563:7:33"],"nodeType":"IdentifierPath","referencedDeclaration":3248,"src":"2563:7:33"}],"src":"2538:33:33"},"parameters":{"id":10079,"nodeType":"ParameterList","parameters":[],"src":"2513:2:33"},"returnParameters":{"id":10085,"nodeType":"ParameterList","parameters":[{"constant":false,"id":10084,"mutability":"mutable","name":"","nameLocation":"-1:-1:-1","nodeType":"VariableDeclaration","scope":10091,"src":"2581:7:33","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"},"typeName":{"id":10083,"name":"uint256","nodeType":"ElementaryTypeName","src":"2581:7:33","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"visibility":"internal"}],"src":"2580:9:33"},"scope":10092,"stateMutability":"view","virtual":true,"visibility":"internal"}],"abstract":false,"baseContracts":[{"baseName":{"id":10028,"name":"ERC2771ModuleStandalone","nameLocations":["802:23:33"],"nodeType":"IdentifierPath","referencedDeclaration":13340,"src":"802:23:33"},"id":10029,"nodeType":"InheritanceSpecifier","src":"802:23:33"},{"baseName":{"id":10030,"name":"RuleEngineOwnable","nameLocations":["827:17:33"],"nodeType":"IdentifierPath","referencedDeclaration":10017,"src":"827:17:33"},"id":10031,"nodeType":"InheritanceSpecifier","src":"827:17:33"}],"canonicalName":"RuleEngineOwnable2771","contractDependencies":[],"contractKind":"contract","documentation":{"id":10027,"nodeType":"StructuredDocumentation","src":"369:398:33","text":" @title Implementation of a ruleEngine with ERC-173 Ownable access control and ERC-2771\n @dev {RuleEngineOwnable} plus an immutable trusted forwarder: administrative calls (owner-only functions) may be\n relayed by the forwarder (gasless transactions). Token identity is never resolved through the\n forwarder: the bound-token gate and token self-binding compare the raw `msg.sender`."},"fullyImplemented":true,"linearizedBaseContracts":[10092,10017,1144,9689,3578,9604,34,28,3800,14477,13390,10332,13447,14176,10545,10320,14356,14606,10476,262,464,251,311,285,13340,1565,3248,13913,10442,14580,14379,123],"name":"RuleEngineOwnable2771","nameLocation":"777:21:33","scope":10093,"usedErrors":[1010,1015,14474,14476,14545,14547,14549,14551,14555,14557,14559,14596,14599,14602,14605],"usedEvents":[1021,10450,10455,10490,10498,14565,14571,14574,14579]}],"license":"MPL-2.0"},"id":33} \ No newline at end of file diff --git a/doc/compilation/v3.0.0-rc7/foundry/RuleEngineOwnable2Step.sol/RuleEngineOwnable2Step.json b/doc/compilation/v3.0.0-rc7/foundry/RuleEngineOwnable2Step.sol/RuleEngineOwnable2Step.json new file mode 100644 index 00000000..def5b79a --- /dev/null +++ b/doc/compilation/v3.0.0-rc7/foundry/RuleEngineOwnable2Step.sol/RuleEngineOwnable2Step.json @@ -0,0 +1 @@ +{"abi":[{"type":"constructor","inputs":[{"name":"owner_","type":"address","internalType":"address"},{"name":"tokenContract","type":"address","internalType":"address"}],"stateMutability":"nonpayable"},{"type":"function","name":"DEFAULT_MAX_RULES","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"acceptOwnership","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"addRule","inputs":[{"name":"rule_","type":"address","internalType":"contract IRule"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"bindToken","inputs":[{"name":"token","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"bindTokens","inputs":[{"name":"tokens","type":"address[]","internalType":"address[]"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"canTransfer","inputs":[{"name":"from","type":"address","internalType":"address"},{"name":"to","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"canTransferFrom","inputs":[{"name":"spender","type":"address","internalType":"address"},{"name":"from","type":"address","internalType":"address"},{"name":"to","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"clearRules","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"containsRule","inputs":[{"name":"rule_","type":"address","internalType":"contract IRule"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"created","inputs":[{"name":"to","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"destroyed","inputs":[{"name":"from","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"detectTransferRestriction","inputs":[{"name":"from","type":"address","internalType":"address"},{"name":"to","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint8","internalType":"uint8"}],"stateMutability":"view"},{"type":"function","name":"detectTransferRestrictionFrom","inputs":[{"name":"spender","type":"address","internalType":"address"},{"name":"from","type":"address","internalType":"address"},{"name":"to","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint8","internalType":"uint8"}],"stateMutability":"view"},{"type":"function","name":"getTokenBound","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"getTokenBounds","inputs":[],"outputs":[{"name":"","type":"address[]","internalType":"address[]"}],"stateMutability":"view"},{"type":"function","name":"isTokenBound","inputs":[{"name":"token","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"isTokenSelfBindingApproved","inputs":[{"name":"token","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"maxRules","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"messageForTransferRestriction","inputs":[{"name":"restrictionCode","type":"uint8","internalType":"uint8"}],"outputs":[{"name":"","type":"string","internalType":"string"}],"stateMutability":"view"},{"type":"function","name":"owner","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"pendingOwner","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"removeRule","inputs":[{"name":"rule_","type":"address","internalType":"contract IRule"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"renounceOwnership","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"rule","inputs":[{"name":"ruleId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"rules","inputs":[],"outputs":[{"name":"","type":"address[]","internalType":"address[]"}],"stateMutability":"view"},{"type":"function","name":"rulesCount","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"setMaxRules","inputs":[{"name":"maxRules_","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setRules","inputs":[{"name":"rules_","type":"address[]","internalType":"contract IRule[]"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setTokenSelfBindingApproval","inputs":[{"name":"token","type":"address","internalType":"address"},{"name":"approved","type":"bool","internalType":"bool"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setTokenSelfBindingApprovalBatch","inputs":[{"name":"tokens","type":"address[]","internalType":"address[]"},{"name":"approved","type":"bool","internalType":"bool"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"supportsInterface","inputs":[{"name":"interfaceId","type":"bytes4","internalType":"bytes4"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"transferOwnership","inputs":[{"name":"newOwner","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"transferred","inputs":[{"name":"spender","type":"address","internalType":"address"},{"name":"from","type":"address","internalType":"address"},{"name":"to","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"transferred","inputs":[{"name":"from","type":"address","internalType":"address"},{"name":"to","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"unbindToken","inputs":[{"name":"token","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"unbindTokens","inputs":[{"name":"tokens","type":"address[]","internalType":"address[]"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"version","inputs":[],"outputs":[{"name":"version_","type":"string","internalType":"string"}],"stateMutability":"view"},{"type":"event","name":"AddRule","inputs":[{"name":"rule","type":"address","indexed":true,"internalType":"contract IRule"}],"anonymous":false},{"type":"event","name":"ClearRules","inputs":[],"anonymous":false},{"type":"event","name":"OwnershipTransferStarted","inputs":[{"name":"previousOwner","type":"address","indexed":true,"internalType":"address"},{"name":"newOwner","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"name":"previousOwner","type":"address","indexed":true,"internalType":"address"},{"name":"newOwner","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"RemoveRule","inputs":[{"name":"rule","type":"address","indexed":true,"internalType":"contract IRule"}],"anonymous":false},{"type":"event","name":"SetMaxRules","inputs":[{"name":"maxRules","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"TokenBound","inputs":[{"name":"token","type":"address","indexed":false,"internalType":"address"}],"anonymous":false},{"type":"event","name":"TokenSelfBindingApprovalBatchSet","inputs":[{"name":"tokens","type":"address[]","indexed":false,"internalType":"address[]"},{"name":"approved","type":"bool","indexed":false,"internalType":"bool"}],"anonymous":false},{"type":"event","name":"TokenSelfBindingApprovalSet","inputs":[{"name":"token","type":"address","indexed":true,"internalType":"address"},{"name":"approved","type":"bool","indexed":false,"internalType":"bool"}],"anonymous":false},{"type":"event","name":"TokenUnbound","inputs":[{"name":"token","type":"address","indexed":false,"internalType":"address"}],"anonymous":false},{"type":"error","name":"OwnableInvalidOwner","inputs":[{"name":"owner","type":"address","internalType":"address"}]},{"type":"error","name":"OwnableUnauthorizedAccount","inputs":[{"name":"account","type":"address","internalType":"address"}]},{"type":"error","name":"RuleEngine_AdminWithAddressZeroNotAllowed","inputs":[]},{"type":"error","name":"RuleEngine_RuleInvalidInterface","inputs":[]},{"type":"error","name":"RuleEngine_RulesManagementModule_ArrayIsEmpty","inputs":[]},{"type":"error","name":"RuleEngine_RulesManagementModule_MaxRulesExceeded","inputs":[{"name":"maxRules","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"RuleEngine_RulesManagementModule_MaxRulesZeroNotAllowed","inputs":[]},{"type":"error","name":"RuleEngine_RulesManagementModule_RuleAccountCannotReceivePrivileges","inputs":[]},{"type":"error","name":"RuleEngine_RulesManagementModule_RuleAddressZeroNotAllowed","inputs":[]},{"type":"error","name":"RuleEngine_RulesManagementModule_RuleAlreadyExists","inputs":[]},{"type":"error","name":"RuleEngine_RulesManagementModule_RuleDoNotMatch","inputs":[]},{"type":"error","name":"TokenBinding_InvalidTokenAddress","inputs":[]},{"type":"error","name":"TokenBinding_TokenAlreadyBound","inputs":[]},{"type":"error","name":"TokenBinding_TokenNotBound","inputs":[]},{"type":"error","name":"TokenBinding_UnauthorizedCaller","inputs":[]}],"bytecode":{"object":"0x6080604052600a600255348015610014575f5ffd5b50604051611f2e380380611f2e833981016040819052610033916102bd565b81816001600160a01b0381161561004d5761004d81610096565b610057600a61012e565b506001600160a01b03811661008557604051631e4fbdf760e01b81525f600482015260240160405180910390fd5b61008e81610183565b5050506102ee565b6001600160a01b0381166100bd5760405163135217db60e21b815260040160405180910390fd5b6100c68161019f565b6100d16003826101c7565b6100ee576040516371b3c56560e11b815260040160405180910390fd5b6040516001600160a01b03821681527f2de35142b19ed5a07796cf30791959c592018f70b1d2d7c460eef8ffe713692b906020015b60405180910390a150565b805f0361014e57604051631e69e71760e21b815260040160405180910390fd5b60028190556040518181527f2292ad4720fff63e2bd104c6b1c0d72c2c729a6001c8ab4bb947cbcc5110986390602001610123565b600780546001600160a01b031916905561019c816101e4565b50565b6101a95f82610235565b1561019c576040516302925f7360e11b815260040160405180910390fd5b5f6101db836001600160a01b038416610256565b90505b92915050565b600680546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b6001600160a01b0381165f90815260018301602052604081205415156101db565b5f81815260018301602052604081205461029b57508154600181810184555f8481526020808220909301849055845484825282860190935260409020919091556101de565b505f6101de565b80516001600160a01b03811681146102b8575f5ffd5b919050565b5f5f604083850312156102ce575f5ffd5b6102d7836102a2565b91506102e5602084016102a2565b90509250929050565b611c33806102fb5f395ff3fe608060405234801561000f575f5ffd5b506004361061021e575f3560e01c80638d2ea7721161012a578063d4ce1415116100b4578063e3c4602c11610079578063e3c4602c146104bc578063e46638e6146104cf578063e54621d2146104e2578063f2fde38b146104ea578063f76bf550146104fd575f5ffd5b8063d4ce141514610447578063db18af6c1461045a578063db75d0171461046d578063df21950f14610498578063e30c3978146104ab575f5ffd5b8063b27aef3a116100fa578063b27aef3a146103e1578063bb4b6121146103f4578063bc13eacc14610407578063c7c24b181461040f578063d32c7bb514610422575f5ffd5b80638d2ea772146103a25780638da5cb5b146103b5578063993e8b95146103c6578063b043572e146103d9575f5ffd5b806354fd4d50116101ab578063715018a61161017b578063715018a6146103595780637157797f1461036157806379ba5097146103745780637f4ab1dd1461037c5780638baf29b41461038f575f5ffd5b806354fd4d50146102e65780635f8dead3146103145780636a3edf28146103275780636ae728c614610347575f5ffd5b80633e5af4ca116101f15780633e5af4ca146102855780633ff5aa021461029857806340db3b50146102ab57806352f6747a146102be57806354e4b945146102d3575f5ffd5b806301ffc9a7146102225780631455d0e71461024a5780633284a9a51461025f5780633a56d6d514610272575b5f5ffd5b610235610230366004611777565b610505565b60405190151581526020015b60405180910390f35b61025d6102583660046117e6565b61052f565b005b61025d61026d366004611846565b61057d565b61025d61028036600461187d565b6105ba565b61025d610293366004611894565b6105ce565b61025d6102a63660046118e2565b6105e8565b61025d6102b93660046118e2565b6105fa565b6102c661060c565b60405161024191906118fd565b6102356102e13660046118e2565b61061c565b604080518082019091526009815268332e302e302d72633760b81b60208201525b6040516102419190611948565b61025d61032236600461197d565b610627565b61032f61063a565b6040516001600160a01b039091168152602001610241565b6002545b604051908152602001610241565b61025d61065c565b61023561036f366004611894565b61066f565b61025d61068c565b61030761038a3660046119b5565b61069d565b61025d61039d3660046119d0565b6106a8565b61025d6103b036600461197d565b6106bb565b6006546001600160a01b031661032f565b6102356103d43660046118e2565b6106ce565b61025d6106da565b61025d6103ef3660046117e6565b6106ea565b61025d610402366004611a0e565b61079d565b61034b61086b565b61025d61041d3660046117e6565b610875565b610435610430366004611894565b6108be565b60405160ff9091168152602001610241565b6104356104553660046119d0565b6108d4565b61032f61046836600461187d565b6108ea565b61023561047b3660046118e2565b6001600160a01b03165f9081526005602052604090205460ff1690565b61025d6104a63660046118e2565b61090c565b6007546001600160a01b031661032f565b61025d6104ca3660046118e2565b61091d565b6102356104dd3660046119d0565b61095f565b6102c6610978565b61025d6104f83660046118e2565b610984565b61034b600a81565b5f6001600160e01b03198216639ab669ef60e01b148061052957506105298261099e565b92915050565b6105376109e2565b5f5b818110156105785761057083838381811061055657610556611a61565b905060200201602081019061056b91906118e2565b6109ea565b600101610539565b505050565b6105856109e2565b6001600160a01b0382166105ac5760405163135217db60e21b815260040160405180910390fd5b6105b682826109f3565b5050565b6105c2610a51565b6105cb81610a59565b50565b6105d6610ab5565b6105e284848484610add565b50505050565b6105f181610b7f565b6105cb81610b88565b61060381610b7f565b6105cb816109ea565b60606106175f610c19565b905090565b5f6105298183610c25565b61062f610ab5565b6105b65f8383610c45565b5f5f6106466003610cde565b11156106575761061760035f610ce7565b505f90565b610664610cf2565b61066d5f610d1f565b565b5f8061067d868686866108be565b60ff161490505b949350505050565b61069533610d38565b61066d610d5f565b606061052982610da0565b6106b0610ab5565b610578838383610c45565b6106c3610ab5565b6105b6825f83610c45565b5f610529600383610c25565b6106e2610a51565b61066d610f15565b6106f2610a51565b5f819003610713576040516359203cb960e01b815260040160405180910390fd5b6002548082111561074357604051630befc49d60e01b815260040161073a91815260200190565b60405180910390fd5b505f61074e5f610cde565b111561075c5761075c610f15565b5f5b818110156105785761079583838381811061077b5761077b611a61565b905060200201602081019061079091906118e2565b610f46565b60010161075e565b6107a56109e2565b5f5b8281101561082a575f8484838181106107c2576107c2611a61565b90506020020160208101906107d791906118e2565b90506001600160a01b0381166108005760405163135217db60e21b815260040160405180910390fd5b6001600160a01b03165f908152600560205260409020805460ff19168315151790556001016107a7565b507f430881f04f203566ee9b32d6444cf02e1b2a0f17ab6b4263a1ee2074d3d0f48383838360405161085e93929190611a75565b60405180910390a1505050565b5f6106175f610cde565b61087d6109e2565b5f5b81811015610578576108b683838381811061089c5761089c611a61565b90506020020160208101906108b191906118e2565b610b88565b60010161087f565b5f6108cb85858585610fac565b95945050505050565b5f6108e0848484611079565b90505b9392505050565b5f6108f45f610cde565b821015610905576105295f83610ce7565b505f919050565b610914610a51565b6105cb8161113d565b610925610a51565b600254806109325f610cde565b10819061095557604051630befc49d60e01b815260040161073a91815260200190565b506105b682610f46565b5f8061096c8585856108d4565b60ff1614949350505050565b60606106176003610c19565b61098c610cf2565b61099581610d38565b6105cb8161119a565b5f6109a88261120b565b806109c357506001600160e01b031982166307f5828d60e41b145b8061052957506301ffc9a760e01b6001600160e01b0319831614610529565b61066d610a51565b6105cb816112ac565b6001600160a01b0382165f81815260056020908152604091829020805460ff191685151590811790915591519182527f407b412a9b6db334d48445ec9bcad46fb50bc4b2e97f73e963e397101957a729910160405180910390a25050565b61066d610cf2565b805f03610a7957604051631e69e71760e21b815260040160405180910390fd5b60028190556040518181527f2292ad4720fff63e2bd104c6b1c0d72c2c729a6001c8ab4bb947cbcc51109863906020015b60405180910390a150565b610ac0600333610c25565b61066d57604051630599c0e960e01b815260040160405180910390fd5b5f610ae75f610cde565b90505f5b81811015610b7757610afd5f82610ce7565b604051631f2d7a6560e11b81526001600160a01b03888116600483015287811660248301528681166044830152606482018690529190911690633e5af4ca906084015f604051808303815f87803b158015610b56575f5ffd5b505af1158015610b68573d5f5f3e3d5ffd5b50505050806001019050610aeb565b505050505050565b6105cb816112f4565b6001600160a01b038116610baf5760405163135217db60e21b815260040160405180910390fd5b610bb881611333565b610bc360038261133d565b610be0576040516371b3c56560e11b815260040160405180910390fd5b6040516001600160a01b03821681527f2de35142b19ed5a07796cf30791959c592018f70b1d2d7c460eef8ffe713692b90602001610aaa565b60605f6108e383611351565b6001600160a01b03165f9081526001919091016020526040902054151590565b5f610c4f5f610cde565b90505f5b81811015610cd757610c655f82610ce7565b6040516322ebca6d60e21b81526001600160a01b0387811660048301528681166024830152604482018690529190911690638baf29b4906064015f604051808303815f87803b158015610cb6575f5ffd5b505af1158015610cc8573d5f5f3e3d5ffd5b50505050806001019050610c53565b5050505050565b5f610529825490565b5f6108e383836113aa565b6006546001600160a01b0316331461066d5760405163118cdaa760e01b815233600482015260240161073a565b600780546001600160a01b03191690556105cb816113d0565b610d418161061c565b156105cb576040516302925f7360e11b815260040160405180910390fd5b60075433906001600160a01b03168114610d975760405163118cdaa760e01b81526001600160a01b038216600482015260240161073a565b6105cb81610d1f565b606060ff8216610dd357505060408051808201909152600d81526c2737a932b9ba3934b1ba34b7b760991b602082015290565b5f610ddd5f610cde565b90505f5b81811015610ed9575f610df48183610ce7565b604051633e822efb60e11b815260ff871660048201529091506001600160a01b03821690637d045df690602401602060405180830381865afa158015610e3c573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e609190611acd565b15610ed057604051637f4ab1dd60e01b815260ff861660048201526001600160a01b03821690637f4ab1dd906024015f60405180830381865afa158015610ea9573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526108cb9190810190611afc565b50600101610de1565b505060408051808201909152601881527f556e6b6e6f776e207265737472696374696f6e20636f64650000000000000000602082015292915050565b6040517fdbf61473843cd9be1c9791ce51ef66d0da6c9026d62ba80c1ca433b13fb729b2905f90a161066d5f611421565b610f4f8161142a565b610f595f8261133d565b610f765760405163cc790a4b60e01b815260040160405180910390fd5b6040516001600160a01b038216907f60305ce6c9104acd0969d358f926bf391174340660aaf5e6215261fd6847bf46905f90a250565b5f5f610fb75f610cde565b90505f5b8181101561106d575f610fce8183610ce7565b60405163d32c7bb560e01b81526001600160a01b038a811660048301528981166024830152888116604483015260648201889052919091169063d32c7bb590608401602060405180830381865afa15801561102b573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061104f9190611baf565b905060ff811615611064579250610684915050565b50600101610fbb565b505f9695505050505050565b5f5f6110845f610cde565b90505f5b81811015611132575f61109b8183610ce7565b60405163d4ce141560e01b81526001600160a01b038981166004830152888116602483015260448201889052919091169063d4ce141590606401602060405180830381865afa1580156110f0573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111149190611baf565b905060ff8116156111295792506108e3915050565b50600101611088565b505f95945050505050565b6111475f82611482565b61116457604051632cdc3a4160e21b815260040160405180910390fd5b6040516001600160a01b038216907f6d83315c9718799346b67584ec64301b1457e989c8e35a8e2982a7776c04bfc4905f90a250565b6111a2610cf2565b600780546001600160a01b0383166001600160a01b031990911681179091556111d36006546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b5f6001600160e01b031982166320c49ce760e01b148061123b57506001600160e01b0319821663157094b960e31b145b8061125657506001600160e01b031982166378a8de7d60e01b145b8061127157506001600160e01b03198216630c51264760e21b145b8061128c57506001600160e01b03198216633235d15f60e11b145b8061052957506001600160e01b03198216637157797f60e01b1492915050565b6112b581611496565b336001600160a01b038216148015906112e557506001600160a01b0381165f9081526005602052604090205460ff165b156105cb576105cb815f6109f3565b336001600160a01b03821614801561132357506001600160a01b0381165f9081526005602052604090205460ff165b1561132b5750565b6105cb6109e2565b610d415f82610c25565b5f6108e3836001600160a01b0384166114f7565b6060815f0180548060200260200160405190810160405280929190818152602001828054801561139e57602002820191905f5260205f20905b81548152602001906001019080831161138a575b50505050509050919050565b5f825f0182815481106113bf576113bf611a61565b905f5260205f200154905092915050565b600680546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b6105cb81611543565b6114338161159c565b61143e600382610c25565b1561145c576040516302925f7360e11b815260040160405180910390fd5b611465816115c3565b6105cb57604051639952e34360e01b815260040160405180910390fd5b5f6108e3836001600160a01b038416611600565b6114a1600382611482565b6114be57604051633477dd1760e01b815260040160405180910390fd5b6040516001600160a01b03821681527f28a4ca7134a3b3f9aff286e79ad3daadb4a06d1b43d037a3a98bdc074edd9b7a90602001610aaa565b5f81815260018301602052604081205461153c57508154600181810184555f848152602080822090930184905584548482528286019093526040902091909155610529565b505f610529565b5f61154c825490565b90505f5b8181101561159557826001015f845f01838154811061157157611571611a61565b905f5260205f20015481526020019081526020015f205f9055806001019050611550565b50505f9055565b6001600160a01b0381166105cb5760405163f9d152fb60e01b815260040160405180910390fd5b5f6115cd826116e3565b6115d857505f919050565b6115e9826358d34ba960e11b611722565b80610529575061052982632497d6cb60e01b611722565b5f81815260018301602052604081205480156116da575f611622600183611bca565b85549091505f9061163590600190611bca565b9050808214611694575f865f01828154811061165357611653611a61565b905f5260205f200154905080875f01848154811061167357611673611a61565b5f918252602080832090910192909255918252600188019052604090208390555b85548690806116a5576116a5611be9565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f905560019350505050610529565b5f915050610529565b5f6116f5826301ffc9a760e01b611722565b15610905575f8061170e846001600160e01b0319611743565b915091508180156106845750159392505050565b5f5f5f61172f8585611743565b915091508180156108cb5750949350505050565b6301ffc9a760e01b5f818152600483905290819060208260248188617530fa92505f511515601f3d11169150509250929050565b5f60208284031215611787575f5ffd5b81356001600160e01b0319811681146108e3575f5ffd5b5f5f83601f8401126117ae575f5ffd5b50813567ffffffffffffffff8111156117c5575f5ffd5b6020830191508360208260051b85010111156117df575f5ffd5b9250929050565b5f5f602083850312156117f7575f5ffd5b823567ffffffffffffffff81111561180d575f5ffd5b6118198582860161179e565b90969095509350505050565b6001600160a01b03811681146105cb575f5ffd5b80151581146105cb575f5ffd5b5f5f60408385031215611857575f5ffd5b823561186281611825565b9150602083013561187281611839565b809150509250929050565b5f6020828403121561188d575f5ffd5b5035919050565b5f5f5f5f608085870312156118a7575f5ffd5b84356118b281611825565b935060208501356118c281611825565b925060408501356118d281611825565b9396929550929360600135925050565b5f602082840312156118f2575f5ffd5b81356108e381611825565b602080825282518282018190525f918401906040840190835b8181101561193d5783516001600160a01b0316835260209384019390920191600101611916565b509095945050505050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b5f5f6040838503121561198e575f5ffd5b823561199981611825565b946020939093013593505050565b60ff811681146105cb575f5ffd5b5f602082840312156119c5575f5ffd5b81356108e3816119a7565b5f5f5f606084860312156119e2575f5ffd5b83356119ed81611825565b925060208401356119fd81611825565b929592945050506040919091013590565b5f5f5f60408486031215611a20575f5ffd5b833567ffffffffffffffff811115611a36575f5ffd5b611a428682870161179e565b9094509250506020840135611a5681611839565b809150509250925092565b634e487b7160e01b5f52603260045260245ffd5b604080825281018390525f8460608301825b86811015611ab7578235611a9a81611825565b6001600160a01b0316825260209283019290910190600101611a87565b5080925050508215156020830152949350505050565b5f60208284031215611add575f5ffd5b81516108e381611839565b634e487b7160e01b5f52604160045260245ffd5b5f60208284031215611b0c575f5ffd5b815167ffffffffffffffff811115611b22575f5ffd5b8201601f81018413611b32575f5ffd5b805167ffffffffffffffff811115611b4c57611b4c611ae8565b604051601f8201601f19908116603f0116810167ffffffffffffffff81118282101715611b7b57611b7b611ae8565b604052818152828201602001861015611b92575f5ffd5b8160208401602083015e5f91810160200191909152949350505050565b5f60208284031215611bbf575f5ffd5b81516108e3816119a7565b8181038181111561052957634e487b7160e01b5f52601160045260245ffd5b634e487b7160e01b5f52603160045260245ffdfea2646970667358221220abfb7ca5d60f80b565f0f276bbabc522f01859bc1b7929a3ded4de56b59eece064736f6c63430008250033","sourceMap":"677:2427:34:-:0;;;537:2:80;1188:46:69;;1057:108:34;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;1155:6;1132:13;-1:-1:-1;;;;;1101:27:29;;;1097:83;;1144:25;1155:13;1144:10;:25::i;:::-;1279:31;537:2:80;1279:12:29;:31::i;:::-;-1:-1:-1;;;;;;1273:26:10;;1269:95;;1322:31;;-1:-1:-1;;;1322:31:10;;1350:1;1322:31;;;640:51:83;613:18;;1322:31:10;;;;;;;1269:95;1373:32;1392:12;1373:18;:32::i;:::-;1225:187;1057:108:34;;677:2427;;4440:400:71;-1:-1:-1;;;;;4510:19:71;;4502:64;;;;-1:-1:-1;;;4502:64:71;;;;;;;;;;;;4576:26;4596:5;4576:19;:26::i;:::-;4743:23;:12;4760:5;4743:16;:23::i;:::-;4735:66;;;;-1:-1:-1;;;4735:66:71;;;;;;;;;;;;4816:17;;-1:-1:-1;;;;;658:32:83;;640:51;;4816:17:71;;628:2:83;613:18;4816:17:71;;;;;;;;4440:400;:::o;6050:225:69:-;6126:9;6139:1;6126:14;6118:82;;;;-1:-1:-1;;;6118:82:69;;;;;;;;;;;;6210:9;:21;;;6246:22;;848:25:83;;;6246:22:69;;836:2:83;821:18;6246:22:69;702:177:83;2011:153:11;2100:13;2093:20;;-1:-1:-1;;;;;;2093:20:11;;;2123:34;2148:8;2123:24;:34::i;:::-;2011:153;:::o;9793:195:28:-;9887:22;:6;9903:5;9887:15;:22::i;:::-;9886:23;9878:103;;;;-1:-1:-1;;;9878:103:28;;;;;;;;;;;16462:150:27;16532:4;16555:50;16560:3;-1:-1:-1;;;;;16580:23:27;;16555:4;:50::i;:::-;16548:57;;16462:150;;;;;:::o;2912:187:10:-;3004:6;;;-1:-1:-1;;;;;3020:17:10;;;-1:-1:-1;;;;;;3020:17:10;;;;;;;3052:40;;3004:6;;;3020:17;3004:6;;3052:40;;2985:16;;3052:40;2975:124;2912:187;:::o;17414:165:27:-;-1:-1:-1;;;;;17547:23:27;;17494:4;5238:21;;;:14;;;:21;;;;;;:26;;17517:55;5142:129;2538:406;2601:4;5238:21;;;:14;;;:21;;;;;;2617:321;;-1:-1:-1;2659:23:27;;;;;;;;:11;:23;;;;;;;;;;;;;2841:18;;2817:21;;;:14;;;:21;;;;;;:42;;;;2873:11;;2617:321;-1:-1:-1;2922:5:27;2915:12;;14:177:83;93:13;;-1:-1:-1;;;;;135:31:83;;125:42;;115:70;;181:1;178;171:12;115:70;14:177;;;:::o;196:293::-;275:6;283;336:2;324:9;315:7;311:23;307:32;304:52;;;352:1;349;342:12;304:52;375:40;405:9;375:40;:::i;:::-;365:50;;434:49;479:2;468:9;464:18;434:49;:::i;:::-;424:59;;196:293;;;;;:::o;702:177::-;677:2427:34;;;;;;","linkReferences":{}},"deployedBytecode":{"object":"0x608060405234801561000f575f5ffd5b506004361061021e575f3560e01c80638d2ea7721161012a578063d4ce1415116100b4578063e3c4602c11610079578063e3c4602c146104bc578063e46638e6146104cf578063e54621d2146104e2578063f2fde38b146104ea578063f76bf550146104fd575f5ffd5b8063d4ce141514610447578063db18af6c1461045a578063db75d0171461046d578063df21950f14610498578063e30c3978146104ab575f5ffd5b8063b27aef3a116100fa578063b27aef3a146103e1578063bb4b6121146103f4578063bc13eacc14610407578063c7c24b181461040f578063d32c7bb514610422575f5ffd5b80638d2ea772146103a25780638da5cb5b146103b5578063993e8b95146103c6578063b043572e146103d9575f5ffd5b806354fd4d50116101ab578063715018a61161017b578063715018a6146103595780637157797f1461036157806379ba5097146103745780637f4ab1dd1461037c5780638baf29b41461038f575f5ffd5b806354fd4d50146102e65780635f8dead3146103145780636a3edf28146103275780636ae728c614610347575f5ffd5b80633e5af4ca116101f15780633e5af4ca146102855780633ff5aa021461029857806340db3b50146102ab57806352f6747a146102be57806354e4b945146102d3575f5ffd5b806301ffc9a7146102225780631455d0e71461024a5780633284a9a51461025f5780633a56d6d514610272575b5f5ffd5b610235610230366004611777565b610505565b60405190151581526020015b60405180910390f35b61025d6102583660046117e6565b61052f565b005b61025d61026d366004611846565b61057d565b61025d61028036600461187d565b6105ba565b61025d610293366004611894565b6105ce565b61025d6102a63660046118e2565b6105e8565b61025d6102b93660046118e2565b6105fa565b6102c661060c565b60405161024191906118fd565b6102356102e13660046118e2565b61061c565b604080518082019091526009815268332e302e302d72633760b81b60208201525b6040516102419190611948565b61025d61032236600461197d565b610627565b61032f61063a565b6040516001600160a01b039091168152602001610241565b6002545b604051908152602001610241565b61025d61065c565b61023561036f366004611894565b61066f565b61025d61068c565b61030761038a3660046119b5565b61069d565b61025d61039d3660046119d0565b6106a8565b61025d6103b036600461197d565b6106bb565b6006546001600160a01b031661032f565b6102356103d43660046118e2565b6106ce565b61025d6106da565b61025d6103ef3660046117e6565b6106ea565b61025d610402366004611a0e565b61079d565b61034b61086b565b61025d61041d3660046117e6565b610875565b610435610430366004611894565b6108be565b60405160ff9091168152602001610241565b6104356104553660046119d0565b6108d4565b61032f61046836600461187d565b6108ea565b61023561047b3660046118e2565b6001600160a01b03165f9081526005602052604090205460ff1690565b61025d6104a63660046118e2565b61090c565b6007546001600160a01b031661032f565b61025d6104ca3660046118e2565b61091d565b6102356104dd3660046119d0565b61095f565b6102c6610978565b61025d6104f83660046118e2565b610984565b61034b600a81565b5f6001600160e01b03198216639ab669ef60e01b148061052957506105298261099e565b92915050565b6105376109e2565b5f5b818110156105785761057083838381811061055657610556611a61565b905060200201602081019061056b91906118e2565b6109ea565b600101610539565b505050565b6105856109e2565b6001600160a01b0382166105ac5760405163135217db60e21b815260040160405180910390fd5b6105b682826109f3565b5050565b6105c2610a51565b6105cb81610a59565b50565b6105d6610ab5565b6105e284848484610add565b50505050565b6105f181610b7f565b6105cb81610b88565b61060381610b7f565b6105cb816109ea565b60606106175f610c19565b905090565b5f6105298183610c25565b61062f610ab5565b6105b65f8383610c45565b5f5f6106466003610cde565b11156106575761061760035f610ce7565b505f90565b610664610cf2565b61066d5f610d1f565b565b5f8061067d868686866108be565b60ff161490505b949350505050565b61069533610d38565b61066d610d5f565b606061052982610da0565b6106b0610ab5565b610578838383610c45565b6106c3610ab5565b6105b6825f83610c45565b5f610529600383610c25565b6106e2610a51565b61066d610f15565b6106f2610a51565b5f819003610713576040516359203cb960e01b815260040160405180910390fd5b6002548082111561074357604051630befc49d60e01b815260040161073a91815260200190565b60405180910390fd5b505f61074e5f610cde565b111561075c5761075c610f15565b5f5b818110156105785761079583838381811061077b5761077b611a61565b905060200201602081019061079091906118e2565b610f46565b60010161075e565b6107a56109e2565b5f5b8281101561082a575f8484838181106107c2576107c2611a61565b90506020020160208101906107d791906118e2565b90506001600160a01b0381166108005760405163135217db60e21b815260040160405180910390fd5b6001600160a01b03165f908152600560205260409020805460ff19168315151790556001016107a7565b507f430881f04f203566ee9b32d6444cf02e1b2a0f17ab6b4263a1ee2074d3d0f48383838360405161085e93929190611a75565b60405180910390a1505050565b5f6106175f610cde565b61087d6109e2565b5f5b81811015610578576108b683838381811061089c5761089c611a61565b90506020020160208101906108b191906118e2565b610b88565b60010161087f565b5f6108cb85858585610fac565b95945050505050565b5f6108e0848484611079565b90505b9392505050565b5f6108f45f610cde565b821015610905576105295f83610ce7565b505f919050565b610914610a51565b6105cb8161113d565b610925610a51565b600254806109325f610cde565b10819061095557604051630befc49d60e01b815260040161073a91815260200190565b506105b682610f46565b5f8061096c8585856108d4565b60ff1614949350505050565b60606106176003610c19565b61098c610cf2565b61099581610d38565b6105cb8161119a565b5f6109a88261120b565b806109c357506001600160e01b031982166307f5828d60e41b145b8061052957506301ffc9a760e01b6001600160e01b0319831614610529565b61066d610a51565b6105cb816112ac565b6001600160a01b0382165f81815260056020908152604091829020805460ff191685151590811790915591519182527f407b412a9b6db334d48445ec9bcad46fb50bc4b2e97f73e963e397101957a729910160405180910390a25050565b61066d610cf2565b805f03610a7957604051631e69e71760e21b815260040160405180910390fd5b60028190556040518181527f2292ad4720fff63e2bd104c6b1c0d72c2c729a6001c8ab4bb947cbcc51109863906020015b60405180910390a150565b610ac0600333610c25565b61066d57604051630599c0e960e01b815260040160405180910390fd5b5f610ae75f610cde565b90505f5b81811015610b7757610afd5f82610ce7565b604051631f2d7a6560e11b81526001600160a01b03888116600483015287811660248301528681166044830152606482018690529190911690633e5af4ca906084015f604051808303815f87803b158015610b56575f5ffd5b505af1158015610b68573d5f5f3e3d5ffd5b50505050806001019050610aeb565b505050505050565b6105cb816112f4565b6001600160a01b038116610baf5760405163135217db60e21b815260040160405180910390fd5b610bb881611333565b610bc360038261133d565b610be0576040516371b3c56560e11b815260040160405180910390fd5b6040516001600160a01b03821681527f2de35142b19ed5a07796cf30791959c592018f70b1d2d7c460eef8ffe713692b90602001610aaa565b60605f6108e383611351565b6001600160a01b03165f9081526001919091016020526040902054151590565b5f610c4f5f610cde565b90505f5b81811015610cd757610c655f82610ce7565b6040516322ebca6d60e21b81526001600160a01b0387811660048301528681166024830152604482018690529190911690638baf29b4906064015f604051808303815f87803b158015610cb6575f5ffd5b505af1158015610cc8573d5f5f3e3d5ffd5b50505050806001019050610c53565b5050505050565b5f610529825490565b5f6108e383836113aa565b6006546001600160a01b0316331461066d5760405163118cdaa760e01b815233600482015260240161073a565b600780546001600160a01b03191690556105cb816113d0565b610d418161061c565b156105cb576040516302925f7360e11b815260040160405180910390fd5b60075433906001600160a01b03168114610d975760405163118cdaa760e01b81526001600160a01b038216600482015260240161073a565b6105cb81610d1f565b606060ff8216610dd357505060408051808201909152600d81526c2737a932b9ba3934b1ba34b7b760991b602082015290565b5f610ddd5f610cde565b90505f5b81811015610ed9575f610df48183610ce7565b604051633e822efb60e11b815260ff871660048201529091506001600160a01b03821690637d045df690602401602060405180830381865afa158015610e3c573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e609190611acd565b15610ed057604051637f4ab1dd60e01b815260ff861660048201526001600160a01b03821690637f4ab1dd906024015f60405180830381865afa158015610ea9573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526108cb9190810190611afc565b50600101610de1565b505060408051808201909152601881527f556e6b6e6f776e207265737472696374696f6e20636f64650000000000000000602082015292915050565b6040517fdbf61473843cd9be1c9791ce51ef66d0da6c9026d62ba80c1ca433b13fb729b2905f90a161066d5f611421565b610f4f8161142a565b610f595f8261133d565b610f765760405163cc790a4b60e01b815260040160405180910390fd5b6040516001600160a01b038216907f60305ce6c9104acd0969d358f926bf391174340660aaf5e6215261fd6847bf46905f90a250565b5f5f610fb75f610cde565b90505f5b8181101561106d575f610fce8183610ce7565b60405163d32c7bb560e01b81526001600160a01b038a811660048301528981166024830152888116604483015260648201889052919091169063d32c7bb590608401602060405180830381865afa15801561102b573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061104f9190611baf565b905060ff811615611064579250610684915050565b50600101610fbb565b505f9695505050505050565b5f5f6110845f610cde565b90505f5b81811015611132575f61109b8183610ce7565b60405163d4ce141560e01b81526001600160a01b038981166004830152888116602483015260448201889052919091169063d4ce141590606401602060405180830381865afa1580156110f0573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111149190611baf565b905060ff8116156111295792506108e3915050565b50600101611088565b505f95945050505050565b6111475f82611482565b61116457604051632cdc3a4160e21b815260040160405180910390fd5b6040516001600160a01b038216907f6d83315c9718799346b67584ec64301b1457e989c8e35a8e2982a7776c04bfc4905f90a250565b6111a2610cf2565b600780546001600160a01b0383166001600160a01b031990911681179091556111d36006546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b5f6001600160e01b031982166320c49ce760e01b148061123b57506001600160e01b0319821663157094b960e31b145b8061125657506001600160e01b031982166378a8de7d60e01b145b8061127157506001600160e01b03198216630c51264760e21b145b8061128c57506001600160e01b03198216633235d15f60e11b145b8061052957506001600160e01b03198216637157797f60e01b1492915050565b6112b581611496565b336001600160a01b038216148015906112e557506001600160a01b0381165f9081526005602052604090205460ff165b156105cb576105cb815f6109f3565b336001600160a01b03821614801561132357506001600160a01b0381165f9081526005602052604090205460ff165b1561132b5750565b6105cb6109e2565b610d415f82610c25565b5f6108e3836001600160a01b0384166114f7565b6060815f0180548060200260200160405190810160405280929190818152602001828054801561139e57602002820191905f5260205f20905b81548152602001906001019080831161138a575b50505050509050919050565b5f825f0182815481106113bf576113bf611a61565b905f5260205f200154905092915050565b600680546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b6105cb81611543565b6114338161159c565b61143e600382610c25565b1561145c576040516302925f7360e11b815260040160405180910390fd5b611465816115c3565b6105cb57604051639952e34360e01b815260040160405180910390fd5b5f6108e3836001600160a01b038416611600565b6114a1600382611482565b6114be57604051633477dd1760e01b815260040160405180910390fd5b6040516001600160a01b03821681527f28a4ca7134a3b3f9aff286e79ad3daadb4a06d1b43d037a3a98bdc074edd9b7a90602001610aaa565b5f81815260018301602052604081205461153c57508154600181810184555f848152602080822090930184905584548482528286019093526040902091909155610529565b505f610529565b5f61154c825490565b90505f5b8181101561159557826001015f845f01838154811061157157611571611a61565b905f5260205f20015481526020019081526020015f205f9055806001019050611550565b50505f9055565b6001600160a01b0381166105cb5760405163f9d152fb60e01b815260040160405180910390fd5b5f6115cd826116e3565b6115d857505f919050565b6115e9826358d34ba960e11b611722565b80610529575061052982632497d6cb60e01b611722565b5f81815260018301602052604081205480156116da575f611622600183611bca565b85549091505f9061163590600190611bca565b9050808214611694575f865f01828154811061165357611653611a61565b905f5260205f200154905080875f01848154811061167357611673611a61565b5f918252602080832090910192909255918252600188019052604090208390555b85548690806116a5576116a5611be9565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f905560019350505050610529565b5f915050610529565b5f6116f5826301ffc9a760e01b611722565b15610905575f8061170e846001600160e01b0319611743565b915091508180156106845750159392505050565b5f5f5f61172f8585611743565b915091508180156108cb5750949350505050565b6301ffc9a760e01b5f818152600483905290819060208260248188617530fa92505f511515601f3d11169150509250929050565b5f60208284031215611787575f5ffd5b81356001600160e01b0319811681146108e3575f5ffd5b5f5f83601f8401126117ae575f5ffd5b50813567ffffffffffffffff8111156117c5575f5ffd5b6020830191508360208260051b85010111156117df575f5ffd5b9250929050565b5f5f602083850312156117f7575f5ffd5b823567ffffffffffffffff81111561180d575f5ffd5b6118198582860161179e565b90969095509350505050565b6001600160a01b03811681146105cb575f5ffd5b80151581146105cb575f5ffd5b5f5f60408385031215611857575f5ffd5b823561186281611825565b9150602083013561187281611839565b809150509250929050565b5f6020828403121561188d575f5ffd5b5035919050565b5f5f5f5f608085870312156118a7575f5ffd5b84356118b281611825565b935060208501356118c281611825565b925060408501356118d281611825565b9396929550929360600135925050565b5f602082840312156118f2575f5ffd5b81356108e381611825565b602080825282518282018190525f918401906040840190835b8181101561193d5783516001600160a01b0316835260209384019390920191600101611916565b509095945050505050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b5f5f6040838503121561198e575f5ffd5b823561199981611825565b946020939093013593505050565b60ff811681146105cb575f5ffd5b5f602082840312156119c5575f5ffd5b81356108e3816119a7565b5f5f5f606084860312156119e2575f5ffd5b83356119ed81611825565b925060208401356119fd81611825565b929592945050506040919091013590565b5f5f5f60408486031215611a20575f5ffd5b833567ffffffffffffffff811115611a36575f5ffd5b611a428682870161179e565b9094509250506020840135611a5681611839565b809150509250925092565b634e487b7160e01b5f52603260045260245ffd5b604080825281018390525f8460608301825b86811015611ab7578235611a9a81611825565b6001600160a01b0316825260209283019290910190600101611a87565b5080925050508215156020830152949350505050565b5f60208284031215611add575f5ffd5b81516108e381611839565b634e487b7160e01b5f52604160045260245ffd5b5f60208284031215611b0c575f5ffd5b815167ffffffffffffffff811115611b22575f5ffd5b8201601f81018413611b32575f5ffd5b805167ffffffffffffffff811115611b4c57611b4c611ae8565b604051601f8201601f19908116603f0116810167ffffffffffffffff81118282101715611b7b57611b7b611ae8565b604052818152828201602001861015611b92575f5ffd5b8160208401602083015e5f91810160200191909152949350505050565b5f60208284031215611bbf575f5ffd5b81516108e3816119a7565b8181038181111561052957634e487b7160e01b5f52601160045260245ffd5b634e487b7160e01b5f52603160045260245ffdfea2646970667358221220abfb7ca5d60f80b565f0f276bbabc522f01859bc1b7929a3ded4de56b59eece064736f6c63430008250033","sourceMap":"677:2427:34:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2290:319;;;;;;:::i;:::-;;:::i;:::-;;;470:14:83;;463:22;445:41;;433:2;418:18;2290:319:34;;;;;;;;1872:205:70;;;;;;:::i;:::-;;:::i;:::-;;2125:251;;;;;;:::i;:::-;;:::i;3487:150:69:-;;;;;;:::i;:::-;;:::i;2583:330:28:-;;;;;;:::i;:::-;;:::i;2979:137:71:-;;;;;;:::i;:::-;;:::i;3404:141::-;;;;;;:::i;:::-;;:::i;5029:136:69:-;;;:::i;:::-;;;;;;;:::i;4333:158::-;;;;;;:::i;:::-;;:::i;737:129:72:-;852:7;;;;;;;;;;;;-1:-1:-1;;;852:7:72;;;;737:129;;;;;;;:::i;3239:155:28:-;;;;;;:::i;:::-;;:::i;2211:383:68:-;;;:::i;:::-;;;-1:-1:-1;;;;;4963:32:83;;;4945:51;;4933:2;4918:18;2211:383:68;4799:203:83;3949:124:69;4057:9;;3949:124;;;5153:25:83;;;5141:2;5126:18;3949:124:69;5007:177:83;2293:101:10;;;:::i;5266:311:28:-;;;;;;:::i;:::-;;:::i;1876:175:34:-;;;:::i;4621:240:28:-;;;;;;:::i;:::-;;:::i;2982:212::-;;;;;;:::i;:::-;;:::i;3439:161::-;;;;;;:::i;:::-;;:::i;1638:85:10:-;1710:6;;-1:-1:-1;;;;;1710:6:10;1638:85;;3636:133:71;;;;;;:::i;:::-;;:::i;2691:117:69:-;;;:::i;2150:477::-;;;;;;:::i;:::-;;:::i;2424:478:70:-;;;;;;:::i;:::-;;:::i;4137:132:69:-;;;:::i;1623:201:70:-;;;;;;:::i;:::-;;:::i;4289:282:28:-;;;;;;:::i;:::-;;:::i;:::-;;;7269:4:83;7257:17;;;7239:36;;7227:2;7212:18;4289:282:28;7097:184:83;3991:242:28;;;;;;:::i;:::-;;:::i;4555:410:69:-;;;;;;:::i;:::-;;:::i;3001:151:70:-;;;;;;:::i;:::-;-1:-1:-1;;;;;3113:32:70;3090:4;3113:32;;;:25;:32;;;;;;;;;3001:151;3701:133:69;;;;;;:::i;:::-;;:::i;1232:99:11:-;1311:13;;-1:-1:-1;;;;;1311:13:11;1232:99;;3040:383:69;;;;;;:::i;:::-;;:::i;4925:281:28:-;;;;;;:::i;:::-;;:::i;3200:127:70:-;;;:::i;1365:209:34:-;;;;;;:::i;:::-;;:::i;493:46:80:-;;537:2;493:46;;2290:319:34;2440:4;-1:-1:-1;;;;;;2467:65:34;;-1:-1:-1;;;2467:65:34;;:135;;;2548:54;2590:11;2548:41;:54::i;:::-;2460:142;2290:319;-1:-1:-1;;2290:319:34:o;1872:205:70:-;2185:26:71;:24;:26::i;:::-;1984:9:70::1;1979:92;1999:17:::0;;::::1;1979:92;;;2037:23;2050:6;;2057:1;2050:9;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;2037:12;:23::i;:::-;2018:3;;1979:92;;;;1872:205:::0;;:::o;2125:251::-;2185:26:71;:24;:26::i;:::-;-1:-1:-1;;;;;2258:19:70;::::1;2250:64;;;;-1:-1:-1::0;;;2250:64:70::1;;;;;;;;;;;;2324:45;2353:5;2360:8;2324:28;:45::i;:::-;2125:251:::0;;:::o;3487:150:69:-;880:24;:22;:24::i;:::-;3607:23:::1;3620:9;3607:12;:23::i;:::-;3487:150:::0;:::o;2583:330:28:-;2002:18:71;:16;:18::i;:::-;2846:60:28::1;2881:7;2890:4;2896:2;2900:5;2846:34;:60::i;:::-;2583:330:::0;;;;:::o;2979:137:71:-;3047:35;3076:5;3047:28;:35::i;:::-;3092:17;3103:5;3092:10;:17::i;3404:141::-;3474:35;3503:5;3474:28;:35::i;:::-;3519:19;3532:5;3519:12;:19::i;5029:136:69:-;5108:16;5143:15;:6;:13;:15::i;:::-;5136:22;;5029:136;:::o;4333:158::-;4430:4;4453:31;4430:4;4477:5;4453:15;:31::i;3239:155:28:-;2002:18:71;:16;:18::i;:::-;3352:35:28::1;3373:1;3377:2;3381:5;3352:12;:35::i;2211:383:68:-:0;2274:7;2321:1;2297:21;:12;:19;:21::i;:::-;:25;2293:295;;;2510:19;:12;2527:1;2510:16;:19::i;2293:295::-;-1:-1:-1;2575:1:68;;2211:383::o;2293:101:10:-;1531:13;:11;:13::i;:::-;2357:30:::1;2384:1;2357:18;:30::i;:::-;2293:101::o:0;5266:311:28:-;5447:4;;5474:55;5504:7;5513:4;5519:2;5523:5;5474:29;:55::i;:::-;:96;;;5467:103;;5266:311;;;;;;;:::o;1876:175:34:-;1937:67;735:10:18;1937:53:34;:67::i;:::-;2014:30;:28;:30::i;4621:240:28:-;4771:13;4807:47;4838:15;4807:30;:47::i;2982:212::-;2002:18:71;:16;:18::i;:::-;3158:29:28::1;3171:4;3177:2;3181:5;3158:12;:29::i;3439:161::-:0;2002:18:71;:16;:18::i;:::-;3556:37:28::1;3569:4;3583:1;3587:5;3556:12;:37::i;3636:133:71:-:0;3711:4;3734:28;:12;3756:5;3734:21;:28::i;2691:117:69:-;794:19;:17;:19::i;:::-;2788:13:::1;:11;:13::i;2150:477::-:0;794:19;:17;:19::i;:::-;2293:1:::1;2276:18:::0;;;2268:76:::1;;;;-1:-1:-1::0;;;2268:76:69::1;;;;;;;;;;;;2379:9;::::0;2362:26;;::::1;;2354:97;;;;-1:-1:-1::0;;;2354:97:69::1;;;;;;5153:25:83::0;;5141:2;5126:18;;5007:177;2354:97:69::1;;;;;;;;;;2483:1;2465:15;:6;:13;:15::i;:::-;:19;2461:63;;;2500:13;:11;:13::i;:::-;2538:9;2533:88;2553:17:::0;;::::1;2533:88;;;2591:19;2600:6;;2607:1;2600:9;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;2591:8;:19::i;:::-;2572:3;;2533:88;;2424:478:70::0;2185:26:71;:24;:26::i;:::-;2607:9:70::1;2602:229;2622:17:::0;;::::1;2602:229;;;2660:13;2676:6;;2683:1;2676:9;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;2660:25:::0;-1:-1:-1;;;;;;2707:19:70;::::1;2699:64;;;;-1:-1:-1::0;;;2699:64:70::1;;;;;;;;;;;;-1:-1:-1::0;;;;;2777:32:70::1;;::::0;;;:25:::1;:32;::::0;;;;:43;;-1:-1:-1;;2777:43:70::1;::::0;::::1;;;::::0;;-1:-1:-1;2641:3:70::1;2602:229;;;;2845:50;2878:6;;2886:8;2845:50;;;;;;;;:::i;:::-;;;;;;;;2424:478:::0;;;:::o;4137:132:69:-;4221:7;4247:15;:6;:13;:15::i;1623:201:70:-;2185:26:71;:24;:26::i;:::-;1733:9:70::1;1728:90;1748:17:::0;;::::1;1728:90;;;1786:21;1797:6;;1804:1;1797:9;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;1786:10;:21::i;:::-;1767:3;;1728:90;;4289:282:28::0;4480:5;4508:56;4539:7;4548:4;4554:2;4558:5;4508:30;:56::i;:::-;4501:63;4289:282;-1:-1:-1;;;;;4289:282:28:o;3991:242::-;4155:5;4183:43;4210:4;4216:2;4220:5;4183:26;:43::i;:::-;4176:50;;3991:242;;;;;;:::o;4555:410:69:-;4647:7;4679:15;:6;:13;:15::i;:::-;4670:6;:24;4666:293;;;4882:18;:6;4893;4882:10;:18::i;4666:293::-;-1:-1:-1;4946:1:69;;4555:410;-1:-1:-1;4555:410:69:o;3701:133::-;794:19;:17;:19::i;:::-;3809:18:::1;3821:5;3809:11;:18::i;3040:383::-:0;794:19;:17;:19::i;:::-;3274:9:::1;::::0;;3301:15:::1;3254:17;3301:13;:15::i;:::-;:27;3380:9;3293:98;;;;;-1:-1:-1::0;;;3293:98:69::1;;;;;;5153:25:83::0;;5141:2;5126:18;;5007:177;3293:98:69::1;;3401:15;3410:5;3401:8;:15::i;4925:281:28:-:0;5089:4;;5116:42;5142:4;5148:2;5152:5;5116:25;:42::i;:::-;:83;;;;4925:281;-1:-1:-1;;;;4925:281:28:o;3200:127:70:-;3264:16;3299:21;:12;:19;:21::i;1365:209:34:-;1531:13:10;:11;:13::i;:::-;1454:63:34::1;1508:8;1454:53;:63::i;:::-;1527:40;1558:8;1527:30;:40::i;1556:288:29:-:0;1658:4;1681:45;1714:11;1681:32;:45::i;:::-;:103;;;-1:-1:-1;;;;;;;1730:54:29;;-1:-1:-1;;;1730:54:29;1681:103;:156;;;-1:-1:-1;;;;;;;;;;829:40:22;;;1800:37:29;730:146:22;2998:103:68;3070:24;:22;:24::i;2008:174:67:-;2129:46;2169:5;2129:39;:46::i;4883:204:70:-;-1:-1:-1;;;;;4978:32:70;;;;;;:25;:32;;;;;;;;;:43;;-1:-1:-1;;4978:43:70;;;;;;;;;;5036:44;;445:41:83;;;5036:44:70;;418:18:83;5036:44:70;;;;;;;4883:204;;:::o;2881:72:34:-;1531:13:10;:11;:13::i;6050:225:69:-;6126:9;6139:1;6126:14;6118:82;;;;-1:-1:-1;;;6118:82:69;;;;;;;;;;;;6210:9;:21;;;6246:22;;5153:25:83;;;6246:22:69;;5141:2:83;5126:18;6246:22:69;;;;;;;;6050:225;:::o;6902:144:71:-;6970:33;:12;6992:10;6970:21;:33::i;:::-;6962:77;;;;-1:-1:-1;;;6962:77:71;;;;;;;;;;;9164:285:69;9271:19;9293:15;:6;:13;:15::i;:::-;9271:37;-1:-1:-1;9323:9:69;9318:125;9342:11;9338:1;:15;9318:125;;;9380:13;:6;9391:1;9380:10;:13::i;:::-;9374:58;;-1:-1:-1;;;9374:58:69;;-1:-1:-1;;;;;8575:32:83;;;9374:58:69;;;8557:51:83;8644:32;;;8624:18;;;8617:60;8713:32;;;8693:18;;;8686:60;8762:18;;;8755:34;;;9374:32:69;;;;;;;8529:19:83;;9374:58:69;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;9355:3;;;;;9318:125;;;;9261:188;9164:285;;;;:::o;1475:234:67:-;1640:62;1696:5;1640:55;:62::i;4440:400:71:-;-1:-1:-1;;;;;4510:19:71;;4502:64;;;;-1:-1:-1;;;4502:64:71;;;;;;;;;;;;4576:26;4596:5;4576:19;:26::i;:::-;4743:23;:12;4760:5;4743:16;:23::i;:::-;4735:66;;;;-1:-1:-1;;;4735:66:71;;;;;;;;;;;;4816:17;;-1:-1:-1;;;;;4963:32:83;;4945:51;;4816:17:71;;4933:2:83;4918:18;4816:17:71;4799:203:83;19500:273:27;19563:16;19591:22;19616:19;19624:3;19616:7;:19::i;17414:165::-;-1:-1:-1;;;;;17547:23:27;17494:4;5238:21;;;:14;;;;;:21;;;;;;:26;;;17414:165::o;8250:259:69:-;8340:19;8362:15;:6;:13;:15::i;:::-;8340:37;-1:-1:-1;8392:9:69;8387:116;8411:11;8407:1;:15;8387:116;;;8449:13;:6;8460:1;8449:10;:13::i;:::-;8443:49;;-1:-1:-1;;;8443:49:69;;-1:-1:-1;;;;;9020:32:83;;;8443:49:69;;;9002:51:83;9089:32;;;9069:18;;;9062:60;9138:18;;;9131:34;;;8443:32:69;;;;;;;8975:18:83;;8443:49:69;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8424:3;;;;;8387:116;;;;8330:179;8250:259;;;:::o;17660:115:27:-;17723:7;17749:19;17757:3;5434:18;;5352:107;18802:158;18877:7;18927:23;18932:3;18944:5;18927:4;:23::i;1796:162:10:-;1710:6;;-1:-1:-1;;;;;1710:6:10;735:10:18;1855:23:10;1851:101;;1901:40;;-1:-1:-1;;;1901:40:10;;735:10:18;1901:40:10;;;4945:51:83;4918:18;;1901:40:10;4799:203:83;2011:153:11;2100:13;2093:20;;-1:-1:-1;;;;;;2093:20:11;;;2123:34;2148:8;2123:24;:34::i;2022:206:29:-;2120:29;2139:8;2120:12;:29::i;:::-;2119:30;2111:110;;;;-1:-1:-1;;;2111:110:29;;;;;;;;;;;2244:229:11;1311:13;;735:10:18;;-1:-1:-1;;;;;1311:13:11;2339:24;;2335:96;;2386:34;;-1:-1:-1;;;2386:34:11;;-1:-1:-1;;;;;4963:32:83;;2386:34:11;;;4945:51:83;4918:18;;2386:34:11;4799:203:83;2335:96:11;2440:26;2459:6;2440:18;:26::i;8179:594:28:-;8273:13;8302:56;;;8298:110;;-1:-1:-1;;8381:16:28;;;;;;;;;;;;-1:-1:-1;;;8381:16:28;;;;;8179:594::o;8298:110::-;8417:19;8439:15;:6;:13;:15::i;:::-;8417:37;-1:-1:-1;8469:9:28;8464:267;8488:11;8484:1;:15;8464:267;;;8520:11;8540:13;8520:11;8551:1;8540:10;:13::i;:::-;8572:55;;-1:-1:-1;;;8572:55:28;;7269:4:83;7257:17;;8572:55:28;;;7239:36:83;8520:34:28;;-1:-1:-1;;;;;;8572:38:28;;;;;7212:18:83;;8572:55:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;8568:153;;;8654:52;;-1:-1:-1;;;8654:52:28;;7269:4:83;7257:17;;8654:52:28;;;7239:36:83;-1:-1:-1;;;;;8654:35:28;;;;;7212:18:83;;8654:52:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;8654:52:28;;;;;;;;;;;;:::i;8568:153::-;-1:-1:-1;8501:3:28;;8464:267;;;-1:-1:-1;;8747:19:28;;;;;;;;;;;;;;;;;;8179:594;-1:-1:-1;;8179:594:28:o;5444:98:69:-;5499:12;;;;;;;5521:14;:6;:12;:14::i;6762:312::-;6820:26;6839:5;6820:10;:26::i;:::-;6957;:6;6976:5;6957:10;:26::i;:::-;6949:89;;;;-1:-1:-1;;;6949:89:69;;;;;;;;;;;;7053:14;;-1:-1:-1;;;;;7053:14:69;;;;;;;;6762:312;:::o;6974:537:28:-;7135:5;7156:19;7178:15;:6;:13;:15::i;:::-;7156:37;-1:-1:-1;7208:9:28;7203:248;7227:11;7223:1;:15;7203:248;;;7259:17;7285:13;7259:17;7296:1;7285:10;:13::i;:::-;7279:76;;-1:-1:-1;;;7279:76:28;;-1:-1:-1;;;;;8575:32:83;;;7279:76:28;;;8557:51:83;8644:32;;;8624:18;;;8617:60;8713:32;;;8693:18;;;8686:60;8762:18;;;8755:34;;;7279:50:28;;;;;;;8529:19:83;;7279:76:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;7259:96;-1:-1:-1;7373:15:28;;;;7369:72;;7415:11;-1:-1:-1;7408:18:28;;-1:-1:-1;;7408:18:28;7369:72;-1:-1:-1;7240:3:28;;7203:248;;;-1:-1:-1;7473:30:28;7460:44;6974:537;-1:-1:-1;;;;;;6974:537:28:o;6110:467::-;6218:5;6235:19;6257:15;:6;:13;:15::i;:::-;6235:37;-1:-1:-1;6287:9:28;6282:235;6306:11;6302:1;:15;6282:235;;;6338:17;6364:13;6338:17;6375:1;6364:10;:13::i;:::-;6358:63;;-1:-1:-1;;;6358:63:28;;-1:-1:-1;;;;;9020:32:83;;;6358:63:28;;;9002:51:83;9089:32;;;9069:18;;;9062:60;9138:18;;;9131:34;;;6358:46:28;;;;;;;8975:18:83;;6358:63:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;6338:83;-1:-1:-1;6439:15:28;;;;6435:72;;6481:11;-1:-1:-1;6474:18:28;;-1:-1:-1;;6474:18:28;6435:72;-1:-1:-1;6319:3:28;;6282:235;;;-1:-1:-1;6539:30:28;6526:44;6110:467;-1:-1:-1;;;;;6110:467:28:o;7335:255:69:-;7470:29;:6;7492:5;7470:13;:29::i;:::-;7462:89;;;;-1:-1:-1;;;7462:89:69;;;;;;;;;;;;7566:17;;-1:-1:-1;;;;;7566:17:69;;;;;;;;7335:255;:::o;1649:178:11:-;1531:13:10;:11;:13::i;:::-;1738::11::1;:24:::0;;-1:-1:-1;;;;;1738:24:11;::::1;-1:-1:-1::0;;;;;;1738:24:11;;::::1;::::0;::::1;::::0;;;1802:7:::1;1710:6:10::0;;-1:-1:-1;;;;;1710:6:10;;1638:85;1802:7:11::1;-1:-1:-1::0;;;;;1777:43:11::1;;;;;;;;;;;1649:178:::0;:::o;11440:599:28:-;11533:4;-1:-1:-1;;;;;;11556:61:28;;-1:-1:-1;;;11556:61:28;;:132;;-1:-1:-1;;;;;;;11633:55:28;;-1:-1:-1;;;11633:55:28;11556:132;:214;;;-1:-1:-1;;;;;;;11704:66:28;;-1:-1:-1;;;11704:66:28;11556:214;:298;;;-1:-1:-1;;;;;;;11786:68:28;;-1:-1:-1;;;11786:68:28;11556:298;:391;;;-1:-1:-1;;;;;;;11870:77:28;;-1:-1:-1;;;11870:77:28;11556:391;:476;;;-1:-1:-1;;;;;;;11963:69:28;;-1:-1:-1;;;11963:69:28;11549:483;11440:599;-1:-1:-1;;11440:599:28:o;4275:255:70:-;4348:38;4380:5;4348:31;:38::i;:::-;4400:10;-1:-1:-1;;;;;4400:19:70;;;;;;:55;;-1:-1:-1;;;;;;4423:32:70;;;;;;:25;:32;;;;;;;;4400:55;4396:128;;;4471:42;4500:5;4507;4471:28;:42::i;5759:223::-;5852:10;-1:-1:-1;;;;;5852:19:70;;;:55;;;;-1:-1:-1;;;;;;5875:32:70;;;;;;:25;:32;;;;;;;;5852:55;5848:92;;;5759:223;:::o;5848:92::-;5949:26;:24;:26::i;9793:195:28:-;9887:22;:6;9903:5;9887:15;:22::i;16462:150:27:-;16532:4;16555:50;16560:3;-1:-1:-1;;;;;16580:23:27;;16555:4;:50::i;6460:109::-;6516:16;6551:3;:11;;6544:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6460:109;;;:::o;5801:119::-;5869:7;5895:3;:11;;5907:5;5895:18;;;;;;;;:::i;:::-;;;;;;;;;5888:25;;5801:119;;;;:::o;2912:187:10:-;3004:6;;;-1:-1:-1;;;;;3020:17:10;;;-1:-1:-1;;;;;;3020:17:10;;;;;;;3052:40;;3004:6;;;3020:17;3004:6;;3052:40;;2985:16;;3052:40;2975:124;2912:187;:::o;17250:83:27:-;17308:18;17315:3;17308:6;:18::i;9061:324:28:-;9137:39;9170:5;9137:32;:39::i;:::-;9195:28;:12;9217:5;9195:21;:28::i;:::-;9194:29;9186:109;;;;-1:-1:-1;;;9186:109:28;;;;;;;;;;;;9313:29;9336:5;9313:22;:29::i;:::-;9305:73;;;;-1:-1:-1;;;9305:73:28;;;;;;;;;;;16780:156:27;16853:4;16876:53;16884:3;-1:-1:-1;;;;;16904:23:27;;16876:7;:53::i;5410:294:71:-;5605:26;:12;5625:5;5605:19;:26::i;:::-;5597:65;;;;-1:-1:-1;;;5597:65:71;;;;;;;;;;;;5678:19;;-1:-1:-1;;;;;4963:32:83;;4945:51;;5678:19:71;;4933:2:83;4918:18;5678:19:71;4799:203:83;2538:406:27;2601:4;5238:21;;;:14;;;:21;;;;;;2617:321;;-1:-1:-1;2659:23:27;;;;;;;;:11;:23;;;;;;;;;;;;;2841:18;;2817:21;;;:14;;;:21;;;;;;:42;;;;2873:11;;2617:321;-1:-1:-1;2922:5:27;2915:12;;4824:237;4875:11;4889:12;4897:3;5434:18;;5352:107;4889:12;4875:26;-1:-1:-1;4916:9:27;4911:96;4935:3;4931:1;:7;4911:96;;;4966:3;:14;;:30;4981:3;:11;;4993:1;4981:14;;;;;;;;:::i;:::-;;;;;;;;;4966:30;;;;;;;;;;;4959:37;;;4940:3;;;;;4911:96;;;-1:-1:-1;;5039:11:27;34209:23:16;;2125:251:70:o;9974:164:69:-;-1:-1:-1;;;;;10049:19:69;;10041:90;;;;-1:-1:-1;;;10041:90:69;;;;;;;;;;;10702:397:28;10780:4;10801:35;10830:5;10801:28;:35::i;:::-;10796:79;;-1:-1:-1;10859:5:28;;10702:397;-1:-1:-1;10702:397:28:o;10796:79::-;10891:89;10938:5;-1:-1:-1;;;10891:46:28;:89::i;:::-;:201;;;-1:-1:-1;10996:96:28;11043:5;-1:-1:-1;;;10996:46:28;:96::i;3112:1368:27:-;3178:4;3307:21;;;:14;;;:21;;;;;;3343:13;;3339:1135;;3710:18;3731:12;3742:1;3731:8;:12;:::i;:::-;3777:18;;3710:33;;-1:-1:-1;3757:17:27;;3777:22;;3798:1;;3777:22;:::i;:::-;3757:42;;3832:9;3818:10;:23;3814:378;;3861:17;3881:3;:11;;3893:9;3881:22;;;;;;;;:::i;:::-;;;;;;;;;3861:42;;4028:9;4002:3;:11;;4014:10;4002:23;;;;;;;;:::i;:::-;;;;;;;;;;;;:35;;;;4141:25;;;:14;;;:25;;;;;:36;;;3814:378;4270:17;;:3;;:17;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;4373:3;:14;;:21;4388:5;4373:21;;;;;;;;;;;4366:28;;;4416:4;4409:11;;;;;;;3339:1135;4458:5;4451:12;;;;;719:528:23;783:4;976:68;1009:7;-1:-1:-1;;;976:32:23;:68::i;:::-;972:269;;;1061:12;;1093:52;1115:7;-1:-1:-1;;;;;;1093:21:23;:52::i;:::-;1060:85;;;;1166:7;:21;;;;-1:-1:-1;1177:10:23;;1159:28;-1:-1:-1;;;719:528:23:o;4504:238::-;4606:4;4623:12;4637:14;4655:43;4677:7;4686:11;4655:21;:43::i;:::-;4622:76;;;;4715:7;:20;;;;-1:-1:-1;4726:9:23;4708:27;-1:-1:-1;;;;4504:238:23:o;5198:628::-;-1:-1:-1;;;5310:12:23;5452:22;;;5494:4;5487:25;;;5310:12;;;5581:4;5310:12;5569:4;5310:12;5554:7;5547:5;5536:50;5525:61;;5740:4;5734:11;5727:19;5720:27;5654:4;5636:16;5633:26;5612:198;5599:211;;5438:382;5198:628;;;;;:::o;14:286:83:-;72:6;125:2;113:9;104:7;100:23;96:32;93:52;;;141:1;138;131:12;93:52;167:23;;-1:-1:-1;;;;;;219:32:83;;209:43;;199:71;;266:1;263;256:12;497:367;560:8;570:6;624:3;617:4;609:6;605:17;601:27;591:55;;642:1;639;632:12;591:55;-1:-1:-1;665:20:83;;708:18;697:30;;694:50;;;740:1;737;730:12;694:50;777:4;769:6;765:17;753:29;;837:3;830:4;820:6;817:1;813:14;805:6;801:27;797:38;794:47;791:67;;;854:1;851;844:12;791:67;497:367;;;;;:::o;869:437::-;955:6;963;1016:2;1004:9;995:7;991:23;987:32;984:52;;;1032:1;1029;1022:12;984:52;1072:9;1059:23;1105:18;1097:6;1094:30;1091:50;;;1137:1;1134;1127:12;1091:50;1176:70;1238:7;1229:6;1218:9;1214:22;1176:70;:::i;:::-;1265:8;;1150:96;;-1:-1:-1;869:437:83;-1:-1:-1;;;;869:437:83:o;1311:131::-;-1:-1:-1;;;;;1386:31:83;;1376:42;;1366:70;;1432:1;1429;1422:12;1447:118;1533:5;1526:13;1519:21;1512:5;1509:32;1499:60;;1555:1;1552;1545:12;1570:382;1635:6;1643;1696:2;1684:9;1675:7;1671:23;1667:32;1664:52;;;1712:1;1709;1702:12;1664:52;1751:9;1738:23;1770:31;1795:5;1770:31;:::i;:::-;1820:5;-1:-1:-1;1877:2:83;1862:18;;1849:32;1890:30;1849:32;1890:30;:::i;:::-;1939:7;1929:17;;;1570:382;;;;;:::o;1957:226::-;2016:6;2069:2;2057:9;2048:7;2044:23;2040:32;2037:52;;;2085:1;2082;2075:12;2037:52;-1:-1:-1;2130:23:83;;1957:226;-1:-1:-1;1957:226:83:o;2188:650::-;2274:6;2282;2290;2298;2351:3;2339:9;2330:7;2326:23;2322:33;2319:53;;;2368:1;2365;2358:12;2319:53;2407:9;2394:23;2426:31;2451:5;2426:31;:::i;:::-;2476:5;-1:-1:-1;2533:2:83;2518:18;;2505:32;2546:33;2505:32;2546:33;:::i;:::-;2598:7;-1:-1:-1;2657:2:83;2642:18;;2629:32;2670:33;2629:32;2670:33;:::i;:::-;2188:650;;;;-1:-1:-1;2722:7:83;;2802:2;2787:18;2774:32;;-1:-1:-1;;2188:650:83:o;2843:247::-;2902:6;2955:2;2943:9;2934:7;2930:23;2926:32;2923:52;;;2971:1;2968;2961:12;2923:52;3010:9;2997:23;3029:31;3054:5;3029:31;:::i;3095:637::-;3285:2;3297:21;;;3367:13;;3270:18;;;3389:22;;;3237:4;;3468:15;;;3442:2;3427:18;;;3237:4;3511:195;3525:6;3522:1;3519:13;3511:195;;;3590:13;;-1:-1:-1;;;;;3586:39:83;3574:52;;3655:2;3681:15;;;;3646:12;;;;3622:1;3540:9;3511:195;;;-1:-1:-1;3723:3:83;;3095:637;-1:-1:-1;;;;;3095:637:83:o;4004:418::-;4153:2;4142:9;4135:21;4116:4;4185:6;4179:13;4228:6;4223:2;4212:9;4208:18;4201:34;4287:6;4282:2;4274:6;4270:15;4265:2;4254:9;4250:18;4244:50;4343:1;4338:2;4329:6;4318:9;4314:22;4310:31;4303:42;4413:2;4406;4402:7;4397:2;4389:6;4385:15;4381:29;4370:9;4366:45;4362:54;4354:62;;;4004:418;;;;:::o;4427:367::-;4495:6;4503;4556:2;4544:9;4535:7;4531:23;4527:32;4524:52;;;4572:1;4569;4562:12;4524:52;4611:9;4598:23;4630:31;4655:5;4630:31;:::i;:::-;4680:5;4758:2;4743:18;;;;4730:32;;-1:-1:-1;;;4427:367:83:o;5189:114::-;5273:4;5266:5;5262:16;5255:5;5252:27;5242:55;;5293:1;5290;5283:12;5308:243;5365:6;5418:2;5406:9;5397:7;5393:23;5389:32;5386:52;;;5434:1;5431;5424:12;5386:52;5473:9;5460:23;5492:29;5515:5;5492:29;:::i;5556:508::-;5633:6;5641;5649;5702:2;5690:9;5681:7;5677:23;5673:32;5670:52;;;5718:1;5715;5708:12;5670:52;5757:9;5744:23;5776:31;5801:5;5776:31;:::i;:::-;5826:5;-1:-1:-1;5883:2:83;5868:18;;5855:32;5896:33;5855:32;5896:33;:::i;:::-;5556:508;;5948:7;;-1:-1:-1;;;6028:2:83;6013:18;;;;6000:32;;5556:508::o;6526:566::-;6618:6;6626;6634;6687:2;6675:9;6666:7;6662:23;6658:32;6655:52;;;6703:1;6700;6693:12;6655:52;6743:9;6730:23;6776:18;6768:6;6765:30;6762:50;;;6808:1;6805;6798:12;6762:50;6847:70;6909:7;6900:6;6889:9;6885:22;6847:70;:::i;:::-;6936:8;;-1:-1:-1;6821:96:83;-1:-1:-1;;7021:2:83;7006:18;;6993:32;7034:28;6993:32;7034:28;:::i;:::-;7081:5;7071:15;;;6526:566;;;;;:::o;7286:127::-;7347:10;7342:3;7338:20;7335:1;7328:31;7378:4;7375:1;7368:15;7402:4;7399:1;7392:15;7550:771;7772:2;7784:21;;;7757:18;;7840:22;;;7724:4;7919:6;7893:2;7878:18;;7724:4;7953:281;7967:6;7964:1;7961:13;7953:281;;;8042:6;8029:20;8062:31;8087:5;8062:31;:::i;:::-;-1:-1:-1;;;;;8118:31:83;8106:44;;8179:4;8207:17;;;;8170:14;;;;8146:1;7982:9;7953:281;;;7957:3;8251;8243:11;;;;8306:6;8299:14;8292:22;8285:4;8274:9;8270:20;8263:52;7550:771;;;;;;:::o;9176:245::-;9243:6;9296:2;9284:9;9275:7;9271:23;9267:32;9264:52;;;9312:1;9309;9302:12;9264:52;9344:9;9338:16;9363:28;9385:5;9363:28;:::i;9426:127::-;9487:10;9482:3;9478:20;9475:1;9468:31;9518:4;9515:1;9508:15;9542:4;9539:1;9532:15;9558:935;9638:6;9691:2;9679:9;9670:7;9666:23;9662:32;9659:52;;;9707:1;9704;9697:12;9659:52;9740:9;9734:16;9773:18;9765:6;9762:30;9759:50;;;9805:1;9802;9795:12;9759:50;9828:22;;9881:4;9873:13;;9869:27;-1:-1:-1;9859:55:83;;9910:1;9907;9900:12;9859:55;9943:2;9937:9;9969:18;9961:6;9958:30;9955:56;;;9991:18;;:::i;:::-;10040:2;10034:9;10132:2;10094:17;;-1:-1:-1;;10090:31:83;;;10123:2;10086:40;10082:54;10070:67;;10167:18;10152:34;;10188:22;;;10149:62;10146:88;;;10214:18;;:::i;:::-;10250:2;10243:22;10274;;;10315:15;;;10332:2;10311:24;10308:37;-1:-1:-1;10305:57:83;;;10358:1;10355;10348:12;10305:57;10407:6;10402:2;10398;10394:11;10389:2;10381:6;10377:15;10371:43;10460:1;10434:19;;;10455:2;10430:28;10423:39;;;;10438:6;9558:935;-1:-1:-1;;;;9558:935:83:o;10498:247::-;10566:6;10619:2;10607:9;10598:7;10594:23;10590:32;10587:52;;;10635:1;10632;10625:12;10587:52;10667:9;10661:16;10686:29;10709:5;10686:29;:::i;10750:225::-;10817:9;;;10838:11;;;10835:134;;;10891:10;10886:3;10882:20;10879:1;10872:31;10926:4;10923:1;10916:15;10954:4;10951:1;10944:15;10980:127;11041:10;11036:3;11032:20;11029:1;11022:31;11072:4;11069:1;11062:15;11096:4;11093:1;11086:15","linkReferences":{}},"methodIdentifiers":{"DEFAULT_MAX_RULES()":"f76bf550","acceptOwnership()":"79ba5097","addRule(address)":"e3c4602c","bindToken(address)":"3ff5aa02","bindTokens(address[])":"c7c24b18","canTransfer(address,address,uint256)":"e46638e6","canTransferFrom(address,address,address,uint256)":"7157797f","clearRules()":"b043572e","containsRule(address)":"54e4b945","created(address,uint256)":"5f8dead3","destroyed(address,uint256)":"8d2ea772","detectTransferRestriction(address,address,uint256)":"d4ce1415","detectTransferRestrictionFrom(address,address,address,uint256)":"d32c7bb5","getTokenBound()":"6a3edf28","getTokenBounds()":"e54621d2","isTokenBound(address)":"993e8b95","isTokenSelfBindingApproved(address)":"db75d017","maxRules()":"6ae728c6","messageForTransferRestriction(uint8)":"7f4ab1dd","owner()":"8da5cb5b","pendingOwner()":"e30c3978","removeRule(address)":"df21950f","renounceOwnership()":"715018a6","rule(uint256)":"db18af6c","rules()":"52f6747a","rulesCount()":"bc13eacc","setMaxRules(uint256)":"3a56d6d5","setRules(address[])":"b27aef3a","setTokenSelfBindingApproval(address,bool)":"3284a9a5","setTokenSelfBindingApprovalBatch(address[],bool)":"bb4b6121","supportsInterface(bytes4)":"01ffc9a7","transferOwnership(address)":"f2fde38b","transferred(address,address,address,uint256)":"3e5af4ca","transferred(address,address,uint256)":"8baf29b4","unbindToken(address)":"40db3b50","unbindTokens(address[])":"1455d0e7","version()":"54fd4d50"},"rawMetadata":"{\"compiler\":{\"version\":\"0.8.37+commit.f401782d\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenContract\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"OwnableInvalidOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"OwnableUnauthorizedAccount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_AdminWithAddressZeroNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_RuleInvalidInterface\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_RulesManagementModule_ArrayIsEmpty\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"maxRules\",\"type\":\"uint256\"}],\"name\":\"RuleEngine_RulesManagementModule_MaxRulesExceeded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_RulesManagementModule_MaxRulesZeroNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_RulesManagementModule_RuleAccountCannotReceivePrivileges\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_RulesManagementModule_RuleAddressZeroNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_RulesManagementModule_RuleAlreadyExists\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_RulesManagementModule_RuleDoNotMatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TokenBinding_InvalidTokenAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TokenBinding_TokenAlreadyBound\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TokenBinding_TokenNotBound\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TokenBinding_UnauthorizedCaller\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract IRule\",\"name\":\"rule\",\"type\":\"address\"}],\"name\":\"AddRule\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"ClearRules\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferStarted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract IRule\",\"name\":\"rule\",\"type\":\"address\"}],\"name\":\"RemoveRule\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"maxRules\",\"type\":\"uint256\"}],\"name\":\"SetMaxRules\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"TokenBound\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"tokens\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"TokenSelfBindingApprovalBatchSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"TokenSelfBindingApprovalSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"TokenUnbound\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DEFAULT_MAX_RULES\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IRule\",\"name\":\"rule_\",\"type\":\"address\"}],\"name\":\"addRule\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"bindToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"tokens\",\"type\":\"address[]\"}],\"name\":\"bindTokens\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"canTransfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"canTransferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"clearRules\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IRule\",\"name\":\"rule_\",\"type\":\"address\"}],\"name\":\"containsRule\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"created\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"destroyed\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"detectTransferRestriction\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"detectTransferRestrictionFrom\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTokenBound\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTokenBounds\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"isTokenBound\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"isTokenSelfBindingApproved\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"maxRules\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"restrictionCode\",\"type\":\"uint8\"}],\"name\":\"messageForTransferRestriction\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingOwner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IRule\",\"name\":\"rule_\",\"type\":\"address\"}],\"name\":\"removeRule\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"ruleId\",\"type\":\"uint256\"}],\"name\":\"rule\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"rules\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"rulesCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"maxRules_\",\"type\":\"uint256\"}],\"name\":\"setMaxRules\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IRule[]\",\"name\":\"rules_\",\"type\":\"address[]\"}],\"name\":\"setRules\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"setTokenSelfBindingApproval\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"tokens\",\"type\":\"address[]\"},{\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"setTokenSelfBindingApprovalBatch\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"transferred\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"transferred\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"unbindToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"tokens\",\"type\":\"address[]\"}],\"name\":\"unbindTokens\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"version_\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"No ERC-2771 support: every caller is the raw `msg.sender`. Deploy {RuleEngineOwnable2Step2771} to administer the engine through a trusted forwarder (gasless transactions).\",\"errors\":{\"OwnableInvalidOwner(address)\":[{\"details\":\"The owner is not a valid owner account. (eg. `address(0)`)\"}],\"OwnableUnauthorizedAccount(address)\":[{\"details\":\"The caller account is not authorized to perform an operation.\"}]},\"events\":{\"AddRule(address)\":{\"params\":{\"rule\":\"The address of the rule contract that was added.\"}},\"RemoveRule(address)\":{\"params\":{\"rule\":\"The address of the rule contract that was removed.\"}},\"SetMaxRules(uint256)\":{\"params\":{\"maxRules\":\"The new rule cap.\"}},\"TokenBound(address)\":{\"details\":\"Same declaration as ERC-3643 `TokenBound(address _token)`, which does not index the token. Keep it non-indexed: `indexed` would move `token` from the data to a topic and break consumers decoding with the standard ERC-3643 ABI.\",\"params\":{\"token\":\"The address of the token that was bound.\"}},\"TokenSelfBindingApprovalBatchSet(address[],bool)\":{\"details\":\"`tokens` is the array as passed: it may contain tokens already at `approved` and duplicates, and is empty for an empty batch, so it lists the tokens that were set, not only those that changed. No {TokenSelfBindingApprovalSet} is emitted per token, so a filter on that event's indexed `token` does not see batch updates. `tokens` is not indexed: an indexed array is stored as a hash and cannot be filtered per token.\",\"params\":{\"approved\":\"True if token self-bind/unbind is allowed, false otherwise.\",\"tokens\":\"The token addresses whose self-binding permission was set, as passed to the call.\"}},\"TokenSelfBindingApprovalSet(address,bool)\":{\"details\":\"Emitted on every call, also when `approved` equals the current value. Not emitted by {setTokenSelfBindingApprovalBatch}, which emits {TokenSelfBindingApprovalBatchSet} instead: a consumer reconstructing the approvals, or filtering on `token`, must handle both events, or read {isTokenSelfBindingApproved}, which is authoritative.\",\"params\":{\"approved\":\"True if token self-bind/unbind is allowed, false otherwise.\",\"token\":\"The token address whose self-binding permission was set.\"}},\"TokenUnbound(address)\":{\"details\":\"Same declaration as ERC-3643 `TokenUnbound(address _token)`; kept non-indexed for the same reason as {TokenBound}.\",\"params\":{\"token\":\"The address of the token that was unbound.\"}}},\"kind\":\"dev\",\"methods\":{\"acceptOwnership()\":{\"details\":\"Repeats the rule-account check of {transferOwnership}: an address nominated while it was not a rule, then added as a rule, cannot accept until it is removed from the rule set.\"},\"addRule(address)\":{\"details\":\"Reverts when the configured maximum number of rules is already reached. Security convention: do not grant {RULES_MANAGEMENT_ROLE} to rule contracts.\",\"params\":{\"rule_\":\"The IRule contract to add.\"}},\"bindToken(address)\":{\"custom:security-note\":\"\\\"Multi-tenant\\\" means one instance is shared by multiple token contracts. Downstream state (for the RuleEngine: the per-address accounting held by stateful rules) is shared across all bound tokens, so binding tokens from different issuers silently cross-contaminates it. Only bind tokens that are equally trusted and governed together.\",\"details\":\"Authorized by {_authorizeTokenBindingChange}.\",\"params\":{\"token\":\"The address of the token to bind.\"}},\"bindTokens(address[])\":{\"custom:security-note\":\"See {bindToken} for multi-tenant state risks. All tokens bound in this batch share the same downstream state. Only bind tokens that are equally trusted and governed together.\",\"details\":\"Must be restricted by implementation-specific access control. Atomic: reverts if any token is invalid or already bound (or listed twice), and then binds none of them. This deliberately departs from the usual batch convention of skipping elements already in the target state: a binding change is security-relevant, and a token that is already bound in the list is most likely an operator mistake that should stop the whole operation. An empty array is a no-op.\",\"params\":{\"tokens\":\"The token addresses to bind.\"}},\"canTransfer(address,address,uint256)\":{\"details\":\"Don't check the balance and the user's right (access control)\",\"params\":{\"from\":\"The address sending tokens.\",\"to\":\"The address receiving tokens.\",\"value\":\"The amount of tokens to transfer.\"},\"returns\":{\"_0\":\"True if the transfer is valid, false otherwise.\"}},\"canTransferFrom(address,address,address,uint256)\":{\"details\":\"Does not check balances or access rights (Access Control).\",\"params\":{\"from\":\"The source address.\",\"spender\":\"The address performing the transfer.\",\"to\":\"The destination address.\",\"value\":\"The number of tokens to transfer.\"},\"returns\":{\"_0\":\"isCompliant True if the transfer complies with policy.\"}},\"clearRules()\":{\"details\":\"After calling this function, no rules will remain set. Cost is O(n) in the number of configured rules. With the default cap of 10 this is negligible, but a high {maxRules} setting re-exposes unbounded cost here even though per-transfer cost remains bounded.\"},\"constructor\":{\"params\":{\"owner_\":\"Address of the initial contract owner (ERC-173).\",\"tokenContract\":\"Address of the token contract to bind at deployment (use zero address to skip).\"}},\"containsRule(address)\":{\"details\":\"Complexity: O(1).\",\"params\":{\"rule_\":\"The IRule contract to check for membership.\"},\"returns\":{\"_0\":\"True if the rule is present, false otherwise.\"}},\"created(address,uint256)\":{\"details\":\"Called by the token contract when new tokens are issued to an account. Reverts if the minting does not comply with the rules.\",\"params\":{\"to\":\"The address receiving the minted tokens.\",\"value\":\"The number of tokens created.\"}},\"destroyed(address,uint256)\":{\"details\":\"Called by the token contract when tokens are redeemed or burned. Reverts if the burning does not comply with the rules.\",\"params\":{\"from\":\"The address whose tokens are being destroyed.\",\"value\":\"The number of tokens destroyed.\"}},\"detectTransferRestriction(address,address,uint256)\":{\"params\":{\"from\":\"the origin address\",\"to\":\"the destination address\",\"value\":\"to transfer\"},\"returns\":{\"_0\":\"The restriction code or REJECTED_CODE_BASE.TRANSFER_OK (0) if the transfer is valid\"}},\"detectTransferRestrictionFrom(address,address,address,uint256)\":{\"details\":\" See {ERC-1404} Add an additionnal argument `spender` This function is where an issuer enforces the restriction logic of their token transfers. Some examples of this might include: - checking if the token recipient is whitelisted, - checking if a sender's tokens are frozen in a lock-up period, etc.\",\"params\":{\"from\":\"The address sending tokens.\",\"spender\":\"The address initiating the delegated transfer.\",\"to\":\"The address receiving tokens.\",\"value\":\"amount of tokens to transfer\"},\"returns\":{\"_0\":\"uint8 restricted code, 0 means the transfer is authorized\"}},\"getTokenBound()\":{\"details\":\"If multiple tokens are supported, consider using getTokenBounds().\",\"returns\":{\"_0\":\"The address of the currently bound token.\"}},\"getTokenBounds()\":{\"details\":\"This operation copies the entire storage set to memory and is mainly intended for off-chain reads.\",\"returns\":{\"_0\":\"An array of bound token addresses.\"}},\"isTokenBound(address)\":{\"details\":\"Complexity: O(1).\",\"params\":{\"token\":\"The token address to verify.\"},\"returns\":{\"_0\":\"True if the token is bound, false otherwise.\"}},\"isTokenSelfBindingApproved(address)\":{\"params\":{\"token\":\"The token address to query.\"},\"returns\":{\"_0\":\"True if self-binding is approved for `token`, false otherwise.\"}},\"maxRules()\":{\"returns\":{\"_0\":\"The maximum number of rules that can be configured.\"}},\"messageForTransferRestriction(uint8)\":{\"details\":\"See {ERC-1404} This function is effectively an accessor for the \\\"message\\\", a human-readable explanation as to why a transaction is restricted.\",\"params\":{\"restrictionCode\":\"The restriction code to translate into a message.\"},\"returns\":{\"_0\":\"The human-readable message corresponding to `restrictionCode`.\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pendingOwner()\":{\"details\":\"Returns the address of the pending owner.\"},\"removeRule(address)\":{\"details\":\"Reverts if the provided rule is not found or does not match the stored rule at its index. Complexity: O(1).\",\"params\":{\"rule_\":\"The IRule contract to remove.\"}},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.\"},\"rule(uint256)\":{\"details\":\"Reverts if `ruleId` is out of bounds. Complexity: O(1). Note that there are no guarantees on the ordering of values inside the array, and it may change when more values are added or removed.\",\"params\":{\"ruleId\":\"The index of the desired rule in the array.\"},\"returns\":{\"_0\":\"The address of the corresponding IRule contract, return the `zero address` is out of bounds.\"}},\"rules()\":{\"details\":\"This is a view-only function that does not modify state. This operation will copy the entire storage to memory, which can be quite expensive. This is designed to mostly be used by view accessors that are queried without any gas fees.\",\"returns\":{\"_0\":\"An array of all active rule contract addresses.\"}},\"rulesCount()\":{\"details\":\"Equivalent to the length of the internal rules array. Complexity: O(1)\",\"returns\":{\"_0\":\"The number of active rules.\"}},\"setMaxRules(uint256)\":{\"details\":\"Access control is implementation specific (admin/owner). Setting a very high cap re-exposes unbounded gas cost for administrative operations such as {clearRules} even though normal per-transfer cost remains bounded.\",\"params\":{\"maxRules_\":\"New maximum number of rules.\"}},\"setRules(address[])\":{\"details\":\"Replaces the entire rule set atomically. Reverts if `rules_` is empty. Use {clearRules} to remove all rules explicitly. To transition from one non-empty set to another without an enforcement gap, call this function directly with the new set. Emits {ClearRules} when the existing rule set is non-empty, then emits {AddRule} for each new rule. Off-chain indexers must handle both events to reconstruct state. Security convention: rule contracts should be treated as trusted business logic, but should not also be granted {RULES_MANAGEMENT_ROLE}.\",\"params\":{\"rules_\":\"The array of addresses representing the new rules to be set.\"}},\"setTokenSelfBindingApproval(address,bool)\":{\"details\":\"Must be restricted by implementation-specific access control. An approval stays in force until it is revoked here or until the binding manager unbinds the token ({unbindToken} or {unbindTokens}), which revokes it and emits {TokenSelfBindingApprovalSet} with `false`. A token that unbinds itself keeps its approval, so it can bind itself again later.\",\"params\":{\"approved\":\"Whether self-binding is approved for `token`.\",\"token\":\"The token address to configure.\"}},\"setTokenSelfBindingApprovalBatch(address[],bool)\":{\"details\":\"Must be restricted by implementation-specific access control. Reverts if any token in `tokens` is the zero address. Emits a single {TokenSelfBindingApprovalBatchSet} with the input array, not one {TokenSelfBindingApprovalSet} per token.\",\"params\":{\"approved\":\"Whether self-binding is approved for all provided tokens.\",\"tokens\":\"The token addresses to configure.\"}},\"supportsInterface(bytes4)\":{\"params\":{\"interfaceId\":\"The interface identifier to check.\"},\"returns\":{\"_0\":\"True if the interface is supported, false otherwise.\"}},\"transferOwnership(address)\":{\"details\":\"Reverts when `newOwner` is already configured as a rule.\",\"params\":{\"newOwner\":\"The address of the new owner.\"}},\"transferred(address,address,address,uint256)\":{\"details\":\"Must revert if the transfer is invalid Same name as ERC-3643 but with one supplementary argument `spender` This function can be used to update state variables of the RuleEngine contract This function can be called ONLY by the token contract bound to the RuleEngine Which overload the token calls (since CMTAT v3.3.0): - this 4-argument overload for `transferFrom` (`spender` = approved spender) and for every operation initiated by an operator, with the operator as `spender`: mint (`from == address(0)`), burn (`to == address(0)`), including `burnFrom`, self-burn and cross-chain mint/burn, and the minter `batchTransfer`; - the 3-argument ERC-3643 overload `transferred(from, to, value)`, inherited from {IERC3643IComplianceContract}, only for a direct `transfer`. Up to CMTAT v3.2.0, mint, burn and the minter transfer used the 3-argument overload. WARNING - zero-value calls are permissionless. ERC-20 requires transfers of `0` to be treated as normal transfers, and OpenZeppelin's `_spendAllowance` consumes no allowance when `value == 0`. Any address can therefore call `transferFrom(victim, anyone, 0)` on the token and reach this callback for an arbitrary `from`, with itself as `spender`, without ever having been approved. The token deliberately does not suppress the notification, because doing so would make its compliance notifications inconsistent with its own ERC-20 transfer semantics. Implementations MUST therefore treat `value == 0` as carrying no economic meaning: any stateful rule (cooldown, holding period, quota, tax bucket, counter, holder tracking, ...) MUST be a no-op for a zero value, otherwise an attacker can desynchronize policy state from balances, or keep a holder permanently restricted, at no cost. The same applies to the 3-argument ERC-3643 overload, which a zero-value `transfer(to, 0)` reaches the same way.\",\"params\":{\"from\":\"token holder address\",\"spender\":\"spender address (sender)\",\"to\":\"receiver address\",\"value\":\"value of tokens involved in the transfer; MAY be `0` \\u2014 see the warning above\"}},\"transferred(address,address,uint256)\":{\"details\":\" This function can be used to update state variables of the compliance contract This function can be called ONLY by the token contract bound to the compliance\",\"params\":{\"from\":\"The address of the sender\",\"to\":\"The address of the receiver\",\"value\":\"value of tokens involved in the transfer\"}},\"unbindToken(address)\":{\"details\":\"Authorized by {_authorizeTokenBindingChange}. Operator warning: unbinding is an administrative operation and does not erase any state already stored downstream in a previously shared (\\\"multi-tenant\\\") setup.\",\"params\":{\"token\":\"The address of the token to unbind.\"}},\"unbindTokens(address[])\":{\"details\":\"Must be restricted by implementation-specific access control. Atomic: reverts if any token is not currently bound, and then unbinds none of them. Deliberately not the skip-if-already-done batch convention, for the same reason as {bindTokens}. An empty array is a no-op. Like a manager's {unbindToken}, revokes each token's self-binding approval (see {setTokenSelfBindingApproval}).\",\"params\":{\"tokens\":\"The token addresses to unbind.\"}},\"version()\":{\"details\":\"This value is useful to know which smart contract version has been used\",\"returns\":{\"version_\":\"A string representing the version of the token implementation (e.g., \\\"1.0.0\\\").\"}}},\"title\":\"Implementation of a ruleEngine with ERC-173 Ownable2Step access control\",\"version\":1},\"userdoc\":{\"errors\":{\"TokenBinding_InvalidTokenAddress()\":[{\"notice\":\"Thrown when the zero address is passed as a token to bind or to approve.\"}],\"TokenBinding_TokenAlreadyBound()\":[{\"notice\":\"Thrown when binding a token that is already bound.\"}],\"TokenBinding_TokenNotBound()\":[{\"notice\":\"Thrown when unbinding a token that is not currently bound.\"}],\"TokenBinding_UnauthorizedCaller()\":[{\"notice\":\"Thrown when a caller that is not a bound token calls a bound-token entry point.\"}]},\"events\":{\"AddRule(address)\":{\"notice\":\"Emitted when a new rule is added to the rule set.\"},\"ClearRules()\":{\"notice\":\"Emitted when all rules are cleared from the rule set.\"},\"RemoveRule(address)\":{\"notice\":\"Emitted when a rule is removed from the rule set.\"},\"SetMaxRules(uint256)\":{\"notice\":\"Emitted when the maximum allowed number of rules is updated.\"},\"TokenBound(address)\":{\"notice\":\"Emitted when a token is successfully bound.\"},\"TokenSelfBindingApprovalBatchSet(address[],bool)\":{\"notice\":\"Emitted once by {setTokenSelfBindingApprovalBatch}, with the input array.\"},\"TokenSelfBindingApprovalSet(address,bool)\":{\"notice\":\"Emitted by {setTokenSelfBindingApproval} when self-binding permission is set for a token.\"},\"TokenUnbound(address)\":{\"notice\":\"Emitted when a token is successfully unbound.\"}},\"kind\":\"user\",\"methods\":{\"DEFAULT_MAX_RULES()\":{\"notice\":\"Default upper bound on the number of rules a RuleEngine may hold.\"},\"acceptOwnership()\":{\"notice\":\"Completes the ownership transfer; callable by the pending owner only.\"},\"addRule(address)\":{\"notice\":\"Adds a new rule to the current rule set.\"},\"bindToken(address)\":{\"notice\":\"Binds a token contract, allowing it to call the bound-token entry points.\"},\"bindTokens(address[])\":{\"notice\":\"Binds several token contracts in a single call.\"},\"canTransfer(address,address,uint256)\":{\"notice\":\"Returns true if the transfer is valid, and false otherwise.\"},\"canTransferFrom(address,address,address,uint256)\":{\"notice\":\"Checks if `spender` can transfer `value` tokens from `from` to `to` under compliance rules.\"},\"clearRules()\":{\"notice\":\"Removes all configured rules.\"},\"constructor\":{\"notice\":\"Deploys a RuleEngine with ERC-173 two-step ownership transfer, without a trusted forwarder.\"},\"containsRule(address)\":{\"notice\":\"Checks whether a specific rule is currently configured.\"},\"created(address,uint256)\":{\"notice\":\"Updates the compliance contract state when tokens are created (minted).\"},\"destroyed(address,uint256)\":{\"notice\":\"Updates the compliance contract state when tokens are destroyed (burned).\"},\"detectTransferRestriction(address,address,uint256)\":{\"notice\":\"Queries every rule, in order, and returns the first restriction code that is not zero\"},\"detectTransferRestrictionFrom(address,address,address,uint256)\":{\"notice\":\"Returns a uint8 code to indicate if a transfer is restricted or not\"},\"getTokenBound()\":{\"notice\":\"Returns the single token currently bound to this compliance contract.\"},\"getTokenBounds()\":{\"notice\":\"Returns all tokens currently bound.\"},\"isTokenBound(address)\":{\"notice\":\"Checks whether a token is currently bound.\"},\"isTokenSelfBindingApproved(address)\":{\"notice\":\"Returns whether a token is approved to bind and unbind itself.\"},\"maxRules()\":{\"notice\":\"Returns the maximum number of rules allowed in the engine.\"},\"removeRule(address)\":{\"notice\":\"Removes a specific rule from the current rule set.\"},\"rule(uint256)\":{\"notice\":\"Retrieves the rule address at a specific index.\"},\"rules()\":{\"notice\":\"Returns the full list of currently configured rules.\"},\"rulesCount()\":{\"notice\":\"Returns the total number of currently configured rules.\"},\"setMaxRules(uint256)\":{\"notice\":\"Updates the maximum number of rules allowed in the engine.\"},\"setRules(address[])\":{\"notice\":\"Defines the rules for the rule engine.\"},\"setTokenSelfBindingApproval(address,bool)\":{\"notice\":\"Sets whether a token is allowed to bind and unbind itself.\"},\"setTokenSelfBindingApprovalBatch(address[],bool)\":{\"notice\":\"Sets self-binding approval for multiple tokens in one transaction.\"},\"supportsInterface(bytes4)\":{\"notice\":\"ERC-165 interface detection.\"},\"transferOwnership(address)\":{\"notice\":\"Starts ownership transfer to `newOwner`.\"},\"transferred(address,address,address,uint256)\":{\"notice\":\"Function called whenever tokens are transferred from one wallet to another, minted or burned, when the token knows the account that initiated the operation (`spender`).\"},\"transferred(address,address,uint256)\":{\"notice\":\"Function called whenever tokens are transferred from one wallet to another\"},\"unbindToken(address)\":{\"notice\":\"Unbinds a token contract, revoking its access to the bound-token entry points.\"},\"unbindTokens(address[])\":{\"notice\":\"Unbinds several token contracts in a single call.\"},\"version()\":{\"notice\":\"Returns the current version of the token contract.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/deployment/ownable/RuleEngineOwnable2Step.sol\":\"RuleEngineOwnable2Step\"},\"evmVersion\":\"osaka\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[\":@chainlink/contracts-ccip/=lib/Rules/lib/chainlink-ace/node_modules/@chainlink/contracts-ccip/chains/evm/contracts/\",\":@chainlink/contracts/=lib/Rules/lib/chainlink-ace/node_modules/@chainlink/contracts/\",\":@chainlink/contracts@1.4.0/=lib/Rules/lib/chainlink-doc/node_modules/@chainlink/contracts-1.4.0/\",\":@chainlink/cross-chain-identity/=lib/Rules/lib/chainlink-ace/packages/cross-chain-identity/src/\",\":@chainlink/local/=lib/Rules/lib/chainlink-doc/node_modules/@chainlink/local/\",\":@chainlink/policy-management/=lib/Rules/lib/chainlink-ace/packages/policy-management/src/\",\":@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\":@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\":@openzeppelin/contracts@4.7.3/=lib/Rules/lib/chainlink-doc/node_modules/@openzeppelin/contracts-4.7.3/\",\":@openzeppelin/contracts@4.8.3/=lib/Rules/lib/chainlink-ace/node_modules/@openzeppelin/contracts-4.8.3/\",\":@openzeppelin/contracts@4.9.6/=lib/Rules/lib/chainlink-doc/node_modules/@openzeppelin/contracts-4.9.6/\",\":@openzeppelin/contracts@5.0.2/=lib/Rules/lib/chainlink-ace/node_modules/@openzeppelin/contracts/\",\":@openzeppelin/contracts@5.1.0/=lib/Rules/lib/chainlink-doc/node_modules/@openzeppelin/contracts-5.1.0/\",\":@openzeppelin/contracts@5.3.0/=lib/Rules/lib/chainlink-ace/node_modules/@openzeppelin/contracts-5.3.0/\",\":CMTAT/=lib/CMTAT/contracts/\",\":CMTATv3.0.0/=lib/CMTATv3.0.0/contracts/\",\":ERC-3643/=lib/ERC-3643/contracts/\",\":ERC3643/=lib/Rules/lib/ERC-3643/contracts/\",\":RuleEngine/=lib/Rules/lib/RuleEngine/\",\":Rules/=lib/Rules/\",\":chainlink-ace/=lib/Rules/lib/chainlink-ace/\",\":chainlink-doc/=lib/Rules/lib/\",\":erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/\",\":forge-std/=lib/forge-std/src/\",\":halmos-cheatcodes/=lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/\",\":openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\":openzeppelin-contracts/=lib/openzeppelin-contracts/\"]},\"sources\":{\"lib/CMTAT/contracts/interfaces/engine/IRuleEngine.sol\":{\"keccak256\":\"0xeda899e2e46a9b9c3516acb61a7f7e92ed098928379010655c330da721aaffa7\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://60f8555330fc531dff7d0d71a862696fb286a0ba3290e41efbbbf4dd25947a3c\",\"dweb:/ipfs/QmWvbsBGWPtNMNN2EEedwdzzvQG7NtSj9VD2fmNgqVtCXN\"]},\"lib/CMTAT/contracts/interfaces/technical/IERC5679.sol\":{\"keccak256\":\"0x5bee30750c9a65438469a6c5bd8465e1603eec3aeeb94c07bd64ba3e9ee766e1\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://ef7a5c5f0d47135c97ab5d7456d31e513a71c849ae7f2f5395f860be125c4fbc\",\"dweb:/ipfs/Qmezem3qqSjij6ggyB34wC2S15KrY9fu42oymyS9epAYCQ\"]},\"lib/CMTAT/contracts/interfaces/tokenization/IERC3643Partial.sol\":{\"keccak256\":\"0x5c84c2e2442824e98625c471482fb3c9502f43f4c345e7c0fb07fa549be02e26\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://19071f2d12fb580d37eeee07885461f193568df34f3f69d2c5d65ce655d84435\",\"dweb:/ipfs/QmRqHwC7LksE3YPohMtxFieiPerhWdoDNUUMMLbB4XYvhK\"]},\"lib/CMTAT/contracts/interfaces/tokenization/draft-IERC1404.sol\":{\"keccak256\":\"0xc27cdac182d930a94391d589bdafa15364b6f8d9bf211175781dba661f1c0336\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://b509fa7f3cfd785632569f6ae3bec846aa0beefd73c1d5bde233440cae919f0f\",\"dweb:/ipfs/QmPCAdiEun8gaMqS8KhwPpRZV2zXAPfURRaF4C2KjX5Kby\"]},\"lib/CMTAT/contracts/interfaces/tokenization/draft-IERC7551.sol\":{\"keccak256\":\"0x84b73eb77ec82d6d7b313eff2d87f58d3b795840d004aaa10c611b360b827e30\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://a5b8c99fb3600369065a422d3821ba441dc06fc64f50ce0f33950a76ad82b51b\",\"dweb:/ipfs/QmbviJsZPY3xuLU3cHUWJx11aJCPAuN4WKnCufN4kVLm2U\"]},\"lib/CMTAT/contracts/interfaces/tokenization/draft-IERC7943.sol\":{\"keccak256\":\"0xc69588a72da81057ee278e961e8e3bb61a28d64c3c6cebe494ce00809c1cef15\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://148f117d9c463de441f81e6c0a67e95f1f14a61db209492dd0a1767b5572f21a\",\"dweb:/ipfs/QmUjT5uyJfNSYgUWn5Dxhf6Sx9Y1z8CNf3PuTEaGoAx3za\"]},\"lib/CMTAT/contracts/library/ERC1404ExtendInterfaceId.sol\":{\"keccak256\":\"0xf8268f4eb3a6b2e26c32cf76c5c76b6c17df3385c150f05953538a2472149247\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://05108de7a7ba2a0a67978bdfe8e500360674db6d894f42970bb1016b36639056\",\"dweb:/ipfs/QmRux9Qj1GomATseS6Tyq9uiPPNNipuxg2HjdjnPjgSQds\"]},\"lib/CMTAT/contracts/library/RuleEngineInterfaceId.sol\":{\"keccak256\":\"0x1152a49cba4232d943e295d259eb8a1b216d815067367410a5729a256dae4051\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://470f4435a5e62b0ba0ad70f8657b2db0e4cc3b7f2561772adb944ce010551ee6\",\"dweb:/ipfs/QmXECahRr8rK9XJPZwBCnemLDVPdFvPEBusezhaBqbLBqp\"]},\"lib/openzeppelin-contracts/contracts/access/Ownable.sol\":{\"keccak256\":\"0xff6d0bb2e285473e5311d9d3caacb525ae3538a80758c10649a4d61029b017bb\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://8ed324d3920bb545059d66ab97d43e43ee85fd3bd52e03e401f020afb0b120f6\",\"dweb:/ipfs/QmfEckWLmZkDDcoWrkEvMWhms66xwTLff9DDhegYpvHo1a\"]},\"lib/openzeppelin-contracts/contracts/access/Ownable2Step.sol\":{\"keccak256\":\"0xdcad8898fda432696597752e8ec361b87d85c82cb258115427af006dacf7128c\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://e2c9d517f0c136d54bd00cd57959d25681d4d6273f5bbbc263afe228303772f0\",\"dweb:/ipfs/QmReNFjXBiufByiAAzfSQ2SM5r3qeUErn46BmN3yVRvrek\"]},\"lib/openzeppelin-contracts/contracts/interfaces/IERC165.sol\":{\"keccak256\":\"0x0afcb7e740d1537b252cb2676f600465ce6938398569f09ba1b9ca240dde2dfc\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://1c299900ac4ec268d4570ecef0d697a3013cd11a6eb74e295ee3fbc945056037\",\"dweb:/ipfs/Qmab9owJoxcA7vJT5XNayCMaUR1qxqj1NDzzisduwaJMcZ\"]},\"lib/openzeppelin-contracts/contracts/utils/Arrays.sol\":{\"keccak256\":\"0x772f0c778626a7bdcbcbabca74b825ae9b9dc89d2a47a98b402b1187fbaa63a4\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://eba1d46e58e8880b45c6d51245dc94585b81d6d7290ca77ef50037a6193ed301\",\"dweb:/ipfs/Qme3CWun5qQACjGEerT2MCvhs6brKGFfJirGnzV1ypKTXA\"]},\"lib/openzeppelin-contracts/contracts/utils/Comparators.sol\":{\"keccak256\":\"0x302eecd8cf323b4690e3494a7d960b3cbce077032ab8ef655b323cdd136cec58\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://49ba706f1bc476d68fe6c1fad75517acea4e9e275be0989b548e292eb3a3eacd\",\"dweb:/ipfs/QmeBpvcdGWzWMKTQESUCEhHgnEQYYATVwPxLMxa6vMT7jC\"]},\"lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"keccak256\":\"0x493033a8d1b176a037b2cc6a04dad01a5c157722049bbecf632ca876224dd4b2\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6a708e8a5bdb1011c2c381c9a5cfd8a9a956d7d0a9dc1bd8bcdaf52f76ef2f12\",\"dweb:/ipfs/Qmax9WHBnVsZP46ZxEMNRQpLQnrdE4dK8LehML1Py8FowF\"]},\"lib/openzeppelin-contracts/contracts/utils/Panic.sol\":{\"keccak256\":\"0xf7fe324703a64fc51702311dc51562d5cb1497734f074e4f483bfb6717572d7a\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c6a5ff4f9fd8649b7ee20800b7fa387d3465bd77cf20c2d1068cd5c98e1ed57a\",\"dweb:/ipfs/QmVSaVJf9FXFhdYEYeCEfjMVHrxDh5qL4CGkxdMWpQCrqG\"]},\"lib/openzeppelin-contracts/contracts/utils/SlotDerivation.sol\":{\"keccak256\":\"0x94045fd4f268edf2b2d01ef119268548c320366d6f5294ad30c1b8f9d4f5225f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://edfda81f426f8948b3834115c21e83c48180e6db0d2a8cd2debb2185ed349337\",\"dweb:/ipfs/QmdYZneFyDAux1BuWQxLAdqtABrGS2k9WYCa7C9dvpKkWv\"]},\"lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol\":{\"keccak256\":\"0xcf74f855663ce2ae00ed8352666b7935f6cddea2932fdf2c3ecd30a9b1cd0e97\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://9f660b1f351b757dfe01438e59888f31f33ded3afcf5cb5b0d9bf9aa6f320a8b\",\"dweb:/ipfs/QmarDJ5hZEgBtCmmrVzEZWjub9769eD686jmzb2XpSU1cM\"]},\"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\":{\"keccak256\":\"0x2d9dc2fe26180f74c11c13663647d38e259e45f95eb88f57b61d2160b0109d3e\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://81233d1f98060113d9922180bb0f14f8335856fe9f339134b09335e9f678c377\",\"dweb:/ipfs/QmWh6R35SarhAn4z2wH8SU456jJSYL2FgucfTFgbHJJN4E\"]},\"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165Checker.sol\":{\"keccak256\":\"0x7c7ad70641a7f8cd44def0857ec97b0e40bfd073b2d6037a5f57ce9527ee9bc5\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://e05c6572dfe769f7aea6f3a8002951cc12d143d980dad29f6c5feedf9408bc14\",\"dweb:/ipfs/QmXM7C8YEptxisZiEefXUrwdXt3zMaCobmkCchxTtDg1oK\"]},\"lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"keccak256\":\"0x8891738ffe910f0cf2da09566928589bf5d63f4524dd734fd9cedbac3274dd5c\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://971f954442df5c2ef5b5ebf1eb245d7105d9fbacc7386ee5c796df1d45b21617\",\"dweb:/ipfs/QmadRjHbkicwqwwh61raUEapaVEtaLMcYbQZWs9gUkgj3u\"]},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"keccak256\":\"0x59973a93b1f983f94e10529f46ca46544a9fec2b5f56fb1390bbe9e0dc79f857\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c55ef8f0b9719790c2ae6f81d80a59ffb89f2f0abe6bc065585bd79edce058c5\",\"dweb:/ipfs/QmNNmCbX9NjPXKqHJN8R1WC2rNeZSQrPZLd6FF6AKLyH5Y\"]},\"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\":{\"keccak256\":\"0xc8cae21c9ae4a46e5162ff9bf5b351d6fa6a6eba72d515f3bc1bdfeda7fdf083\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://ce830ebcf28e31643caba318996db3763c36d52cd0f23798ba83c135355d45e9\",\"dweb:/ipfs/QmdGPcvptHN7UBCbUYBbRX3hiRVRFLRwno8b4uga6uFNif\"]},\"lib/openzeppelin-contracts/contracts/utils/structs/EnumerableSet.sol\":{\"keccak256\":\"0xd553ff8b7d55679f0711f1598600ac292dbd8cfdf4b2419b9cabe4c931172895\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://7905ccb27e2308fd0d90dc1212161003ab6964e1c176593db1ccedef705bcc09\",\"dweb:/ipfs/QmW37vm2PcrWLKnN74sKkvAzqSwntCEfCp4EoSEvbBHWkj\"]},\"src/RuleEngineBase.sol\":{\"keccak256\":\"0xb3d832fa55b615574d80b0e0ad76620ad236aa046523617ed5daa46ae07bf853\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://7be31bf5dbd3fa1be025cdc4b7674b76bf40e1c14ce89ec78f792cb3d7ed804e\",\"dweb:/ipfs/QmPq4xBiB3XwXerWtuonZLGiWHMqvz5tKvjhTh9AiWkbww\"]},\"src/RuleEngineOwnableShared.sol\":{\"keccak256\":\"0xa78493398d8b0554e72def7f14d7439109bd4dbd5e07f1466b40acea2bb7dc02\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://ebd87d69b4f6eb193c5d03476381ac132f9587248422d3306dda95b79fd4e470\",\"dweb:/ipfs/QmWYDLvPWjRcfxdR2KhXAij8U9TrFjeM77fsJRX25jWQmY\"]},\"src/deployment/ownable/RuleEngineOwnable2Step.sol\":{\"keccak256\":\"0xf8d7f52cf7857f0d89adeb7dfa42444dbaf371dd6cca712c797181baf7a3fe97\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://f3307f7a2800dfc1b23c89cf6eebcbf21fd283eeb19343a374bc5bc771b7a4ef\",\"dweb:/ipfs/QmbFjoQ97zF74QCWwbswVwKL7wB1Gx4pfRdu7jp2vE36DB\"]},\"src/interfaces/IERC3643Compliance.sol\":{\"keccak256\":\"0xd0edd6697d67135853576ac6a40cadaffd787cedea98071708bbfb189c7ee5bc\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://4ed3cd3af64fccff17a1f33989cdfbdacbc0e4f32a56de11a072cf9e2277a1f6\",\"dweb:/ipfs/QmenRqRw1Yy39yDv1pJgBmnHtwuZhDdHE4omchL41CjXjb\"]},\"src/interfaces/IERC3643ComplianceExtended.sol\":{\"keccak256\":\"0x4a43bf330c7a904cba110acf52f519718d8409514c377912d5bd063c9d963729\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://c671879c591760ecbc2691e2f24adfb215a658c9fe6eb0c05dd1ca980054e585\",\"dweb:/ipfs/QmdbA19PFpJgHraF46YrcMNzUgswbTRA92atL2Lha63JLY\"]},\"src/interfaces/IRule.sol\":{\"keccak256\":\"0x81580b67f7be09049aa64d93cc1d8d691a87c639adc1cf169dc6073e1e543a5c\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://6f1808c3ed18ef1acbccdd9b30011b6e7220d388cfd66cba40b1ef0b485306a1\",\"dweb:/ipfs/QmcUCQ5MYcf7KTtoeqMKsTutPPSJhNTaK1ntHV21ioS9Fm\"]},\"src/interfaces/IRulesManagementModule.sol\":{\"keccak256\":\"0x082dd58070e83b02f275584afa872c4583ac4ca8ad12eb329fc11301470147f9\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://e2d0ad78dc323881864f406acd44976f5de39cdc97a6c99a724d8458b993e2e2\",\"dweb:/ipfs/QmRFfMbXbdiAYV3vQyNppXG7tHTji6mV1Y5Cu3ZzEQm5ng\"]},\"src/interfaces/ITokenBinding.sol\":{\"keccak256\":\"0x34dfea4e118c966adf867c0899844515566251819b4e4510fd8ee424555493fd\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://1d054ed49874816688a6e71f76d611bbdefd492d122ae386cb804c6f5af677a7\",\"dweb:/ipfs/QmRaYX4aJWYSNWNa1D4Nich3k7hkGM9rTfc9s2XaVqyRjy\"]},\"src/interfaces/ITokenBindingExtended.sol\":{\"keccak256\":\"0x01f3ab56dffce860d03e72d10e9f2d13b6bfc9004cf058c63a0b23e3b226da99\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://521e0c9651632b70d61c4c3bd0b14c6f05d818166fe65dbed8e3253158b7637e\",\"dweb:/ipfs/QmY2xEVvfV1dgtFYw6coHX3Z7Fm7yRhzPaGyt6cYBMVf76\"]},\"src/modules/ERC3643ComplianceExtendedModule.sol\":{\"keccak256\":\"0x6f808b068517e9e15f09fc6a9d4190001ec8c2314a10e27a85a2d43e44c84fb1\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://c62c0b77fdd8b6e7bf7aa5bf8134a78ff024d6489a23f746874a99df38a8a265\",\"dweb:/ipfs/QmV7PG3ZUUzwDs9tpooC3hmBu5e39buJnJ4TRditojJ3hu\"]},\"src/modules/ERC3643ComplianceModule.sol\":{\"keccak256\":\"0x7cda81af8687328ac2089f9d1d78352e0e75d0f70a4ba8e2b3ac82896f22863f\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://50711cb94d69ea63d787a8bb19c38c0b99539029ec8fb957a8eff00880fc11fc\",\"dweb:/ipfs/QmSapDWh5mpvWn1q6JteZisJfVGPrCz47WP2BBrJCccEjV\"]},\"src/modules/RulesManagementModule.sol\":{\"keccak256\":\"0xe4d9425613284e71a5e3d590d5433167a9751d9496f57efa914baa81f493e66d\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://d07a16e6869df86c526ef89e7e359e34a9553dc4288b262abd2979359ecf720e\",\"dweb:/ipfs/QmRy2JEsyhkv1mxv7eFaSbEWN4A3gtpPSUnnV48W2KiV4u\"]},\"src/modules/TokenBindingExtendedModule.sol\":{\"keccak256\":\"0x4e1ca7b2ec78608c3a7960bec7102a1780bdf3ec7ff544b612bafaf738b34d05\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://657bcdd303fd5a7fbe733b283f69d8e8aa73efeeeaf95c0ae7479769ac573693\",\"dweb:/ipfs/QmXiWPrv8pEqvBQck8jxC7NwB1MUdGQfLjihK6etYcZ54j\"]},\"src/modules/TokenBindingModule.sol\":{\"keccak256\":\"0xf65f46311d0078f60c30e3359dca988e39cba45b9eee53a09d618bfa70e6ef9b\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://e8c458ecfd41df5fb4a391e7ef837fd5ed5c999e61ccc0e6b4bd23023a739832\",\"dweb:/ipfs/Qmdsr765aw9fPFN2M9cSCP69o1o41FNCqhrXjHgEXNwbXV\"]},\"src/modules/VersionModule.sol\":{\"keccak256\":\"0x35daf007be8b9bb1cb9196ae2decb3e5ad4b574f6390f8fc010b78796ac42f73\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://b1b29d75e1c5023a0c6cb8c56638a17d855a3fdc051a60b9d2f304b99f7876d2\",\"dweb:/ipfs/QmXSCVjLuViC8916LwNpKtw8hqyH78Ptag3xH1n7F1fY4g\"]},\"src/modules/library/ComplianceInterfaceId.sol\":{\"keccak256\":\"0xd54bed5328e732f753d2886aeaa2761b2d66536d5247d4548e0ac1c83c7a0dac\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://ad695339fdfe72446a69d2dfbe39373affe2f37299ad921e57016069a7bc3592\",\"dweb:/ipfs/QmWathGt3E85hLfy5rrAYdb291W8VoTa4gpGPoxtWGvNNA\"]},\"src/modules/library/ERC1404InterfaceId.sol\":{\"keccak256\":\"0x07dc6905e137096cd0ae88be29b112d0e54a83ddf8ca527a281718010f6abcce\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://9249dce67cb59432bdbc9e49978c6cac0346cda3d3fca97c5a310e0f424e1600\",\"dweb:/ipfs/QmRi5awH3hjwvd3k3td48y5Cf64n1wvX9wCWy6fQLayuKs\"]},\"src/modules/library/Ownable2StepInterfaceId.sol\":{\"keccak256\":\"0xe4c5bd8569553d93b7283118318993fea44410a608e7bda490ff27bc3e848f89\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://8145a588e30eb836199f489e16464123082cd2af9989c9aeca1038c69ac3da6f\",\"dweb:/ipfs/QmNrQJ2mQQjqx3UY86mKB2M1vCgLQakumumKxVhvqX6AhF\"]},\"src/modules/library/OwnableInterfaceId.sol\":{\"keccak256\":\"0xdbe06b3203e21e41d1fd2a3ef373a80727193443dfd981de6821422158015d4f\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://ebe8699ae8af81c5cd82f25a1609d9396d72ae957647c33aaa745aadcdac8d18\",\"dweb:/ipfs/QmV73gwDJPFthn8VspdYE6GsoAcQMAR7TachUK8YrPonuT\"]},\"src/modules/library/RuleEngineInvariantStorage.sol\":{\"keccak256\":\"0x50a212f09f1695662965e5fba643b42a1978bec2a8368abbf43983489c983096\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://6137f01df7630527c985d85d2f7446359c678fcb933b66c55b51f583757b5c4a\",\"dweb:/ipfs/QmeHo47WQm1V99xZHS4soMk68UdtXtZhtWhV3dQC5BtA7u\"]},\"src/modules/library/RuleInterfaceId.sol\":{\"keccak256\":\"0x0d86820eee4c92b21d6704bea8ce7bd2cc1b35f6e4a1ceabbcf2a10f1c6b02ec\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://cfb560cb8588983b8c79a973d03c214a149bf1ac034fa9130ce93f0031a404d7\",\"dweb:/ipfs/Qmc6qt4E4BHdDyLUegCsgxqhf7ZFUiX4ahj8FjM54V7wpY\"]},\"src/modules/library/RulesManagementModuleInvariantStorage.sol\":{\"keccak256\":\"0xb81ea3a54c6e8d47b87d6c3d9fb5aae80c3430021b8cd66d9adeef7f5fc95893\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://cfcbadc2011f60de7189273c278dda1df2218aeeb153bee3b8a93447ec95df21\",\"dweb:/ipfs/Qmem5FqCLEfBJQdJzS7Xzd3zSfyL8Muf9Wv5WvCiBVsqfh\"]},\"src/modules/library/TokenBindingModuleInvariantStorage.sol\":{\"keccak256\":\"0x9bab8e5b265068da356fd46e343a7c6c73776f3964fdeaeff056e8ce104d40a5\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://e2e75d2d52b1e4f5cbb832d194266de9a1b3a8cc2101e875dce43a2664c31a05\",\"dweb:/ipfs/QmUsd5cTPsE89WKm3kTUWsobR9JsBDUY8NdxDU5RPYpvP6\"]}},\"version\":1}","metadata":{"compiler":{"version":"0.8.37+commit.f401782d"},"language":"Solidity","output":{"abi":[{"inputs":[{"internalType":"address","name":"owner_","type":"address"},{"internalType":"address","name":"tokenContract","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"type":"error","name":"OwnableInvalidOwner"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"type":"error","name":"OwnableUnauthorizedAccount"},{"inputs":[],"type":"error","name":"RuleEngine_AdminWithAddressZeroNotAllowed"},{"inputs":[],"type":"error","name":"RuleEngine_RuleInvalidInterface"},{"inputs":[],"type":"error","name":"RuleEngine_RulesManagementModule_ArrayIsEmpty"},{"inputs":[{"internalType":"uint256","name":"maxRules","type":"uint256"}],"type":"error","name":"RuleEngine_RulesManagementModule_MaxRulesExceeded"},{"inputs":[],"type":"error","name":"RuleEngine_RulesManagementModule_MaxRulesZeroNotAllowed"},{"inputs":[],"type":"error","name":"RuleEngine_RulesManagementModule_RuleAccountCannotReceivePrivileges"},{"inputs":[],"type":"error","name":"RuleEngine_RulesManagementModule_RuleAddressZeroNotAllowed"},{"inputs":[],"type":"error","name":"RuleEngine_RulesManagementModule_RuleAlreadyExists"},{"inputs":[],"type":"error","name":"RuleEngine_RulesManagementModule_RuleDoNotMatch"},{"inputs":[],"type":"error","name":"TokenBinding_InvalidTokenAddress"},{"inputs":[],"type":"error","name":"TokenBinding_TokenAlreadyBound"},{"inputs":[],"type":"error","name":"TokenBinding_TokenNotBound"},{"inputs":[],"type":"error","name":"TokenBinding_UnauthorizedCaller"},{"inputs":[{"internalType":"contract IRule","name":"rule","type":"address","indexed":true}],"type":"event","name":"AddRule","anonymous":false},{"inputs":[],"type":"event","name":"ClearRules","anonymous":false},{"inputs":[{"internalType":"address","name":"previousOwner","type":"address","indexed":true},{"internalType":"address","name":"newOwner","type":"address","indexed":true}],"type":"event","name":"OwnershipTransferStarted","anonymous":false},{"inputs":[{"internalType":"address","name":"previousOwner","type":"address","indexed":true},{"internalType":"address","name":"newOwner","type":"address","indexed":true}],"type":"event","name":"OwnershipTransferred","anonymous":false},{"inputs":[{"internalType":"contract IRule","name":"rule","type":"address","indexed":true}],"type":"event","name":"RemoveRule","anonymous":false},{"inputs":[{"internalType":"uint256","name":"maxRules","type":"uint256","indexed":false}],"type":"event","name":"SetMaxRules","anonymous":false},{"inputs":[{"internalType":"address","name":"token","type":"address","indexed":false}],"type":"event","name":"TokenBound","anonymous":false},{"inputs":[{"internalType":"address[]","name":"tokens","type":"address[]","indexed":false},{"internalType":"bool","name":"approved","type":"bool","indexed":false}],"type":"event","name":"TokenSelfBindingApprovalBatchSet","anonymous":false},{"inputs":[{"internalType":"address","name":"token","type":"address","indexed":true},{"internalType":"bool","name":"approved","type":"bool","indexed":false}],"type":"event","name":"TokenSelfBindingApprovalSet","anonymous":false},{"inputs":[{"internalType":"address","name":"token","type":"address","indexed":false}],"type":"event","name":"TokenUnbound","anonymous":false},{"inputs":[],"stateMutability":"view","type":"function","name":"DEFAULT_MAX_RULES","outputs":[{"internalType":"uint256","name":"","type":"uint256"}]},{"inputs":[],"stateMutability":"nonpayable","type":"function","name":"acceptOwnership"},{"inputs":[{"internalType":"contract IRule","name":"rule_","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"addRule"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"bindToken"},{"inputs":[{"internalType":"address[]","name":"tokens","type":"address[]"}],"stateMutability":"nonpayable","type":"function","name":"bindTokens"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"view","type":"function","name":"canTransfer","outputs":[{"internalType":"bool","name":"","type":"bool"}]},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"view","type":"function","name":"canTransferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}]},{"inputs":[],"stateMutability":"nonpayable","type":"function","name":"clearRules"},{"inputs":[{"internalType":"contract IRule","name":"rule_","type":"address"}],"stateMutability":"view","type":"function","name":"containsRule","outputs":[{"internalType":"bool","name":"","type":"bool"}]},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"nonpayable","type":"function","name":"created"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"nonpayable","type":"function","name":"destroyed"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"view","type":"function","name":"detectTransferRestriction","outputs":[{"internalType":"uint8","name":"","type":"uint8"}]},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"view","type":"function","name":"detectTransferRestrictionFrom","outputs":[{"internalType":"uint8","name":"","type":"uint8"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"getTokenBound","outputs":[{"internalType":"address","name":"","type":"address"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"getTokenBounds","outputs":[{"internalType":"address[]","name":"","type":"address[]"}]},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"stateMutability":"view","type":"function","name":"isTokenBound","outputs":[{"internalType":"bool","name":"","type":"bool"}]},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"stateMutability":"view","type":"function","name":"isTokenSelfBindingApproved","outputs":[{"internalType":"bool","name":"","type":"bool"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"maxRules","outputs":[{"internalType":"uint256","name":"","type":"uint256"}]},{"inputs":[{"internalType":"uint8","name":"restrictionCode","type":"uint8"}],"stateMutability":"view","type":"function","name":"messageForTransferRestriction","outputs":[{"internalType":"string","name":"","type":"string"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}]},{"inputs":[{"internalType":"contract IRule","name":"rule_","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"removeRule"},{"inputs":[],"stateMutability":"nonpayable","type":"function","name":"renounceOwnership"},{"inputs":[{"internalType":"uint256","name":"ruleId","type":"uint256"}],"stateMutability":"view","type":"function","name":"rule","outputs":[{"internalType":"address","name":"","type":"address"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"rules","outputs":[{"internalType":"address[]","name":"","type":"address[]"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"rulesCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}]},{"inputs":[{"internalType":"uint256","name":"maxRules_","type":"uint256"}],"stateMutability":"nonpayable","type":"function","name":"setMaxRules"},{"inputs":[{"internalType":"contract IRule[]","name":"rules_","type":"address[]"}],"stateMutability":"nonpayable","type":"function","name":"setRules"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"stateMutability":"nonpayable","type":"function","name":"setTokenSelfBindingApproval"},{"inputs":[{"internalType":"address[]","name":"tokens","type":"address[]"},{"internalType":"bool","name":"approved","type":"bool"}],"stateMutability":"nonpayable","type":"function","name":"setTokenSelfBindingApprovalBatch"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"stateMutability":"view","type":"function","name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}]},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"transferOwnership"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"nonpayable","type":"function","name":"transferred"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"nonpayable","type":"function","name":"transferred"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"unbindToken"},{"inputs":[{"internalType":"address[]","name":"tokens","type":"address[]"}],"stateMutability":"nonpayable","type":"function","name":"unbindTokens"},{"inputs":[],"stateMutability":"view","type":"function","name":"version","outputs":[{"internalType":"string","name":"version_","type":"string"}]}],"devdoc":{"kind":"dev","methods":{"acceptOwnership()":{"details":"Repeats the rule-account check of {transferOwnership}: an address nominated while it was not a rule, then added as a rule, cannot accept until it is removed from the rule set."},"addRule(address)":{"details":"Reverts when the configured maximum number of rules is already reached. Security convention: do not grant {RULES_MANAGEMENT_ROLE} to rule contracts.","params":{"rule_":"The IRule contract to add."}},"bindToken(address)":{"custom:security-note":"\"Multi-tenant\" means one instance is shared by multiple token contracts. Downstream state (for the RuleEngine: the per-address accounting held by stateful rules) is shared across all bound tokens, so binding tokens from different issuers silently cross-contaminates it. Only bind tokens that are equally trusted and governed together.","details":"Authorized by {_authorizeTokenBindingChange}.","params":{"token":"The address of the token to bind."}},"bindTokens(address[])":{"custom:security-note":"See {bindToken} for multi-tenant state risks. All tokens bound in this batch share the same downstream state. Only bind tokens that are equally trusted and governed together.","details":"Must be restricted by implementation-specific access control. Atomic: reverts if any token is invalid or already bound (or listed twice), and then binds none of them. This deliberately departs from the usual batch convention of skipping elements already in the target state: a binding change is security-relevant, and a token that is already bound in the list is most likely an operator mistake that should stop the whole operation. An empty array is a no-op.","params":{"tokens":"The token addresses to bind."}},"canTransfer(address,address,uint256)":{"details":"Don't check the balance and the user's right (access control)","params":{"from":"The address sending tokens.","to":"The address receiving tokens.","value":"The amount of tokens to transfer."},"returns":{"_0":"True if the transfer is valid, false otherwise."}},"canTransferFrom(address,address,address,uint256)":{"details":"Does not check balances or access rights (Access Control).","params":{"from":"The source address.","spender":"The address performing the transfer.","to":"The destination address.","value":"The number of tokens to transfer."},"returns":{"_0":"isCompliant True if the transfer complies with policy."}},"clearRules()":{"details":"After calling this function, no rules will remain set. Cost is O(n) in the number of configured rules. With the default cap of 10 this is negligible, but a high {maxRules} setting re-exposes unbounded cost here even though per-transfer cost remains bounded."},"constructor":{"params":{"owner_":"Address of the initial contract owner (ERC-173).","tokenContract":"Address of the token contract to bind at deployment (use zero address to skip)."}},"containsRule(address)":{"details":"Complexity: O(1).","params":{"rule_":"The IRule contract to check for membership."},"returns":{"_0":"True if the rule is present, false otherwise."}},"created(address,uint256)":{"details":"Called by the token contract when new tokens are issued to an account. Reverts if the minting does not comply with the rules.","params":{"to":"The address receiving the minted tokens.","value":"The number of tokens created."}},"destroyed(address,uint256)":{"details":"Called by the token contract when tokens are redeemed or burned. Reverts if the burning does not comply with the rules.","params":{"from":"The address whose tokens are being destroyed.","value":"The number of tokens destroyed."}},"detectTransferRestriction(address,address,uint256)":{"params":{"from":"the origin address","to":"the destination address","value":"to transfer"},"returns":{"_0":"The restriction code or REJECTED_CODE_BASE.TRANSFER_OK (0) if the transfer is valid"}},"detectTransferRestrictionFrom(address,address,address,uint256)":{"details":" See {ERC-1404} Add an additionnal argument `spender` This function is where an issuer enforces the restriction logic of their token transfers. Some examples of this might include: - checking if the token recipient is whitelisted, - checking if a sender's tokens are frozen in a lock-up period, etc.","params":{"from":"The address sending tokens.","spender":"The address initiating the delegated transfer.","to":"The address receiving tokens.","value":"amount of tokens to transfer"},"returns":{"_0":"uint8 restricted code, 0 means the transfer is authorized"}},"getTokenBound()":{"details":"If multiple tokens are supported, consider using getTokenBounds().","returns":{"_0":"The address of the currently bound token."}},"getTokenBounds()":{"details":"This operation copies the entire storage set to memory and is mainly intended for off-chain reads.","returns":{"_0":"An array of bound token addresses."}},"isTokenBound(address)":{"details":"Complexity: O(1).","params":{"token":"The token address to verify."},"returns":{"_0":"True if the token is bound, false otherwise."}},"isTokenSelfBindingApproved(address)":{"params":{"token":"The token address to query."},"returns":{"_0":"True if self-binding is approved for `token`, false otherwise."}},"maxRules()":{"returns":{"_0":"The maximum number of rules that can be configured."}},"messageForTransferRestriction(uint8)":{"details":"See {ERC-1404} This function is effectively an accessor for the \"message\", a human-readable explanation as to why a transaction is restricted.","params":{"restrictionCode":"The restriction code to translate into a message."},"returns":{"_0":"The human-readable message corresponding to `restrictionCode`."}},"owner()":{"details":"Returns the address of the current owner."},"pendingOwner()":{"details":"Returns the address of the pending owner."},"removeRule(address)":{"details":"Reverts if the provided rule is not found or does not match the stored rule at its index. Complexity: O(1).","params":{"rule_":"The IRule contract to remove."}},"renounceOwnership()":{"details":"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner."},"rule(uint256)":{"details":"Reverts if `ruleId` is out of bounds. Complexity: O(1). Note that there are no guarantees on the ordering of values inside the array, and it may change when more values are added or removed.","params":{"ruleId":"The index of the desired rule in the array."},"returns":{"_0":"The address of the corresponding IRule contract, return the `zero address` is out of bounds."}},"rules()":{"details":"This is a view-only function that does not modify state. This operation will copy the entire storage to memory, which can be quite expensive. This is designed to mostly be used by view accessors that are queried without any gas fees.","returns":{"_0":"An array of all active rule contract addresses."}},"rulesCount()":{"details":"Equivalent to the length of the internal rules array. Complexity: O(1)","returns":{"_0":"The number of active rules."}},"setMaxRules(uint256)":{"details":"Access control is implementation specific (admin/owner). Setting a very high cap re-exposes unbounded gas cost for administrative operations such as {clearRules} even though normal per-transfer cost remains bounded.","params":{"maxRules_":"New maximum number of rules."}},"setRules(address[])":{"details":"Replaces the entire rule set atomically. Reverts if `rules_` is empty. Use {clearRules} to remove all rules explicitly. To transition from one non-empty set to another without an enforcement gap, call this function directly with the new set. Emits {ClearRules} when the existing rule set is non-empty, then emits {AddRule} for each new rule. Off-chain indexers must handle both events to reconstruct state. Security convention: rule contracts should be treated as trusted business logic, but should not also be granted {RULES_MANAGEMENT_ROLE}.","params":{"rules_":"The array of addresses representing the new rules to be set."}},"setTokenSelfBindingApproval(address,bool)":{"details":"Must be restricted by implementation-specific access control. An approval stays in force until it is revoked here or until the binding manager unbinds the token ({unbindToken} or {unbindTokens}), which revokes it and emits {TokenSelfBindingApprovalSet} with `false`. A token that unbinds itself keeps its approval, so it can bind itself again later.","params":{"approved":"Whether self-binding is approved for `token`.","token":"The token address to configure."}},"setTokenSelfBindingApprovalBatch(address[],bool)":{"details":"Must be restricted by implementation-specific access control. Reverts if any token in `tokens` is the zero address. Emits a single {TokenSelfBindingApprovalBatchSet} with the input array, not one {TokenSelfBindingApprovalSet} per token.","params":{"approved":"Whether self-binding is approved for all provided tokens.","tokens":"The token addresses to configure."}},"supportsInterface(bytes4)":{"params":{"interfaceId":"The interface identifier to check."},"returns":{"_0":"True if the interface is supported, false otherwise."}},"transferOwnership(address)":{"details":"Reverts when `newOwner` is already configured as a rule.","params":{"newOwner":"The address of the new owner."}},"transferred(address,address,address,uint256)":{"details":"Must revert if the transfer is invalid Same name as ERC-3643 but with one supplementary argument `spender` This function can be used to update state variables of the RuleEngine contract This function can be called ONLY by the token contract bound to the RuleEngine Which overload the token calls (since CMTAT v3.3.0): - this 4-argument overload for `transferFrom` (`spender` = approved spender) and for every operation initiated by an operator, with the operator as `spender`: mint (`from == address(0)`), burn (`to == address(0)`), including `burnFrom`, self-burn and cross-chain mint/burn, and the minter `batchTransfer`; - the 3-argument ERC-3643 overload `transferred(from, to, value)`, inherited from {IERC3643IComplianceContract}, only for a direct `transfer`. Up to CMTAT v3.2.0, mint, burn and the minter transfer used the 3-argument overload. WARNING - zero-value calls are permissionless. ERC-20 requires transfers of `0` to be treated as normal transfers, and OpenZeppelin's `_spendAllowance` consumes no allowance when `value == 0`. Any address can therefore call `transferFrom(victim, anyone, 0)` on the token and reach this callback for an arbitrary `from`, with itself as `spender`, without ever having been approved. The token deliberately does not suppress the notification, because doing so would make its compliance notifications inconsistent with its own ERC-20 transfer semantics. Implementations MUST therefore treat `value == 0` as carrying no economic meaning: any stateful rule (cooldown, holding period, quota, tax bucket, counter, holder tracking, ...) MUST be a no-op for a zero value, otherwise an attacker can desynchronize policy state from balances, or keep a holder permanently restricted, at no cost. The same applies to the 3-argument ERC-3643 overload, which a zero-value `transfer(to, 0)` reaches the same way.","params":{"from":"token holder address","spender":"spender address (sender)","to":"receiver address","value":"value of tokens involved in the transfer; MAY be `0` — see the warning above"}},"transferred(address,address,uint256)":{"details":" This function can be used to update state variables of the compliance contract This function can be called ONLY by the token contract bound to the compliance","params":{"from":"The address of the sender","to":"The address of the receiver","value":"value of tokens involved in the transfer"}},"unbindToken(address)":{"details":"Authorized by {_authorizeTokenBindingChange}. Operator warning: unbinding is an administrative operation and does not erase any state already stored downstream in a previously shared (\"multi-tenant\") setup.","params":{"token":"The address of the token to unbind."}},"unbindTokens(address[])":{"details":"Must be restricted by implementation-specific access control. Atomic: reverts if any token is not currently bound, and then unbinds none of them. Deliberately not the skip-if-already-done batch convention, for the same reason as {bindTokens}. An empty array is a no-op. Like a manager's {unbindToken}, revokes each token's self-binding approval (see {setTokenSelfBindingApproval}).","params":{"tokens":"The token addresses to unbind."}},"version()":{"details":"This value is useful to know which smart contract version has been used","returns":{"version_":"A string representing the version of the token implementation (e.g., \"1.0.0\")."}}},"version":1},"userdoc":{"kind":"user","methods":{"DEFAULT_MAX_RULES()":{"notice":"Default upper bound on the number of rules a RuleEngine may hold."},"acceptOwnership()":{"notice":"Completes the ownership transfer; callable by the pending owner only."},"addRule(address)":{"notice":"Adds a new rule to the current rule set."},"bindToken(address)":{"notice":"Binds a token contract, allowing it to call the bound-token entry points."},"bindTokens(address[])":{"notice":"Binds several token contracts in a single call."},"canTransfer(address,address,uint256)":{"notice":"Returns true if the transfer is valid, and false otherwise."},"canTransferFrom(address,address,address,uint256)":{"notice":"Checks if `spender` can transfer `value` tokens from `from` to `to` under compliance rules."},"clearRules()":{"notice":"Removes all configured rules."},"constructor":{"notice":"Deploys a RuleEngine with ERC-173 two-step ownership transfer, without a trusted forwarder."},"containsRule(address)":{"notice":"Checks whether a specific rule is currently configured."},"created(address,uint256)":{"notice":"Updates the compliance contract state when tokens are created (minted)."},"destroyed(address,uint256)":{"notice":"Updates the compliance contract state when tokens are destroyed (burned)."},"detectTransferRestriction(address,address,uint256)":{"notice":"Queries every rule, in order, and returns the first restriction code that is not zero"},"detectTransferRestrictionFrom(address,address,address,uint256)":{"notice":"Returns a uint8 code to indicate if a transfer is restricted or not"},"getTokenBound()":{"notice":"Returns the single token currently bound to this compliance contract."},"getTokenBounds()":{"notice":"Returns all tokens currently bound."},"isTokenBound(address)":{"notice":"Checks whether a token is currently bound."},"isTokenSelfBindingApproved(address)":{"notice":"Returns whether a token is approved to bind and unbind itself."},"maxRules()":{"notice":"Returns the maximum number of rules allowed in the engine."},"removeRule(address)":{"notice":"Removes a specific rule from the current rule set."},"rule(uint256)":{"notice":"Retrieves the rule address at a specific index."},"rules()":{"notice":"Returns the full list of currently configured rules."},"rulesCount()":{"notice":"Returns the total number of currently configured rules."},"setMaxRules(uint256)":{"notice":"Updates the maximum number of rules allowed in the engine."},"setRules(address[])":{"notice":"Defines the rules for the rule engine."},"setTokenSelfBindingApproval(address,bool)":{"notice":"Sets whether a token is allowed to bind and unbind itself."},"setTokenSelfBindingApprovalBatch(address[],bool)":{"notice":"Sets self-binding approval for multiple tokens in one transaction."},"supportsInterface(bytes4)":{"notice":"ERC-165 interface detection."},"transferOwnership(address)":{"notice":"Starts ownership transfer to `newOwner`."},"transferred(address,address,address,uint256)":{"notice":"Function called whenever tokens are transferred from one wallet to another, minted or burned, when the token knows the account that initiated the operation (`spender`)."},"transferred(address,address,uint256)":{"notice":"Function called whenever tokens are transferred from one wallet to another"},"unbindToken(address)":{"notice":"Unbinds a token contract, revoking its access to the bound-token entry points."},"unbindTokens(address[])":{"notice":"Unbinds several token contracts in a single call."},"version()":{"notice":"Returns the current version of the token contract."}},"version":1}},"settings":{"remappings":["@chainlink/contracts-ccip/=lib/Rules/lib/chainlink-ace/node_modules/@chainlink/contracts-ccip/chains/evm/contracts/","@chainlink/contracts/=lib/Rules/lib/chainlink-ace/node_modules/@chainlink/contracts/","@chainlink/contracts@1.4.0/=lib/Rules/lib/chainlink-doc/node_modules/@chainlink/contracts-1.4.0/","@chainlink/cross-chain-identity/=lib/Rules/lib/chainlink-ace/packages/cross-chain-identity/src/","@chainlink/local/=lib/Rules/lib/chainlink-doc/node_modules/@chainlink/local/","@chainlink/policy-management/=lib/Rules/lib/chainlink-ace/packages/policy-management/src/","@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/","@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/","@openzeppelin/contracts@4.7.3/=lib/Rules/lib/chainlink-doc/node_modules/@openzeppelin/contracts-4.7.3/","@openzeppelin/contracts@4.8.3/=lib/Rules/lib/chainlink-ace/node_modules/@openzeppelin/contracts-4.8.3/","@openzeppelin/contracts@4.9.6/=lib/Rules/lib/chainlink-doc/node_modules/@openzeppelin/contracts-4.9.6/","@openzeppelin/contracts@5.0.2/=lib/Rules/lib/chainlink-ace/node_modules/@openzeppelin/contracts/","@openzeppelin/contracts@5.1.0/=lib/Rules/lib/chainlink-doc/node_modules/@openzeppelin/contracts-5.1.0/","@openzeppelin/contracts@5.3.0/=lib/Rules/lib/chainlink-ace/node_modules/@openzeppelin/contracts-5.3.0/","CMTAT/=lib/CMTAT/contracts/","CMTATv3.0.0/=lib/CMTATv3.0.0/contracts/","ERC-3643/=lib/ERC-3643/contracts/","ERC3643/=lib/Rules/lib/ERC-3643/contracts/","RuleEngine/=lib/Rules/lib/RuleEngine/","Rules/=lib/Rules/","chainlink-ace/=lib/Rules/lib/chainlink-ace/","chainlink-doc/=lib/Rules/lib/","erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/","forge-std/=lib/forge-std/src/","halmos-cheatcodes/=lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/","openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/","openzeppelin-contracts/=lib/openzeppelin-contracts/"],"optimizer":{"enabled":true,"runs":200},"metadata":{"bytecodeHash":"ipfs"},"compilationTarget":{"src/deployment/ownable/RuleEngineOwnable2Step.sol":"RuleEngineOwnable2Step"},"evmVersion":"osaka","libraries":{}},"sources":{"lib/CMTAT/contracts/interfaces/engine/IRuleEngine.sol":{"keccak256":"0xeda899e2e46a9b9c3516acb61a7f7e92ed098928379010655c330da721aaffa7","urls":["bzz-raw://60f8555330fc531dff7d0d71a862696fb286a0ba3290e41efbbbf4dd25947a3c","dweb:/ipfs/QmWvbsBGWPtNMNN2EEedwdzzvQG7NtSj9VD2fmNgqVtCXN"],"license":"MPL-2.0"},"lib/CMTAT/contracts/interfaces/technical/IERC5679.sol":{"keccak256":"0x5bee30750c9a65438469a6c5bd8465e1603eec3aeeb94c07bd64ba3e9ee766e1","urls":["bzz-raw://ef7a5c5f0d47135c97ab5d7456d31e513a71c849ae7f2f5395f860be125c4fbc","dweb:/ipfs/Qmezem3qqSjij6ggyB34wC2S15KrY9fu42oymyS9epAYCQ"],"license":"MPL-2.0"},"lib/CMTAT/contracts/interfaces/tokenization/IERC3643Partial.sol":{"keccak256":"0x5c84c2e2442824e98625c471482fb3c9502f43f4c345e7c0fb07fa549be02e26","urls":["bzz-raw://19071f2d12fb580d37eeee07885461f193568df34f3f69d2c5d65ce655d84435","dweb:/ipfs/QmRqHwC7LksE3YPohMtxFieiPerhWdoDNUUMMLbB4XYvhK"],"license":"MPL-2.0"},"lib/CMTAT/contracts/interfaces/tokenization/draft-IERC1404.sol":{"keccak256":"0xc27cdac182d930a94391d589bdafa15364b6f8d9bf211175781dba661f1c0336","urls":["bzz-raw://b509fa7f3cfd785632569f6ae3bec846aa0beefd73c1d5bde233440cae919f0f","dweb:/ipfs/QmPCAdiEun8gaMqS8KhwPpRZV2zXAPfURRaF4C2KjX5Kby"],"license":"MPL-2.0"},"lib/CMTAT/contracts/interfaces/tokenization/draft-IERC7551.sol":{"keccak256":"0x84b73eb77ec82d6d7b313eff2d87f58d3b795840d004aaa10c611b360b827e30","urls":["bzz-raw://a5b8c99fb3600369065a422d3821ba441dc06fc64f50ce0f33950a76ad82b51b","dweb:/ipfs/QmbviJsZPY3xuLU3cHUWJx11aJCPAuN4WKnCufN4kVLm2U"],"license":"MPL-2.0"},"lib/CMTAT/contracts/interfaces/tokenization/draft-IERC7943.sol":{"keccak256":"0xc69588a72da81057ee278e961e8e3bb61a28d64c3c6cebe494ce00809c1cef15","urls":["bzz-raw://148f117d9c463de441f81e6c0a67e95f1f14a61db209492dd0a1767b5572f21a","dweb:/ipfs/QmUjT5uyJfNSYgUWn5Dxhf6Sx9Y1z8CNf3PuTEaGoAx3za"],"license":"MPL-2.0"},"lib/CMTAT/contracts/library/ERC1404ExtendInterfaceId.sol":{"keccak256":"0xf8268f4eb3a6b2e26c32cf76c5c76b6c17df3385c150f05953538a2472149247","urls":["bzz-raw://05108de7a7ba2a0a67978bdfe8e500360674db6d894f42970bb1016b36639056","dweb:/ipfs/QmRux9Qj1GomATseS6Tyq9uiPPNNipuxg2HjdjnPjgSQds"],"license":"MPL-2.0"},"lib/CMTAT/contracts/library/RuleEngineInterfaceId.sol":{"keccak256":"0x1152a49cba4232d943e295d259eb8a1b216d815067367410a5729a256dae4051","urls":["bzz-raw://470f4435a5e62b0ba0ad70f8657b2db0e4cc3b7f2561772adb944ce010551ee6","dweb:/ipfs/QmXECahRr8rK9XJPZwBCnemLDVPdFvPEBusezhaBqbLBqp"],"license":"MPL-2.0"},"lib/openzeppelin-contracts/contracts/access/Ownable.sol":{"keccak256":"0xff6d0bb2e285473e5311d9d3caacb525ae3538a80758c10649a4d61029b017bb","urls":["bzz-raw://8ed324d3920bb545059d66ab97d43e43ee85fd3bd52e03e401f020afb0b120f6","dweb:/ipfs/QmfEckWLmZkDDcoWrkEvMWhms66xwTLff9DDhegYpvHo1a"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/access/Ownable2Step.sol":{"keccak256":"0xdcad8898fda432696597752e8ec361b87d85c82cb258115427af006dacf7128c","urls":["bzz-raw://e2c9d517f0c136d54bd00cd57959d25681d4d6273f5bbbc263afe228303772f0","dweb:/ipfs/QmReNFjXBiufByiAAzfSQ2SM5r3qeUErn46BmN3yVRvrek"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/interfaces/IERC165.sol":{"keccak256":"0x0afcb7e740d1537b252cb2676f600465ce6938398569f09ba1b9ca240dde2dfc","urls":["bzz-raw://1c299900ac4ec268d4570ecef0d697a3013cd11a6eb74e295ee3fbc945056037","dweb:/ipfs/Qmab9owJoxcA7vJT5XNayCMaUR1qxqj1NDzzisduwaJMcZ"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/Arrays.sol":{"keccak256":"0x772f0c778626a7bdcbcbabca74b825ae9b9dc89d2a47a98b402b1187fbaa63a4","urls":["bzz-raw://eba1d46e58e8880b45c6d51245dc94585b81d6d7290ca77ef50037a6193ed301","dweb:/ipfs/Qme3CWun5qQACjGEerT2MCvhs6brKGFfJirGnzV1ypKTXA"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/Comparators.sol":{"keccak256":"0x302eecd8cf323b4690e3494a7d960b3cbce077032ab8ef655b323cdd136cec58","urls":["bzz-raw://49ba706f1bc476d68fe6c1fad75517acea4e9e275be0989b548e292eb3a3eacd","dweb:/ipfs/QmeBpvcdGWzWMKTQESUCEhHgnEQYYATVwPxLMxa6vMT7jC"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/Context.sol":{"keccak256":"0x493033a8d1b176a037b2cc6a04dad01a5c157722049bbecf632ca876224dd4b2","urls":["bzz-raw://6a708e8a5bdb1011c2c381c9a5cfd8a9a956d7d0a9dc1bd8bcdaf52f76ef2f12","dweb:/ipfs/Qmax9WHBnVsZP46ZxEMNRQpLQnrdE4dK8LehML1Py8FowF"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/Panic.sol":{"keccak256":"0xf7fe324703a64fc51702311dc51562d5cb1497734f074e4f483bfb6717572d7a","urls":["bzz-raw://c6a5ff4f9fd8649b7ee20800b7fa387d3465bd77cf20c2d1068cd5c98e1ed57a","dweb:/ipfs/QmVSaVJf9FXFhdYEYeCEfjMVHrxDh5qL4CGkxdMWpQCrqG"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/SlotDerivation.sol":{"keccak256":"0x94045fd4f268edf2b2d01ef119268548c320366d6f5294ad30c1b8f9d4f5225f","urls":["bzz-raw://edfda81f426f8948b3834115c21e83c48180e6db0d2a8cd2debb2185ed349337","dweb:/ipfs/QmdYZneFyDAux1BuWQxLAdqtABrGS2k9WYCa7C9dvpKkWv"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol":{"keccak256":"0xcf74f855663ce2ae00ed8352666b7935f6cddea2932fdf2c3ecd30a9b1cd0e97","urls":["bzz-raw://9f660b1f351b757dfe01438e59888f31f33ded3afcf5cb5b0d9bf9aa6f320a8b","dweb:/ipfs/QmarDJ5hZEgBtCmmrVzEZWjub9769eD686jmzb2XpSU1cM"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol":{"keccak256":"0x2d9dc2fe26180f74c11c13663647d38e259e45f95eb88f57b61d2160b0109d3e","urls":["bzz-raw://81233d1f98060113d9922180bb0f14f8335856fe9f339134b09335e9f678c377","dweb:/ipfs/QmWh6R35SarhAn4z2wH8SU456jJSYL2FgucfTFgbHJJN4E"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165Checker.sol":{"keccak256":"0x7c7ad70641a7f8cd44def0857ec97b0e40bfd073b2d6037a5f57ce9527ee9bc5","urls":["bzz-raw://e05c6572dfe769f7aea6f3a8002951cc12d143d980dad29f6c5feedf9408bc14","dweb:/ipfs/QmXM7C8YEptxisZiEefXUrwdXt3zMaCobmkCchxTtDg1oK"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol":{"keccak256":"0x8891738ffe910f0cf2da09566928589bf5d63f4524dd734fd9cedbac3274dd5c","urls":["bzz-raw://971f954442df5c2ef5b5ebf1eb245d7105d9fbacc7386ee5c796df1d45b21617","dweb:/ipfs/QmadRjHbkicwqwwh61raUEapaVEtaLMcYbQZWs9gUkgj3u"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/math/Math.sol":{"keccak256":"0x59973a93b1f983f94e10529f46ca46544a9fec2b5f56fb1390bbe9e0dc79f857","urls":["bzz-raw://c55ef8f0b9719790c2ae6f81d80a59ffb89f2f0abe6bc065585bd79edce058c5","dweb:/ipfs/QmNNmCbX9NjPXKqHJN8R1WC2rNeZSQrPZLd6FF6AKLyH5Y"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol":{"keccak256":"0xc8cae21c9ae4a46e5162ff9bf5b351d6fa6a6eba72d515f3bc1bdfeda7fdf083","urls":["bzz-raw://ce830ebcf28e31643caba318996db3763c36d52cd0f23798ba83c135355d45e9","dweb:/ipfs/QmdGPcvptHN7UBCbUYBbRX3hiRVRFLRwno8b4uga6uFNif"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/structs/EnumerableSet.sol":{"keccak256":"0xd553ff8b7d55679f0711f1598600ac292dbd8cfdf4b2419b9cabe4c931172895","urls":["bzz-raw://7905ccb27e2308fd0d90dc1212161003ab6964e1c176593db1ccedef705bcc09","dweb:/ipfs/QmW37vm2PcrWLKnN74sKkvAzqSwntCEfCp4EoSEvbBHWkj"],"license":"MIT"},"src/RuleEngineBase.sol":{"keccak256":"0xb3d832fa55b615574d80b0e0ad76620ad236aa046523617ed5daa46ae07bf853","urls":["bzz-raw://7be31bf5dbd3fa1be025cdc4b7674b76bf40e1c14ce89ec78f792cb3d7ed804e","dweb:/ipfs/QmPq4xBiB3XwXerWtuonZLGiWHMqvz5tKvjhTh9AiWkbww"],"license":"MPL-2.0"},"src/RuleEngineOwnableShared.sol":{"keccak256":"0xa78493398d8b0554e72def7f14d7439109bd4dbd5e07f1466b40acea2bb7dc02","urls":["bzz-raw://ebd87d69b4f6eb193c5d03476381ac132f9587248422d3306dda95b79fd4e470","dweb:/ipfs/QmWYDLvPWjRcfxdR2KhXAij8U9TrFjeM77fsJRX25jWQmY"],"license":"MPL-2.0"},"src/deployment/ownable/RuleEngineOwnable2Step.sol":{"keccak256":"0xf8d7f52cf7857f0d89adeb7dfa42444dbaf371dd6cca712c797181baf7a3fe97","urls":["bzz-raw://f3307f7a2800dfc1b23c89cf6eebcbf21fd283eeb19343a374bc5bc771b7a4ef","dweb:/ipfs/QmbFjoQ97zF74QCWwbswVwKL7wB1Gx4pfRdu7jp2vE36DB"],"license":"MPL-2.0"},"src/interfaces/IERC3643Compliance.sol":{"keccak256":"0xd0edd6697d67135853576ac6a40cadaffd787cedea98071708bbfb189c7ee5bc","urls":["bzz-raw://4ed3cd3af64fccff17a1f33989cdfbdacbc0e4f32a56de11a072cf9e2277a1f6","dweb:/ipfs/QmenRqRw1Yy39yDv1pJgBmnHtwuZhDdHE4omchL41CjXjb"],"license":"MPL-2.0"},"src/interfaces/IERC3643ComplianceExtended.sol":{"keccak256":"0x4a43bf330c7a904cba110acf52f519718d8409514c377912d5bd063c9d963729","urls":["bzz-raw://c671879c591760ecbc2691e2f24adfb215a658c9fe6eb0c05dd1ca980054e585","dweb:/ipfs/QmdbA19PFpJgHraF46YrcMNzUgswbTRA92atL2Lha63JLY"],"license":"MPL-2.0"},"src/interfaces/IRule.sol":{"keccak256":"0x81580b67f7be09049aa64d93cc1d8d691a87c639adc1cf169dc6073e1e543a5c","urls":["bzz-raw://6f1808c3ed18ef1acbccdd9b30011b6e7220d388cfd66cba40b1ef0b485306a1","dweb:/ipfs/QmcUCQ5MYcf7KTtoeqMKsTutPPSJhNTaK1ntHV21ioS9Fm"],"license":"MPL-2.0"},"src/interfaces/IRulesManagementModule.sol":{"keccak256":"0x082dd58070e83b02f275584afa872c4583ac4ca8ad12eb329fc11301470147f9","urls":["bzz-raw://e2d0ad78dc323881864f406acd44976f5de39cdc97a6c99a724d8458b993e2e2","dweb:/ipfs/QmRFfMbXbdiAYV3vQyNppXG7tHTji6mV1Y5Cu3ZzEQm5ng"],"license":"MPL-2.0"},"src/interfaces/ITokenBinding.sol":{"keccak256":"0x34dfea4e118c966adf867c0899844515566251819b4e4510fd8ee424555493fd","urls":["bzz-raw://1d054ed49874816688a6e71f76d611bbdefd492d122ae386cb804c6f5af677a7","dweb:/ipfs/QmRaYX4aJWYSNWNa1D4Nich3k7hkGM9rTfc9s2XaVqyRjy"],"license":"MPL-2.0"},"src/interfaces/ITokenBindingExtended.sol":{"keccak256":"0x01f3ab56dffce860d03e72d10e9f2d13b6bfc9004cf058c63a0b23e3b226da99","urls":["bzz-raw://521e0c9651632b70d61c4c3bd0b14c6f05d818166fe65dbed8e3253158b7637e","dweb:/ipfs/QmY2xEVvfV1dgtFYw6coHX3Z7Fm7yRhzPaGyt6cYBMVf76"],"license":"MPL-2.0"},"src/modules/ERC3643ComplianceExtendedModule.sol":{"keccak256":"0x6f808b068517e9e15f09fc6a9d4190001ec8c2314a10e27a85a2d43e44c84fb1","urls":["bzz-raw://c62c0b77fdd8b6e7bf7aa5bf8134a78ff024d6489a23f746874a99df38a8a265","dweb:/ipfs/QmV7PG3ZUUzwDs9tpooC3hmBu5e39buJnJ4TRditojJ3hu"],"license":"MPL-2.0"},"src/modules/ERC3643ComplianceModule.sol":{"keccak256":"0x7cda81af8687328ac2089f9d1d78352e0e75d0f70a4ba8e2b3ac82896f22863f","urls":["bzz-raw://50711cb94d69ea63d787a8bb19c38c0b99539029ec8fb957a8eff00880fc11fc","dweb:/ipfs/QmSapDWh5mpvWn1q6JteZisJfVGPrCz47WP2BBrJCccEjV"],"license":"MPL-2.0"},"src/modules/RulesManagementModule.sol":{"keccak256":"0xe4d9425613284e71a5e3d590d5433167a9751d9496f57efa914baa81f493e66d","urls":["bzz-raw://d07a16e6869df86c526ef89e7e359e34a9553dc4288b262abd2979359ecf720e","dweb:/ipfs/QmRy2JEsyhkv1mxv7eFaSbEWN4A3gtpPSUnnV48W2KiV4u"],"license":"MPL-2.0"},"src/modules/TokenBindingExtendedModule.sol":{"keccak256":"0x4e1ca7b2ec78608c3a7960bec7102a1780bdf3ec7ff544b612bafaf738b34d05","urls":["bzz-raw://657bcdd303fd5a7fbe733b283f69d8e8aa73efeeeaf95c0ae7479769ac573693","dweb:/ipfs/QmXiWPrv8pEqvBQck8jxC7NwB1MUdGQfLjihK6etYcZ54j"],"license":"MPL-2.0"},"src/modules/TokenBindingModule.sol":{"keccak256":"0xf65f46311d0078f60c30e3359dca988e39cba45b9eee53a09d618bfa70e6ef9b","urls":["bzz-raw://e8c458ecfd41df5fb4a391e7ef837fd5ed5c999e61ccc0e6b4bd23023a739832","dweb:/ipfs/Qmdsr765aw9fPFN2M9cSCP69o1o41FNCqhrXjHgEXNwbXV"],"license":"MPL-2.0"},"src/modules/VersionModule.sol":{"keccak256":"0x35daf007be8b9bb1cb9196ae2decb3e5ad4b574f6390f8fc010b78796ac42f73","urls":["bzz-raw://b1b29d75e1c5023a0c6cb8c56638a17d855a3fdc051a60b9d2f304b99f7876d2","dweb:/ipfs/QmXSCVjLuViC8916LwNpKtw8hqyH78Ptag3xH1n7F1fY4g"],"license":"MPL-2.0"},"src/modules/library/ComplianceInterfaceId.sol":{"keccak256":"0xd54bed5328e732f753d2886aeaa2761b2d66536d5247d4548e0ac1c83c7a0dac","urls":["bzz-raw://ad695339fdfe72446a69d2dfbe39373affe2f37299ad921e57016069a7bc3592","dweb:/ipfs/QmWathGt3E85hLfy5rrAYdb291W8VoTa4gpGPoxtWGvNNA"],"license":"MPL-2.0"},"src/modules/library/ERC1404InterfaceId.sol":{"keccak256":"0x07dc6905e137096cd0ae88be29b112d0e54a83ddf8ca527a281718010f6abcce","urls":["bzz-raw://9249dce67cb59432bdbc9e49978c6cac0346cda3d3fca97c5a310e0f424e1600","dweb:/ipfs/QmRi5awH3hjwvd3k3td48y5Cf64n1wvX9wCWy6fQLayuKs"],"license":"MPL-2.0"},"src/modules/library/Ownable2StepInterfaceId.sol":{"keccak256":"0xe4c5bd8569553d93b7283118318993fea44410a608e7bda490ff27bc3e848f89","urls":["bzz-raw://8145a588e30eb836199f489e16464123082cd2af9989c9aeca1038c69ac3da6f","dweb:/ipfs/QmNrQJ2mQQjqx3UY86mKB2M1vCgLQakumumKxVhvqX6AhF"],"license":"MPL-2.0"},"src/modules/library/OwnableInterfaceId.sol":{"keccak256":"0xdbe06b3203e21e41d1fd2a3ef373a80727193443dfd981de6821422158015d4f","urls":["bzz-raw://ebe8699ae8af81c5cd82f25a1609d9396d72ae957647c33aaa745aadcdac8d18","dweb:/ipfs/QmV73gwDJPFthn8VspdYE6GsoAcQMAR7TachUK8YrPonuT"],"license":"MPL-2.0"},"src/modules/library/RuleEngineInvariantStorage.sol":{"keccak256":"0x50a212f09f1695662965e5fba643b42a1978bec2a8368abbf43983489c983096","urls":["bzz-raw://6137f01df7630527c985d85d2f7446359c678fcb933b66c55b51f583757b5c4a","dweb:/ipfs/QmeHo47WQm1V99xZHS4soMk68UdtXtZhtWhV3dQC5BtA7u"],"license":"MPL-2.0"},"src/modules/library/RuleInterfaceId.sol":{"keccak256":"0x0d86820eee4c92b21d6704bea8ce7bd2cc1b35f6e4a1ceabbcf2a10f1c6b02ec","urls":["bzz-raw://cfb560cb8588983b8c79a973d03c214a149bf1ac034fa9130ce93f0031a404d7","dweb:/ipfs/Qmc6qt4E4BHdDyLUegCsgxqhf7ZFUiX4ahj8FjM54V7wpY"],"license":"MPL-2.0"},"src/modules/library/RulesManagementModuleInvariantStorage.sol":{"keccak256":"0xb81ea3a54c6e8d47b87d6c3d9fb5aae80c3430021b8cd66d9adeef7f5fc95893","urls":["bzz-raw://cfcbadc2011f60de7189273c278dda1df2218aeeb153bee3b8a93447ec95df21","dweb:/ipfs/Qmem5FqCLEfBJQdJzS7Xzd3zSfyL8Muf9Wv5WvCiBVsqfh"],"license":"MPL-2.0"},"src/modules/library/TokenBindingModuleInvariantStorage.sol":{"keccak256":"0x9bab8e5b265068da356fd46e343a7c6c73776f3964fdeaeff056e8ce104d40a5","urls":["bzz-raw://e2e75d2d52b1e4f5cbb832d194266de9a1b3a8cc2101e875dce43a2664c31a05","dweb:/ipfs/QmUsd5cTPsE89WKm3kTUWsobR9JsBDUY8NdxDU5RPYpvP6"],"license":"MPL-2.0"}},"version":1},"ast":{"absolutePath":"src/deployment/ownable/RuleEngineOwnable2Step.sol","id":10209,"exportedSymbols":{"Ownable":[1144],"Ownable2Step":[1230],"Ownable2StepInterfaceId":[14461],"RuleEngineOwnable2Step":[10208],"RuleEngineOwnableShared":[9689]},"nodeType":"SourceUnit","src":"37:3068:34","nodes":[{"id":10094,"nodeType":"PragmaDirective","src":"37:24:34","nodes":[],"literals":["solidity","^","0.8",".27"]},{"id":10096,"nodeType":"ImportDirective","src":"91:77:34","nodes":[],"absolutePath":"lib/openzeppelin-contracts/contracts/access/Ownable2Step.sol","file":"@openzeppelin/contracts/access/Ownable2Step.sol","nameLocation":"-1:-1:-1","scope":10209,"sourceUnit":1231,"symbolAliases":[{"foreign":{"id":10095,"name":"Ownable2Step","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":1230,"src":"99:12:34","typeDescriptions":{}},"nameLocation":"-1:-1:-1"}],"unitAlias":""},{"id":10098,"nodeType":"ImportDirective","src":"169:67:34","nodes":[],"absolutePath":"lib/openzeppelin-contracts/contracts/access/Ownable.sol","file":"@openzeppelin/contracts/access/Ownable.sol","nameLocation":"-1:-1:-1","scope":10209,"sourceUnit":1145,"symbolAliases":[{"foreign":{"id":10097,"name":"Ownable","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":1144,"src":"177:7:34","typeDescriptions":{}},"nameLocation":"-1:-1:-1"}],"unitAlias":""},{"id":10100,"nodeType":"ImportDirective","src":"237:74:34","nodes":[],"absolutePath":"src/RuleEngineOwnableShared.sol","file":"../../RuleEngineOwnableShared.sol","nameLocation":"-1:-1:-1","scope":10209,"sourceUnit":9690,"symbolAliases":[{"foreign":{"id":10099,"name":"RuleEngineOwnableShared","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":9689,"src":"245:23:34","typeDescriptions":{}},"nameLocation":"-1:-1:-1"}],"unitAlias":""},{"id":10102,"nodeType":"ImportDirective","src":"312:90:34","nodes":[],"absolutePath":"src/modules/library/Ownable2StepInterfaceId.sol","file":"../../modules/library/Ownable2StepInterfaceId.sol","nameLocation":"-1:-1:-1","scope":10209,"sourceUnit":14462,"symbolAliases":[{"foreign":{"id":10101,"name":"Ownable2StepInterfaceId","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":14461,"src":"320:23:34","typeDescriptions":{}},"nameLocation":"-1:-1:-1"}],"unitAlias":""},{"id":10208,"nodeType":"ContractDefinition","src":"677:2427:34","nodes":[{"id":10122,"nodeType":"FunctionDefinition","src":"1057:108:34","nodes":[],"body":{"id":10121,"nodeType":"Block","src":"1163:2:34","nodes":[],"statements":[]},"documentation":{"id":10108,"nodeType":"StructuredDocumentation","src":"756:296:34","text":" @notice Deploys a RuleEngine with ERC-173 two-step ownership transfer, without a trusted forwarder.\n @param owner_ Address of the initial contract owner (ERC-173).\n @param tokenContract Address of the token contract to bind at deployment (use zero address to skip)."},"implemented":true,"kind":"constructor","modifiers":[{"arguments":[{"id":10115,"name":"tokenContract","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":10112,"src":"1132:13:34","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"id":10116,"kind":"baseConstructorSpecifier","modifierName":{"id":10114,"name":"RuleEngineOwnableShared","nameLocations":["1108:23:34"],"nodeType":"IdentifierPath","referencedDeclaration":9689,"src":"1108:23:34"},"nodeType":"ModifierInvocation","src":"1108:38:34"},{"arguments":[{"id":10118,"name":"owner_","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":10110,"src":"1155:6:34","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"id":10119,"kind":"baseConstructorSpecifier","modifierName":{"id":10117,"name":"Ownable","nameLocations":["1147:7:34"],"nodeType":"IdentifierPath","referencedDeclaration":1144,"src":"1147:7:34"},"nodeType":"ModifierInvocation","src":"1147:15:34"}],"name":"","nameLocation":"-1:-1:-1","parameters":{"id":10113,"nodeType":"ParameterList","parameters":[{"constant":false,"id":10110,"mutability":"mutable","name":"owner_","nameLocation":"1077:6:34","nodeType":"VariableDeclaration","scope":10122,"src":"1069:14:34","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":10109,"name":"address","nodeType":"ElementaryTypeName","src":"1069:7:34","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"},{"constant":false,"id":10112,"mutability":"mutable","name":"tokenContract","nameLocation":"1093:13:34","nodeType":"VariableDeclaration","scope":10122,"src":"1085:21:34","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":10111,"name":"address","nodeType":"ElementaryTypeName","src":"1085:7:34","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"src":"1068:39:34"},"returnParameters":{"id":10120,"nodeType":"ParameterList","parameters":[],"src":"1163:0:34"},"scope":10208,"stateMutability":"nonpayable","virtual":false,"visibility":"public"},{"id":10144,"nodeType":"FunctionDefinition","src":"1365:209:34","nodes":[],"body":{"id":10143,"nodeType":"Block","src":"1444:130:34","nodes":[],"statements":[{"expression":{"arguments":[{"id":10134,"name":"newOwner","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":10125,"src":"1508:8:34","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":10131,"name":"RuleEngineOwnableShared","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":9689,"src":"1454:23:34","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_RuleEngineOwnableShared_$9689_$","typeString":"type(contract RuleEngineOwnableShared)"}},"id":10133,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberLocation":"1478:29:34","memberName":"_checkOwnershipTransferTarget","nodeType":"MemberAccess","referencedDeclaration":9688,"src":"1454:53:34","typeDescriptions":{"typeIdentifier":"t_function_internal_view$_t_address_$returns$__$","typeString":"function (address) view"}},"id":10135,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"nameLocations":[],"names":[],"nodeType":"FunctionCall","src":"1454:63:34","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":10136,"nodeType":"ExpressionStatement","src":"1454:63:34"},{"expression":{"arguments":[{"id":10140,"name":"newOwner","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":10125,"src":"1558:8:34","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":10137,"name":"Ownable2Step","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":1230,"src":"1527:12:34","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_Ownable2Step_$1230_$","typeString":"type(contract Ownable2Step)"}},"id":10139,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberLocation":"1540:17:34","memberName":"transferOwnership","nodeType":"MemberAccess","referencedDeclaration":1188,"src":"1527:30:34","typeDescriptions":{"typeIdentifier":"t_function_internal_nonpayable$_t_address_$returns$__$","typeString":"function (address)"}},"id":10141,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"nameLocations":[],"names":[],"nodeType":"FunctionCall","src":"1527:40:34","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":10142,"nodeType":"ExpressionStatement","src":"1527:40:34"}]},"baseFunctions":[1188],"documentation":{"id":10123,"nodeType":"StructuredDocumentation","src":"1171:189:34","text":" @notice Starts ownership transfer to `newOwner`.\n @dev Reverts when `newOwner` is already configured as a rule.\n @param newOwner The address of the new owner."},"functionSelector":"f2fde38b","implemented":true,"kind":"function","modifiers":[{"id":10129,"kind":"modifierInvocation","modifierName":{"id":10128,"name":"onlyOwner","nameLocations":["1434:9:34"],"nodeType":"IdentifierPath","referencedDeclaration":1055,"src":"1434:9:34"},"nodeType":"ModifierInvocation","src":"1434:9:34"}],"name":"transferOwnership","nameLocation":"1374:17:34","overrides":{"id":10127,"nodeType":"OverrideSpecifier","overrides":[],"src":"1425:8:34"},"parameters":{"id":10126,"nodeType":"ParameterList","parameters":[{"constant":false,"id":10125,"mutability":"mutable","name":"newOwner","nameLocation":"1400:8:34","nodeType":"VariableDeclaration","scope":10144,"src":"1392:16:34","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":10124,"name":"address","nodeType":"ElementaryTypeName","src":"1392:7:34","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"src":"1391:18:34"},"returnParameters":{"id":10130,"nodeType":"ParameterList","parameters":[],"src":"1444:0:34"},"scope":10208,"stateMutability":"nonpayable","virtual":true,"visibility":"public"},{"id":10162,"nodeType":"FunctionDefinition","src":"1876:175:34","nodes":[],"body":{"id":10161,"nodeType":"Block","src":"1927:124:34","nodes":[],"statements":[{"expression":{"arguments":[{"arguments":[],"expression":{"argumentTypes":[],"id":10152,"name":"_msgSender","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":3230,"src":"1991:10:34","typeDescriptions":{"typeIdentifier":"t_function_internal_view$__$returns$_t_address_$","typeString":"function () view returns (address)"}},"id":10153,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"nameLocations":[],"names":[],"nodeType":"FunctionCall","src":"1991:12:34","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_address","typeString":"address"}],"expression":{"id":10149,"name":"RuleEngineOwnableShared","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":9689,"src":"1937:23:34","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_RuleEngineOwnableShared_$9689_$","typeString":"type(contract RuleEngineOwnableShared)"}},"id":10151,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberLocation":"1961:29:34","memberName":"_checkOwnershipTransferTarget","nodeType":"MemberAccess","referencedDeclaration":9688,"src":"1937:53:34","typeDescriptions":{"typeIdentifier":"t_function_internal_view$_t_address_$returns$__$","typeString":"function (address) view"}},"id":10154,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"nameLocations":[],"names":[],"nodeType":"FunctionCall","src":"1937:67:34","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":10155,"nodeType":"ExpressionStatement","src":"1937:67:34"},{"expression":{"arguments":[],"expression":{"argumentTypes":[],"expression":{"id":10156,"name":"Ownable2Step","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":1230,"src":"2014:12:34","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_Ownable2Step_$1230_$","typeString":"type(contract Ownable2Step)"}},"id":10158,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberLocation":"2027:15:34","memberName":"acceptOwnership","nodeType":"MemberAccess","referencedDeclaration":1229,"src":"2014:28:34","typeDescriptions":{"typeIdentifier":"t_function_internal_nonpayable$__$returns$__$","typeString":"function ()"}},"id":10159,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"nameLocations":[],"names":[],"nodeType":"FunctionCall","src":"2014:30:34","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_tuple$__$","typeString":"tuple()"}},"id":10160,"nodeType":"ExpressionStatement","src":"2014:30:34"}]},"baseFunctions":[1229],"documentation":{"id":10145,"nodeType":"StructuredDocumentation","src":"1580:291:34","text":" @notice Completes the ownership transfer; callable by the pending owner only.\n @dev Repeats the rule-account check of {transferOwnership}: an address nominated while it was not a rule,\n then added as a rule, cannot accept until it is removed from the rule set."},"functionSelector":"79ba5097","implemented":true,"kind":"function","modifiers":[],"name":"acceptOwnership","nameLocation":"1885:15:34","overrides":{"id":10147,"nodeType":"OverrideSpecifier","overrides":[],"src":"1918:8:34"},"parameters":{"id":10146,"nodeType":"ParameterList","parameters":[],"src":"1900:2:34"},"returnParameters":{"id":10148,"nodeType":"ParameterList","parameters":[],"src":"1927:0:34"},"scope":10208,"stateMutability":"nonpayable","virtual":true,"visibility":"public"},{"id":10183,"nodeType":"FunctionDefinition","src":"2290:319:34","nodes":[],"body":{"id":10182,"nodeType":"Block","src":"2450:159:34","nodes":[],"statements":[{"expression":{"commonType":{"typeIdentifier":"t_bool","typeString":"bool"},"id":10180,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"leftExpression":{"commonType":{"typeIdentifier":"t_bytes4","typeString":"bytes4"},"id":10175,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"leftExpression":{"id":10172,"name":"interfaceId","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":10165,"src":"2467:11:34","typeDescriptions":{"typeIdentifier":"t_bytes4","typeString":"bytes4"}},"nodeType":"BinaryOperation","operator":"==","rightExpression":{"expression":{"id":10173,"name":"Ownable2StepInterfaceId","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":14461,"src":"2482:23:34","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_Ownable2StepInterfaceId_$14461_$","typeString":"type(library Ownable2StepInterfaceId)"}},"id":10174,"isConstant":false,"isLValue":false,"isPure":true,"lValueRequested":false,"memberLocation":"2506:26:34","memberName":"IOWNABLE2STEP_INTERFACE_ID","nodeType":"MemberAccess","referencedDeclaration":14460,"src":"2482:50:34","typeDescriptions":{"typeIdentifier":"t_bytes4","typeString":"bytes4"}},"src":"2467:65:34","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"nodeType":"BinaryOperation","operator":"||","rightExpression":{"arguments":[{"id":10178,"name":"interfaceId","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":10165,"src":"2590:11:34","typeDescriptions":{"typeIdentifier":"t_bytes4","typeString":"bytes4"}}],"expression":{"argumentTypes":[{"typeIdentifier":"t_bytes4","typeString":"bytes4"}],"expression":{"id":10176,"name":"RuleEngineOwnableShared","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":9689,"src":"2548:23:34","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_RuleEngineOwnableShared_$9689_$","typeString":"type(contract RuleEngineOwnableShared)"}},"id":10177,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberLocation":"2572:17:34","memberName":"supportsInterface","nodeType":"MemberAccess","referencedDeclaration":9670,"src":"2548:41:34","typeDescriptions":{"typeIdentifier":"t_function_internal_view$_t_bytes4_$returns$_t_bool_$","typeString":"function (bytes4) view returns (bool)"}},"id":10179,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"nameLocations":[],"names":[],"nodeType":"FunctionCall","src":"2548:54:34","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"src":"2467:135:34","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"functionReturnParameters":10171,"id":10181,"nodeType":"Return","src":"2460:142:34"}]},"baseFunctions":[9670],"documentation":{"id":10163,"nodeType":"StructuredDocumentation","src":"2101:184:34","text":" @notice ERC-165 interface detection.\n @param interfaceId The interface identifier to check.\n @return True if the interface is supported, false otherwise."},"functionSelector":"01ffc9a7","implemented":true,"kind":"function","modifiers":[],"name":"supportsInterface","nameLocation":"2299:17:34","overrides":{"id":10168,"nodeType":"OverrideSpecifier","overrides":[{"id":10167,"name":"RuleEngineOwnableShared","nameLocations":["2398:23:34"],"nodeType":"IdentifierPath","referencedDeclaration":9689,"src":"2398:23:34"}],"src":"2389:33:34"},"parameters":{"id":10166,"nodeType":"ParameterList","parameters":[{"constant":false,"id":10165,"mutability":"mutable","name":"interfaceId","nameLocation":"2324:11:34","nodeType":"VariableDeclaration","scope":10183,"src":"2317:18:34","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_bytes4","typeString":"bytes4"},"typeName":{"id":10164,"name":"bytes4","nodeType":"ElementaryTypeName","src":"2317:6:34","typeDescriptions":{"typeIdentifier":"t_bytes4","typeString":"bytes4"}},"visibility":"internal"}],"src":"2316:20:34"},"returnParameters":{"id":10171,"nodeType":"ParameterList","parameters":[{"constant":false,"id":10170,"mutability":"mutable","name":"","nameLocation":"-1:-1:-1","nodeType":"VariableDeclaration","scope":10183,"src":"2440:4:34","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"},"typeName":{"id":10169,"name":"bool","nodeType":"ElementaryTypeName","src":"2440:4:34","typeDescriptions":{"typeIdentifier":"t_bool","typeString":"bool"}},"visibility":"internal"}],"src":"2439:6:34"},"scope":10208,"stateMutability":"view","virtual":true,"visibility":"public"},{"id":10191,"nodeType":"FunctionDefinition","src":"2737:67:34","nodes":[],"body":{"id":10190,"nodeType":"Block","src":"2802:2:34","nodes":[],"statements":[]},"baseFunctions":[13890],"documentation":{"id":10184,"nodeType":"StructuredDocumentation","src":"2666:66:34","text":" @dev Access control check using Ownable pattern"},"implemented":true,"kind":"function","modifiers":[{"id":10188,"kind":"modifierInvocation","modifierName":{"id":10187,"name":"onlyOwner","nameLocations":["2792:9:34"],"nodeType":"IdentifierPath","referencedDeclaration":1055,"src":"2792:9:34"},"nodeType":"ModifierInvocation","src":"2792:9:34"}],"name":"_onlyRulesManager","nameLocation":"2746:17:34","overrides":{"id":10186,"nodeType":"OverrideSpecifier","overrides":[],"src":"2783:8:34"},"parameters":{"id":10185,"nodeType":"ParameterList","parameters":[],"src":"2763:2:34"},"returnParameters":{"id":10189,"nodeType":"ParameterList","parameters":[],"src":"2802:0:34"},"scope":10208,"stateMutability":"nonpayable","virtual":true,"visibility":"internal"},{"id":10199,"nodeType":"FunctionDefinition","src":"2881:72:34","nodes":[],"body":{"id":10198,"nodeType":"Block","src":"2951:2:34","nodes":[],"statements":[]},"baseFunctions":[13894],"documentation":{"id":10192,"nodeType":"StructuredDocumentation","src":"2810:66:34","text":" @dev Access control check using Ownable pattern"},"implemented":true,"kind":"function","modifiers":[{"id":10196,"kind":"modifierInvocation","modifierName":{"id":10195,"name":"onlyOwner","nameLocations":["2941:9:34"],"nodeType":"IdentifierPath","referencedDeclaration":1055,"src":"2941:9:34"},"nodeType":"ModifierInvocation","src":"2941:9:34"}],"name":"_onlyRulesLimitManager","nameLocation":"2890:22:34","overrides":{"id":10194,"nodeType":"OverrideSpecifier","overrides":[],"src":"2932:8:34"},"parameters":{"id":10193,"nodeType":"ParameterList","parameters":[],"src":"2912:2:34"},"returnParameters":{"id":10197,"nodeType":"ParameterList","parameters":[],"src":"2951:0:34"},"scope":10208,"stateMutability":"nonpayable","virtual":true,"visibility":"internal"},{"id":10207,"nodeType":"FunctionDefinition","src":"3030:72:34","nodes":[],"body":{"id":10206,"nodeType":"Block","src":"3100:2:34","nodes":[],"statements":[]},"baseFunctions":[13446],"documentation":{"id":10200,"nodeType":"StructuredDocumentation","src":"2959:66:34","text":" @dev Access control check using Ownable pattern"},"implemented":true,"kind":"function","modifiers":[{"id":10204,"kind":"modifierInvocation","modifierName":{"id":10203,"name":"onlyOwner","nameLocations":["3090:9:34"],"nodeType":"IdentifierPath","referencedDeclaration":1055,"src":"3090:9:34"},"nodeType":"ModifierInvocation","src":"3090:9:34"}],"name":"_onlyComplianceManager","nameLocation":"3039:22:34","overrides":{"id":10202,"nodeType":"OverrideSpecifier","overrides":[],"src":"3081:8:34"},"parameters":{"id":10201,"nodeType":"ParameterList","parameters":[],"src":"3061:2:34"},"returnParameters":{"id":10205,"nodeType":"ParameterList","parameters":[],"src":"3100:0:34"},"scope":10208,"stateMutability":"nonpayable","virtual":true,"visibility":"internal"}],"abstract":false,"baseContracts":[{"baseName":{"id":10104,"name":"RuleEngineOwnableShared","nameLocations":["712:23:34"],"nodeType":"IdentifierPath","referencedDeclaration":9689,"src":"712:23:34"},"id":10105,"nodeType":"InheritanceSpecifier","src":"712:23:34"},{"baseName":{"id":10106,"name":"Ownable2Step","nameLocations":["737:12:34"],"nodeType":"IdentifierPath","referencedDeclaration":1230,"src":"737:12:34"},"id":10107,"nodeType":"InheritanceSpecifier","src":"737:12:34"}],"canonicalName":"RuleEngineOwnable2Step","contractDependencies":[],"contractKind":"contract","documentation":{"id":10103,"nodeType":"StructuredDocumentation","src":"404:272:34","text":" @title Implementation of a ruleEngine with ERC-173 Ownable2Step access control\n @dev No ERC-2771 support: every caller is the raw `msg.sender`. Deploy {RuleEngineOwnable2Step2771} to\n administer the engine through a trusted forwarder (gasless transactions)."},"fullyImplemented":true,"linearizedBaseContracts":[10208,1230,1144,9689,3578,9604,34,28,3800,14477,13390,10332,13447,14176,10545,10320,14356,14606,10476,262,464,251,311,285,3248,13913,10442,14580,14379,123],"name":"RuleEngineOwnable2Step","nameLocation":"686:22:34","scope":10209,"usedErrors":[1010,1015,14474,14476,14545,14547,14549,14551,14555,14557,14559,14596,14599,14602,14605],"usedEvents":[1021,1159,10450,10455,10490,10498,14565,14571,14574,14579]}],"license":"MPL-2.0"},"id":34} \ No newline at end of file diff --git a/doc/compilation/v3.0.0-rc7/foundry/RuleEngineOwnable2Step2771.sol/RuleEngineOwnable2Step2771.json b/doc/compilation/v3.0.0-rc7/foundry/RuleEngineOwnable2Step2771.sol/RuleEngineOwnable2Step2771.json new file mode 100644 index 00000000..a58697ed --- /dev/null +++ b/doc/compilation/v3.0.0-rc7/foundry/RuleEngineOwnable2Step2771.sol/RuleEngineOwnable2Step2771.json @@ -0,0 +1 @@ +{"abi":[{"type":"constructor","inputs":[{"name":"owner_","type":"address","internalType":"address"},{"name":"forwarderIrrevocable","type":"address","internalType":"address"},{"name":"tokenContract","type":"address","internalType":"address"}],"stateMutability":"nonpayable"},{"type":"function","name":"DEFAULT_MAX_RULES","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"acceptOwnership","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"addRule","inputs":[{"name":"rule_","type":"address","internalType":"contract IRule"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"bindToken","inputs":[{"name":"token","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"bindTokens","inputs":[{"name":"tokens","type":"address[]","internalType":"address[]"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"canTransfer","inputs":[{"name":"from","type":"address","internalType":"address"},{"name":"to","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"canTransferFrom","inputs":[{"name":"spender","type":"address","internalType":"address"},{"name":"from","type":"address","internalType":"address"},{"name":"to","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"clearRules","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"containsRule","inputs":[{"name":"rule_","type":"address","internalType":"contract IRule"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"created","inputs":[{"name":"to","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"destroyed","inputs":[{"name":"from","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"detectTransferRestriction","inputs":[{"name":"from","type":"address","internalType":"address"},{"name":"to","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint8","internalType":"uint8"}],"stateMutability":"view"},{"type":"function","name":"detectTransferRestrictionFrom","inputs":[{"name":"spender","type":"address","internalType":"address"},{"name":"from","type":"address","internalType":"address"},{"name":"to","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"uint8","internalType":"uint8"}],"stateMutability":"view"},{"type":"function","name":"getTokenBound","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"getTokenBounds","inputs":[],"outputs":[{"name":"","type":"address[]","internalType":"address[]"}],"stateMutability":"view"},{"type":"function","name":"isTokenBound","inputs":[{"name":"token","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"isTokenSelfBindingApproved","inputs":[{"name":"token","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"isTrustedForwarder","inputs":[{"name":"forwarder","type":"address","internalType":"address"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"maxRules","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"messageForTransferRestriction","inputs":[{"name":"restrictionCode","type":"uint8","internalType":"uint8"}],"outputs":[{"name":"","type":"string","internalType":"string"}],"stateMutability":"view"},{"type":"function","name":"owner","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"pendingOwner","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"removeRule","inputs":[{"name":"rule_","type":"address","internalType":"contract IRule"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"renounceOwnership","inputs":[],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"rule","inputs":[{"name":"ruleId","type":"uint256","internalType":"uint256"}],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"rules","inputs":[],"outputs":[{"name":"","type":"address[]","internalType":"address[]"}],"stateMutability":"view"},{"type":"function","name":"rulesCount","inputs":[],"outputs":[{"name":"","type":"uint256","internalType":"uint256"}],"stateMutability":"view"},{"type":"function","name":"setMaxRules","inputs":[{"name":"maxRules_","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setRules","inputs":[{"name":"rules_","type":"address[]","internalType":"contract IRule[]"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setTokenSelfBindingApproval","inputs":[{"name":"token","type":"address","internalType":"address"},{"name":"approved","type":"bool","internalType":"bool"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"setTokenSelfBindingApprovalBatch","inputs":[{"name":"tokens","type":"address[]","internalType":"address[]"},{"name":"approved","type":"bool","internalType":"bool"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"supportsInterface","inputs":[{"name":"interfaceId","type":"bytes4","internalType":"bytes4"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"view"},{"type":"function","name":"transferOwnership","inputs":[{"name":"newOwner","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"transferred","inputs":[{"name":"spender","type":"address","internalType":"address"},{"name":"from","type":"address","internalType":"address"},{"name":"to","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"transferred","inputs":[{"name":"from","type":"address","internalType":"address"},{"name":"to","type":"address","internalType":"address"},{"name":"value","type":"uint256","internalType":"uint256"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"trustedForwarder","inputs":[],"outputs":[{"name":"","type":"address","internalType":"address"}],"stateMutability":"view"},{"type":"function","name":"unbindToken","inputs":[{"name":"token","type":"address","internalType":"address"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"unbindTokens","inputs":[{"name":"tokens","type":"address[]","internalType":"address[]"}],"outputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"version","inputs":[],"outputs":[{"name":"version_","type":"string","internalType":"string"}],"stateMutability":"view"},{"type":"event","name":"AddRule","inputs":[{"name":"rule","type":"address","indexed":true,"internalType":"contract IRule"}],"anonymous":false},{"type":"event","name":"ClearRules","inputs":[],"anonymous":false},{"type":"event","name":"OwnershipTransferStarted","inputs":[{"name":"previousOwner","type":"address","indexed":true,"internalType":"address"},{"name":"newOwner","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"OwnershipTransferred","inputs":[{"name":"previousOwner","type":"address","indexed":true,"internalType":"address"},{"name":"newOwner","type":"address","indexed":true,"internalType":"address"}],"anonymous":false},{"type":"event","name":"RemoveRule","inputs":[{"name":"rule","type":"address","indexed":true,"internalType":"contract IRule"}],"anonymous":false},{"type":"event","name":"SetMaxRules","inputs":[{"name":"maxRules","type":"uint256","indexed":false,"internalType":"uint256"}],"anonymous":false},{"type":"event","name":"TokenBound","inputs":[{"name":"token","type":"address","indexed":false,"internalType":"address"}],"anonymous":false},{"type":"event","name":"TokenSelfBindingApprovalBatchSet","inputs":[{"name":"tokens","type":"address[]","indexed":false,"internalType":"address[]"},{"name":"approved","type":"bool","indexed":false,"internalType":"bool"}],"anonymous":false},{"type":"event","name":"TokenSelfBindingApprovalSet","inputs":[{"name":"token","type":"address","indexed":true,"internalType":"address"},{"name":"approved","type":"bool","indexed":false,"internalType":"bool"}],"anonymous":false},{"type":"event","name":"TokenUnbound","inputs":[{"name":"token","type":"address","indexed":false,"internalType":"address"}],"anonymous":false},{"type":"error","name":"OwnableInvalidOwner","inputs":[{"name":"owner","type":"address","internalType":"address"}]},{"type":"error","name":"OwnableUnauthorizedAccount","inputs":[{"name":"account","type":"address","internalType":"address"}]},{"type":"error","name":"RuleEngine_AdminWithAddressZeroNotAllowed","inputs":[]},{"type":"error","name":"RuleEngine_RuleInvalidInterface","inputs":[]},{"type":"error","name":"RuleEngine_RulesManagementModule_ArrayIsEmpty","inputs":[]},{"type":"error","name":"RuleEngine_RulesManagementModule_MaxRulesExceeded","inputs":[{"name":"maxRules","type":"uint256","internalType":"uint256"}]},{"type":"error","name":"RuleEngine_RulesManagementModule_MaxRulesZeroNotAllowed","inputs":[]},{"type":"error","name":"RuleEngine_RulesManagementModule_RuleAccountCannotReceivePrivileges","inputs":[]},{"type":"error","name":"RuleEngine_RulesManagementModule_RuleAddressZeroNotAllowed","inputs":[]},{"type":"error","name":"RuleEngine_RulesManagementModule_RuleAlreadyExists","inputs":[]},{"type":"error","name":"RuleEngine_RulesManagementModule_RuleDoNotMatch","inputs":[]},{"type":"error","name":"TokenBinding_InvalidTokenAddress","inputs":[]},{"type":"error","name":"TokenBinding_TokenAlreadyBound","inputs":[]},{"type":"error","name":"TokenBinding_TokenNotBound","inputs":[]},{"type":"error","name":"TokenBinding_UnauthorizedCaller","inputs":[]}],"bytecode":{"object":"0x60a0604052600a600255348015610014575f5ffd5b5060405161211b38038061211b833981016040819052610033916102cc565b6001600160a01b03808316608052839082908290829081161561005957610059816100a5565b610063600a61013d565b506001600160a01b03811661009157604051631e4fbdf760e01b81525f600482015260240160405180910390fd5b61009a81610192565b50505050505061030c565b6001600160a01b0381166100cc5760405163135217db60e21b815260040160405180910390fd5b6100d5816101ae565b6100e06003826101d6565b6100fd576040516371b3c56560e11b815260040160405180910390fd5b6040516001600160a01b03821681527f2de35142b19ed5a07796cf30791959c592018f70b1d2d7c460eef8ffe713692b906020015b60405180910390a150565b805f0361015d57604051631e69e71760e21b815260040160405180910390fd5b60028190556040518181527f2292ad4720fff63e2bd104c6b1c0d72c2c729a6001c8ab4bb947cbcc5110986390602001610132565b600780546001600160a01b03191690556101ab816101f3565b50565b6101b85f82610244565b156101ab576040516302925f7360e11b815260040160405180910390fd5b5f6101ea836001600160a01b038416610265565b90505b92915050565b600680546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b6001600160a01b0381165f90815260018301602052604081205415156101ea565b5f8181526001830160205260408120546102aa57508154600181810184555f8481526020808220909301849055845484825282860190935260409020919091556101ed565b505f6101ed565b80516001600160a01b03811681146102c7575f5ffd5b919050565b5f5f5f606084860312156102de575f5ffd5b6102e7846102b1565b92506102f5602085016102b1565b9150610303604085016102b1565b90509250925092565b608051611de96103325f395f818161033a015281816103d401526115100152611de95ff3fe608060405234801561000f575f5ffd5b5060043610610234575f3560e01c80638baf29b411610135578063d4ce1415116100b4578063e3c4602c11610079578063e3c4602c14610538578063e46638e61461054b578063e54621d21461055e578063f2fde38b14610566578063f76bf55014610579575f5ffd5b8063d4ce1415146104c3578063db18af6c146104d6578063db75d017146104e9578063df21950f14610514578063e30c397814610527575f5ffd5b8063b27aef3a116100fa578063b27aef3a1461045d578063bb4b612114610470578063bc13eacc14610483578063c7c24b181461048b578063d32c7bb51461049e575f5ffd5b80638baf29b41461040b5780638d2ea7721461041e5780638da5cb5b14610431578063993e8b9514610442578063b043572e14610455575f5ffd5b806354fd4d50116101c1578063715018a611610186578063715018a6146103af5780637157797f146103b757806379ba5097146103ca5780637da0a877146103d25780637f4ab1dd146103f8575f5ffd5b806354fd4d50146102fc578063572b6c051461032a5780635f8dead31461036a5780636a3edf281461037d5780636ae728c61461039d575f5ffd5b80633e5af4ca116102075780633e5af4ca1461029b5780633ff5aa02146102ae57806340db3b50146102c157806352f6747a146102d457806354e4b945146102e9575f5ffd5b806301ffc9a7146102385780631455d0e7146102605780633284a9a5146102755780633a56d6d514610288575b5f5ffd5b61024b6102463660046118c6565b610581565b60405190151581526020015b60405180910390f35b61027361026e366004611935565b6105ab565b005b610273610283366004611995565b6105f9565b6102736102963660046119cc565b610636565b6102736102a93660046119e3565b61064a565b6102736102bc366004611a31565b610664565b6102736102cf366004611a31565b610676565b6102dc610688565b6040516102579190611a4c565b61024b6102f7366004611a31565b610698565b604080518082019091526009815268332e302e302d72633760b81b60208201525b6040516102579190611a97565b61024b610338366004611a31565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0390811691161490565b610273610378366004611acc565b6106a3565b6103856106b6565b6040516001600160a01b039091168152602001610257565b6002545b604051908152602001610257565b6102736106d8565b61024b6103c53660046119e3565b6106eb565b610273610708565b7f0000000000000000000000000000000000000000000000000000000000000000610385565b61031d610406366004611b04565b610720565b610273610419366004611b1f565b61072b565b61027361042c366004611acc565b61073e565b6006546001600160a01b0316610385565b61024b610450366004611a31565b610751565b61027361075d565b61027361046b366004611935565b61076d565b61027361047e366004611b5d565b610820565b6103a16108ee565b610273610499366004611935565b6108f8565b6104b16104ac3660046119e3565b610941565b60405160ff9091168152602001610257565b6104b16104d1366004611b1f565b610957565b6103856104e43660046119cc565b61096d565b61024b6104f7366004611a31565b6001600160a01b03165f9081526005602052604090205460ff1690565b610273610522366004611a31565b61098f565b6007546001600160a01b0316610385565b610273610546366004611a31565b6109a0565b61024b610559366004611b1f565b6109e2565b6102dc6109fb565b610273610574366004611a31565b610a07565b6103a1600a81565b5f6001600160e01b03198216639ab669ef60e01b14806105a557506105a582610a21565b92915050565b6105b3610a65565b5f5b818110156105f4576105ec8383838181106105d2576105d2611bb0565b90506020020160208101906105e79190611a31565b610a6d565b6001016105b5565b505050565b610601610a65565b6001600160a01b0382166106285760405163135217db60e21b815260040160405180910390fd5b6106328282610a76565b5050565b61063e610ad4565b61064781610adc565b50565b610652610b38565b61065e84848484610b60565b50505050565b61066d81610c02565b61064781610c0b565b61067f81610c02565b61064781610a6d565b60606106935f610c9c565b905090565b5f6105a58183610ca8565b6106ab610b38565b6106325f8383610cc8565b5f5f6106c26003610d61565b11156106d35761069360035f610d6a565b505f90565b6106e0610d75565b6106e95f610dd3565b565b5f806106f986868686610941565b60ff161490505b949350505050565b610718610713610dec565b610df5565b6106e9610e1c565b60606105a582610e7e565b610733610b38565b6105f4838383610cc8565b610746610b38565b610632825f83610cc8565b5f6105a5600383610ca8565b610765610ad4565b6106e9610ff3565b610775610ad4565b5f819003610796576040516359203cb960e01b815260040160405180910390fd5b600254808211156107c657604051630befc49d60e01b81526004016107bd91815260200190565b60405180910390fd5b505f6107d15f610d61565b11156107df576107df610ff3565b5f5b818110156105f4576108188383838181106107fe576107fe611bb0565b90506020020160208101906108139190611a31565b611024565b6001016107e1565b610828610a65565b5f5b828110156108ad575f84848381811061084557610845611bb0565b905060200201602081019061085a9190611a31565b90506001600160a01b0381166108835760405163135217db60e21b815260040160405180910390fd5b6001600160a01b03165f908152600560205260409020805460ff191683151517905560010161082a565b507f430881f04f203566ee9b32d6444cf02e1b2a0f17ab6b4263a1ee2074d3d0f4838383836040516108e193929190611bc4565b60405180910390a1505050565b5f6106935f610d61565b610900610a65565b5f5b818110156105f45761093983838381811061091f5761091f611bb0565b90506020020160208101906109349190611a31565b610c0b565b600101610902565b5f61094e8585858561108a565b95945050505050565b5f610963848484611157565b90505b9392505050565b5f6109775f610d61565b821015610988576105a55f83610d6a565b505f919050565b610997610ad4565b6106478161121b565b6109a8610ad4565b600254806109b55f610d61565b1081906109d857604051630befc49d60e01b81526004016107bd91815260200190565b5061063282611024565b5f806109ef858585610957565b60ff1614949350505050565b60606106936003610c9c565b610a0f610d75565b610a1881610df5565b61064781611278565b5f610a2b826112e9565b80610a4657506001600160e01b031982166307f5828d60e41b145b806105a557506301ffc9a760e01b6001600160e01b03198316146105a5565b6106e9610ad4565b6106478161138a565b6001600160a01b0382165f81815260056020908152604091829020805460ff191685151590811790915591519182527f407b412a9b6db334d48445ec9bcad46fb50bc4b2e97f73e963e397101957a729910160405180910390a25050565b6106e9610d75565b805f03610afc57604051631e69e71760e21b815260040160405180910390fd5b60028190556040518181527f2292ad4720fff63e2bd104c6b1c0d72c2c729a6001c8ab4bb947cbcc51109863906020015b60405180910390a150565b610b43600333610ca8565b6106e957604051630599c0e960e01b815260040160405180910390fd5b5f610b6a5f610d61565b90505f5b81811015610bfa57610b805f82610d6a565b604051631f2d7a6560e11b81526001600160a01b03888116600483015287811660248301528681166044830152606482018690529190911690633e5af4ca906084015f604051808303815f87803b158015610bd9575f5ffd5b505af1158015610beb573d5f5f3e3d5ffd5b50505050806001019050610b6e565b505050505050565b610647816113d2565b6001600160a01b038116610c325760405163135217db60e21b815260040160405180910390fd5b610c3b81611411565b610c4660038261141b565b610c63576040516371b3c56560e11b815260040160405180910390fd5b6040516001600160a01b03821681527f2de35142b19ed5a07796cf30791959c592018f70b1d2d7c460eef8ffe713692b90602001610b2d565b60605f6109668361142f565b6001600160a01b03165f9081526001919091016020526040902054151590565b5f610cd25f610d61565b90505f5b81811015610d5a57610ce85f82610d6a565b6040516322ebca6d60e21b81526001600160a01b0387811660048301528681166024830152604482018690529190911690638baf29b4906064015f604051808303815f87803b158015610d39575f5ffd5b505af1158015610d4b573d5f5f3e3d5ffd5b50505050806001019050610cd6565b5050505050565b5f6105a5825490565b5f6109668383611488565b610d7d610dec565b6001600160a01b0316610d986006546001600160a01b031690565b6001600160a01b0316146106e957610dae610dec565b60405163118cdaa760e01b81526001600160a01b0390911660048201526024016107bd565b600780546001600160a01b0319169055610647816114ae565b5f6106936114ff565b610dfe81610698565b15610647576040516302925f7360e11b815260040160405180910390fd5b5f610e25610dec565b9050806001600160a01b0316610e436007546001600160a01b031690565b6001600160a01b031614610e755760405163118cdaa760e01b81526001600160a01b03821660048201526024016107bd565b61064781610dd3565b606060ff8216610eb157505060408051808201909152600d81526c2737a932b9ba3934b1ba34b7b760991b602082015290565b5f610ebb5f610d61565b90505f5b81811015610fb7575f610ed28183610d6a565b604051633e822efb60e11b815260ff871660048201529091506001600160a01b03821690637d045df690602401602060405180830381865afa158015610f1a573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f3e9190611c1c565b15610fae57604051637f4ab1dd60e01b815260ff861660048201526001600160a01b03821690637f4ab1dd906024015f60405180830381865afa158015610f87573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261094e9190810190611c4b565b50600101610ebf565b505060408051808201909152601881527f556e6b6e6f776e207265737472696374696f6e20636f64650000000000000000602082015292915050565b6040517fdbf61473843cd9be1c9791ce51ef66d0da6c9026d62ba80c1ca433b13fb729b2905f90a16106e95f611569565b61102d81611572565b6110375f8261141b565b6110545760405163cc790a4b60e01b815260040160405180910390fd5b6040516001600160a01b038216907f60305ce6c9104acd0969d358f926bf391174340660aaf5e6215261fd6847bf46905f90a250565b5f5f6110955f610d61565b90505f5b8181101561114b575f6110ac8183610d6a565b60405163d32c7bb560e01b81526001600160a01b038a811660048301528981166024830152888116604483015260648201889052919091169063d32c7bb590608401602060405180830381865afa158015611109573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061112d9190611cfe565b905060ff811615611142579250610700915050565b50600101611099565b505f9695505050505050565b5f5f6111625f610d61565b90505f5b81811015611210575f6111798183610d6a565b60405163d4ce141560e01b81526001600160a01b038981166004830152888116602483015260448201889052919091169063d4ce141590606401602060405180830381865afa1580156111ce573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111f29190611cfe565b905060ff811615611207579250610966915050565b50600101611166565b505f95945050505050565b6112255f826115ca565b61124257604051632cdc3a4160e21b815260040160405180910390fd5b6040516001600160a01b038216907f6d83315c9718799346b67584ec64301b1457e989c8e35a8e2982a7776c04bfc4905f90a250565b611280610d75565b600780546001600160a01b0383166001600160a01b031990911681179091556112b16006546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b5f6001600160e01b031982166320c49ce760e01b148061131957506001600160e01b0319821663157094b960e31b145b8061133457506001600160e01b031982166378a8de7d60e01b145b8061134f57506001600160e01b03198216630c51264760e21b145b8061136a57506001600160e01b03198216633235d15f60e11b145b806105a557506001600160e01b03198216637157797f60e01b1492915050565b611393816115de565b336001600160a01b038216148015906113c357506001600160a01b0381165f9081526005602052604090205460ff165b1561064757610647815f610a76565b336001600160a01b03821614801561140157506001600160a01b0381165f9081526005602052604090205460ff165b156114095750565b610647610a65565b610dfe5f82610ca8565b5f610966836001600160a01b03841661163f565b6060815f0180548060200260200160405190810160405280929190818152602001828054801561147c57602002820191905f5260205f20905b815481526020019060010190808311611468575b50505050509050919050565b5f825f01828154811061149d5761149d611bb0565b905f5260205f200154905092915050565b600680546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b5f36601480821080159061153b57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031633145b156115615761154e36828403815f611d19565b61155791611d40565b60601c9250505090565b339250505090565b6106478161168b565b61157b816116e4565b611586600382610ca8565b156115a4576040516302925f7360e11b815260040160405180910390fd5b6115ad8161170b565b61064757604051639952e34360e01b815260040160405180910390fd5b5f610966836001600160a01b038416611748565b6115e96003826115ca565b61160657604051633477dd1760e01b815260040160405180910390fd5b6040516001600160a01b03821681527f28a4ca7134a3b3f9aff286e79ad3daadb4a06d1b43d037a3a98bdc074edd9b7a90602001610b2d565b5f81815260018301602052604081205461168457508154600181810184555f8481526020808220909301849055845484825282860190935260409020919091556105a5565b505f6105a5565b5f611694825490565b90505f5b818110156116dd57826001015f845f0183815481106116b9576116b9611bb0565b905f5260205f20015481526020019081526020015f205f9055806001019050611698565b50505f9055565b6001600160a01b0381166106475760405163f9d152fb60e01b815260040160405180910390fd5b5f61171582611832565b61172057505f919050565b611731826358d34ba960e11b611871565b806105a557506105a582632497d6cb60e01b611871565b5f8181526001830160205260408120548015611822575f61176a600183611d80565b85549091505f9061177d90600190611d80565b90508082146117dc575f865f01828154811061179b5761179b611bb0565b905f5260205f200154905080875f0184815481106117bb576117bb611bb0565b5f918252602080832090910192909255918252600188019052604090208390555b85548690806117ed576117ed611d9f565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f9055600193505050506105a5565b5f9150506105a5565b5092915050565b5f611844826301ffc9a760e01b611871565b15610988575f8061185d846001600160e01b0319611892565b915091508180156107005750159392505050565b5f5f5f61187e8585611892565b9150915081801561094e5750949350505050565b6301ffc9a760e01b5f818152600483905290819060208260248188617530fa92505f511515601f3d11169150509250929050565b5f602082840312156118d6575f5ffd5b81356001600160e01b031981168114610966575f5ffd5b5f5f83601f8401126118fd575f5ffd5b50813567ffffffffffffffff811115611914575f5ffd5b6020830191508360208260051b850101111561192e575f5ffd5b9250929050565b5f5f60208385031215611946575f5ffd5b823567ffffffffffffffff81111561195c575f5ffd5b611968858286016118ed565b90969095509350505050565b6001600160a01b0381168114610647575f5ffd5b8015158114610647575f5ffd5b5f5f604083850312156119a6575f5ffd5b82356119b181611974565b915060208301356119c181611988565b809150509250929050565b5f602082840312156119dc575f5ffd5b5035919050565b5f5f5f5f608085870312156119f6575f5ffd5b8435611a0181611974565b93506020850135611a1181611974565b92506040850135611a2181611974565b9396929550929360600135925050565b5f60208284031215611a41575f5ffd5b813561096681611974565b602080825282518282018190525f918401906040840190835b81811015611a8c5783516001600160a01b0316835260209384019390920191600101611a65565b509095945050505050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b5f5f60408385031215611add575f5ffd5b8235611ae881611974565b946020939093013593505050565b60ff81168114610647575f5ffd5b5f60208284031215611b14575f5ffd5b813561096681611af6565b5f5f5f60608486031215611b31575f5ffd5b8335611b3c81611974565b92506020840135611b4c81611974565b929592945050506040919091013590565b5f5f5f60408486031215611b6f575f5ffd5b833567ffffffffffffffff811115611b85575f5ffd5b611b91868287016118ed565b9094509250506020840135611ba581611988565b809150509250925092565b634e487b7160e01b5f52603260045260245ffd5b604080825281018390525f8460608301825b86811015611c06578235611be981611974565b6001600160a01b0316825260209283019290910190600101611bd6565b5080925050508215156020830152949350505050565b5f60208284031215611c2c575f5ffd5b815161096681611988565b634e487b7160e01b5f52604160045260245ffd5b5f60208284031215611c5b575f5ffd5b815167ffffffffffffffff811115611c71575f5ffd5b8201601f81018413611c81575f5ffd5b805167ffffffffffffffff811115611c9b57611c9b611c37565b604051601f8201601f19908116603f0116810167ffffffffffffffff81118282101715611cca57611cca611c37565b604052818152828201602001861015611ce1575f5ffd5b8160208401602083015e5f91810160200191909152949350505050565b5f60208284031215611d0e575f5ffd5b815161096681611af6565b5f5f85851115611d27575f5ffd5b83861115611d33575f5ffd5b5050820193919092039150565b80356bffffffffffffffffffffffff19811690601484101561182b576bffffffffffffffffffffffff1960149490940360031b84901b1690921692915050565b818103818111156105a557634e487b7160e01b5f52601160045260245ffd5b634e487b7160e01b5f52603160045260245ffdfea26469706673582212208b02f7ee6873c97209fdcf3b38f7f61aa232ea774b41b32d32be43f587b0165e64736f6c63430008250033","sourceMap":"788:1905:35:-:0;;;537:2:80;1188:46:69;;1268:195:35;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;-1:-1:-1;;;;;1542:37:15;;;;;1434:6:35;;1442:13;;1434:6;;1442:13;;1101:27:29;;;1097:83;;1144:25;1155:13;1144:10;:25::i;:::-;1279:31;537:2:80;1279:12:29;:31::i;:::-;-1:-1:-1;;;;;;1273:26:10;;1269:95;;1322:31;;-1:-1:-1;;;1322:31:10;;1350:1;1322:31;;;725:51:83;698:18;;1322:31:10;;;;;;;1269:95;1373:32;1392:12;1373:18;:32::i;:::-;1225:187;1057:108:34;;1268:195:35;;;788:1905;;4440:400:71;-1:-1:-1;;;;;4510:19:71;;4502:64;;;;-1:-1:-1;;;4502:64:71;;;;;;;;;;;;4576:26;4596:5;4576:19;:26::i;:::-;4743:23;:12;4760:5;4743:16;:23::i;:::-;4735:66;;;;-1:-1:-1;;;4735:66:71;;;;;;;;;;;;4816:17;;-1:-1:-1;;;;;743:32:83;;725:51;;4816:17:71;;713:2:83;698:18;4816:17:71;;;;;;;;4440:400;:::o;6050:225:69:-;6126:9;6139:1;6126:14;6118:82;;;;-1:-1:-1;;;6118:82:69;;;;;;;;;;;;6210:9;:21;;;6246:22;;933:25:83;;;6246:22:69;;921:2:83;906:18;6246:22:69;787:177:83;2011:153:11;2100:13;2093:20;;-1:-1:-1;;;;;;2093:20:11;;;2123:34;2148:8;2123:24;:34::i;:::-;2011:153;:::o;9793:195:28:-;9887:22;:6;9903:5;9887:15;:22::i;:::-;9886:23;9878:103;;;;-1:-1:-1;;;9878:103:28;;;;;;;;;;;16462:150:27;16532:4;16555:50;16560:3;-1:-1:-1;;;;;16580:23:27;;16555:4;:50::i;:::-;16548:57;;16462:150;;;;;:::o;2912:187:10:-;3004:6;;;-1:-1:-1;;;;;3020:17:10;;;-1:-1:-1;;;;;;3020:17:10;;;;;;;3052:40;;3004:6;;;3020:17;3004:6;;3052:40;;2985:16;;3052:40;2975:124;2912:187;:::o;17414:165:27:-;-1:-1:-1;;;;;17547:23:27;;17494:4;5238:21;;;:14;;;:21;;;;;;:26;;17517:55;5142:129;2538:406;2601:4;5238:21;;;:14;;;:21;;;;;;2617:321;;-1:-1:-1;2659:23:27;;;;;;;;:11;:23;;;;;;;;;;;;;2841:18;;2817:21;;;:14;;;:21;;;;;;:42;;;;2873:11;;2617:321;-1:-1:-1;2922:5:27;2915:12;;14:177:83;93:13;;-1:-1:-1;;;;;135:31:83;;125:42;;115:70;;181:1;178;171:12;115:70;14:177;;;:::o;196:378::-;284:6;292;300;353:2;341:9;332:7;328:23;324:32;321:52;;;369:1;366;359:12;321:52;392:40;422:9;392:40;:::i;:::-;382:50;;451:49;496:2;485:9;481:18;451:49;:::i;:::-;441:59;;519:49;564:2;553:9;549:18;519:49;:::i;:::-;509:59;;196:378;;;;;:::o;787:177::-;788:1905:35;;;;;;;;;;;;;;;;;;;;;;","linkReferences":{}},"deployedBytecode":{"object":"0x608060405234801561000f575f5ffd5b5060043610610234575f3560e01c80638baf29b411610135578063d4ce1415116100b4578063e3c4602c11610079578063e3c4602c14610538578063e46638e61461054b578063e54621d21461055e578063f2fde38b14610566578063f76bf55014610579575f5ffd5b8063d4ce1415146104c3578063db18af6c146104d6578063db75d017146104e9578063df21950f14610514578063e30c397814610527575f5ffd5b8063b27aef3a116100fa578063b27aef3a1461045d578063bb4b612114610470578063bc13eacc14610483578063c7c24b181461048b578063d32c7bb51461049e575f5ffd5b80638baf29b41461040b5780638d2ea7721461041e5780638da5cb5b14610431578063993e8b9514610442578063b043572e14610455575f5ffd5b806354fd4d50116101c1578063715018a611610186578063715018a6146103af5780637157797f146103b757806379ba5097146103ca5780637da0a877146103d25780637f4ab1dd146103f8575f5ffd5b806354fd4d50146102fc578063572b6c051461032a5780635f8dead31461036a5780636a3edf281461037d5780636ae728c61461039d575f5ffd5b80633e5af4ca116102075780633e5af4ca1461029b5780633ff5aa02146102ae57806340db3b50146102c157806352f6747a146102d457806354e4b945146102e9575f5ffd5b806301ffc9a7146102385780631455d0e7146102605780633284a9a5146102755780633a56d6d514610288575b5f5ffd5b61024b6102463660046118c6565b610581565b60405190151581526020015b60405180910390f35b61027361026e366004611935565b6105ab565b005b610273610283366004611995565b6105f9565b6102736102963660046119cc565b610636565b6102736102a93660046119e3565b61064a565b6102736102bc366004611a31565b610664565b6102736102cf366004611a31565b610676565b6102dc610688565b6040516102579190611a4c565b61024b6102f7366004611a31565b610698565b604080518082019091526009815268332e302e302d72633760b81b60208201525b6040516102579190611a97565b61024b610338366004611a31565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0390811691161490565b610273610378366004611acc565b6106a3565b6103856106b6565b6040516001600160a01b039091168152602001610257565b6002545b604051908152602001610257565b6102736106d8565b61024b6103c53660046119e3565b6106eb565b610273610708565b7f0000000000000000000000000000000000000000000000000000000000000000610385565b61031d610406366004611b04565b610720565b610273610419366004611b1f565b61072b565b61027361042c366004611acc565b61073e565b6006546001600160a01b0316610385565b61024b610450366004611a31565b610751565b61027361075d565b61027361046b366004611935565b61076d565b61027361047e366004611b5d565b610820565b6103a16108ee565b610273610499366004611935565b6108f8565b6104b16104ac3660046119e3565b610941565b60405160ff9091168152602001610257565b6104b16104d1366004611b1f565b610957565b6103856104e43660046119cc565b61096d565b61024b6104f7366004611a31565b6001600160a01b03165f9081526005602052604090205460ff1690565b610273610522366004611a31565b61098f565b6007546001600160a01b0316610385565b610273610546366004611a31565b6109a0565b61024b610559366004611b1f565b6109e2565b6102dc6109fb565b610273610574366004611a31565b610a07565b6103a1600a81565b5f6001600160e01b03198216639ab669ef60e01b14806105a557506105a582610a21565b92915050565b6105b3610a65565b5f5b818110156105f4576105ec8383838181106105d2576105d2611bb0565b90506020020160208101906105e79190611a31565b610a6d565b6001016105b5565b505050565b610601610a65565b6001600160a01b0382166106285760405163135217db60e21b815260040160405180910390fd5b6106328282610a76565b5050565b61063e610ad4565b61064781610adc565b50565b610652610b38565b61065e84848484610b60565b50505050565b61066d81610c02565b61064781610c0b565b61067f81610c02565b61064781610a6d565b60606106935f610c9c565b905090565b5f6105a58183610ca8565b6106ab610b38565b6106325f8383610cc8565b5f5f6106c26003610d61565b11156106d35761069360035f610d6a565b505f90565b6106e0610d75565b6106e95f610dd3565b565b5f806106f986868686610941565b60ff161490505b949350505050565b610718610713610dec565b610df5565b6106e9610e1c565b60606105a582610e7e565b610733610b38565b6105f4838383610cc8565b610746610b38565b610632825f83610cc8565b5f6105a5600383610ca8565b610765610ad4565b6106e9610ff3565b610775610ad4565b5f819003610796576040516359203cb960e01b815260040160405180910390fd5b600254808211156107c657604051630befc49d60e01b81526004016107bd91815260200190565b60405180910390fd5b505f6107d15f610d61565b11156107df576107df610ff3565b5f5b818110156105f4576108188383838181106107fe576107fe611bb0565b90506020020160208101906108139190611a31565b611024565b6001016107e1565b610828610a65565b5f5b828110156108ad575f84848381811061084557610845611bb0565b905060200201602081019061085a9190611a31565b90506001600160a01b0381166108835760405163135217db60e21b815260040160405180910390fd5b6001600160a01b03165f908152600560205260409020805460ff191683151517905560010161082a565b507f430881f04f203566ee9b32d6444cf02e1b2a0f17ab6b4263a1ee2074d3d0f4838383836040516108e193929190611bc4565b60405180910390a1505050565b5f6106935f610d61565b610900610a65565b5f5b818110156105f45761093983838381811061091f5761091f611bb0565b90506020020160208101906109349190611a31565b610c0b565b600101610902565b5f61094e8585858561108a565b95945050505050565b5f610963848484611157565b90505b9392505050565b5f6109775f610d61565b821015610988576105a55f83610d6a565b505f919050565b610997610ad4565b6106478161121b565b6109a8610ad4565b600254806109b55f610d61565b1081906109d857604051630befc49d60e01b81526004016107bd91815260200190565b5061063282611024565b5f806109ef858585610957565b60ff1614949350505050565b60606106936003610c9c565b610a0f610d75565b610a1881610df5565b61064781611278565b5f610a2b826112e9565b80610a4657506001600160e01b031982166307f5828d60e41b145b806105a557506301ffc9a760e01b6001600160e01b03198316146105a5565b6106e9610ad4565b6106478161138a565b6001600160a01b0382165f81815260056020908152604091829020805460ff191685151590811790915591519182527f407b412a9b6db334d48445ec9bcad46fb50bc4b2e97f73e963e397101957a729910160405180910390a25050565b6106e9610d75565b805f03610afc57604051631e69e71760e21b815260040160405180910390fd5b60028190556040518181527f2292ad4720fff63e2bd104c6b1c0d72c2c729a6001c8ab4bb947cbcc51109863906020015b60405180910390a150565b610b43600333610ca8565b6106e957604051630599c0e960e01b815260040160405180910390fd5b5f610b6a5f610d61565b90505f5b81811015610bfa57610b805f82610d6a565b604051631f2d7a6560e11b81526001600160a01b03888116600483015287811660248301528681166044830152606482018690529190911690633e5af4ca906084015f604051808303815f87803b158015610bd9575f5ffd5b505af1158015610beb573d5f5f3e3d5ffd5b50505050806001019050610b6e565b505050505050565b610647816113d2565b6001600160a01b038116610c325760405163135217db60e21b815260040160405180910390fd5b610c3b81611411565b610c4660038261141b565b610c63576040516371b3c56560e11b815260040160405180910390fd5b6040516001600160a01b03821681527f2de35142b19ed5a07796cf30791959c592018f70b1d2d7c460eef8ffe713692b90602001610b2d565b60605f6109668361142f565b6001600160a01b03165f9081526001919091016020526040902054151590565b5f610cd25f610d61565b90505f5b81811015610d5a57610ce85f82610d6a565b6040516322ebca6d60e21b81526001600160a01b0387811660048301528681166024830152604482018690529190911690638baf29b4906064015f604051808303815f87803b158015610d39575f5ffd5b505af1158015610d4b573d5f5f3e3d5ffd5b50505050806001019050610cd6565b5050505050565b5f6105a5825490565b5f6109668383611488565b610d7d610dec565b6001600160a01b0316610d986006546001600160a01b031690565b6001600160a01b0316146106e957610dae610dec565b60405163118cdaa760e01b81526001600160a01b0390911660048201526024016107bd565b600780546001600160a01b0319169055610647816114ae565b5f6106936114ff565b610dfe81610698565b15610647576040516302925f7360e11b815260040160405180910390fd5b5f610e25610dec565b9050806001600160a01b0316610e436007546001600160a01b031690565b6001600160a01b031614610e755760405163118cdaa760e01b81526001600160a01b03821660048201526024016107bd565b61064781610dd3565b606060ff8216610eb157505060408051808201909152600d81526c2737a932b9ba3934b1ba34b7b760991b602082015290565b5f610ebb5f610d61565b90505f5b81811015610fb7575f610ed28183610d6a565b604051633e822efb60e11b815260ff871660048201529091506001600160a01b03821690637d045df690602401602060405180830381865afa158015610f1a573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f3e9190611c1c565b15610fae57604051637f4ab1dd60e01b815260ff861660048201526001600160a01b03821690637f4ab1dd906024015f60405180830381865afa158015610f87573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261094e9190810190611c4b565b50600101610ebf565b505060408051808201909152601881527f556e6b6e6f776e207265737472696374696f6e20636f64650000000000000000602082015292915050565b6040517fdbf61473843cd9be1c9791ce51ef66d0da6c9026d62ba80c1ca433b13fb729b2905f90a16106e95f611569565b61102d81611572565b6110375f8261141b565b6110545760405163cc790a4b60e01b815260040160405180910390fd5b6040516001600160a01b038216907f60305ce6c9104acd0969d358f926bf391174340660aaf5e6215261fd6847bf46905f90a250565b5f5f6110955f610d61565b90505f5b8181101561114b575f6110ac8183610d6a565b60405163d32c7bb560e01b81526001600160a01b038a811660048301528981166024830152888116604483015260648201889052919091169063d32c7bb590608401602060405180830381865afa158015611109573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061112d9190611cfe565b905060ff811615611142579250610700915050565b50600101611099565b505f9695505050505050565b5f5f6111625f610d61565b90505f5b81811015611210575f6111798183610d6a565b60405163d4ce141560e01b81526001600160a01b038981166004830152888116602483015260448201889052919091169063d4ce141590606401602060405180830381865afa1580156111ce573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111f29190611cfe565b905060ff811615611207579250610966915050565b50600101611166565b505f95945050505050565b6112255f826115ca565b61124257604051632cdc3a4160e21b815260040160405180910390fd5b6040516001600160a01b038216907f6d83315c9718799346b67584ec64301b1457e989c8e35a8e2982a7776c04bfc4905f90a250565b611280610d75565b600780546001600160a01b0383166001600160a01b031990911681179091556112b16006546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b5f6001600160e01b031982166320c49ce760e01b148061131957506001600160e01b0319821663157094b960e31b145b8061133457506001600160e01b031982166378a8de7d60e01b145b8061134f57506001600160e01b03198216630c51264760e21b145b8061136a57506001600160e01b03198216633235d15f60e11b145b806105a557506001600160e01b03198216637157797f60e01b1492915050565b611393816115de565b336001600160a01b038216148015906113c357506001600160a01b0381165f9081526005602052604090205460ff165b1561064757610647815f610a76565b336001600160a01b03821614801561140157506001600160a01b0381165f9081526005602052604090205460ff165b156114095750565b610647610a65565b610dfe5f82610ca8565b5f610966836001600160a01b03841661163f565b6060815f0180548060200260200160405190810160405280929190818152602001828054801561147c57602002820191905f5260205f20905b815481526020019060010190808311611468575b50505050509050919050565b5f825f01828154811061149d5761149d611bb0565b905f5260205f200154905092915050565b600680546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b5f36601480821080159061153b57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031633145b156115615761154e36828403815f611d19565b61155791611d40565b60601c9250505090565b339250505090565b6106478161168b565b61157b816116e4565b611586600382610ca8565b156115a4576040516302925f7360e11b815260040160405180910390fd5b6115ad8161170b565b61064757604051639952e34360e01b815260040160405180910390fd5b5f610966836001600160a01b038416611748565b6115e96003826115ca565b61160657604051633477dd1760e01b815260040160405180910390fd5b6040516001600160a01b03821681527f28a4ca7134a3b3f9aff286e79ad3daadb4a06d1b43d037a3a98bdc074edd9b7a90602001610b2d565b5f81815260018301602052604081205461168457508154600181810184555f8481526020808220909301849055845484825282860190935260409020919091556105a5565b505f6105a5565b5f611694825490565b90505f5b818110156116dd57826001015f845f0183815481106116b9576116b9611bb0565b905f5260205f20015481526020019081526020015f205f9055806001019050611698565b50505f9055565b6001600160a01b0381166106475760405163f9d152fb60e01b815260040160405180910390fd5b5f61171582611832565b61172057505f919050565b611731826358d34ba960e11b611871565b806105a557506105a582632497d6cb60e01b611871565b5f8181526001830160205260408120548015611822575f61176a600183611d80565b85549091505f9061177d90600190611d80565b90508082146117dc575f865f01828154811061179b5761179b611bb0565b905f5260205f200154905080875f0184815481106117bb576117bb611bb0565b5f918252602080832090910192909255918252600188019052604090208390555b85548690806117ed576117ed611d9f565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f9055600193505050506105a5565b5f9150506105a5565b5092915050565b5f611844826301ffc9a760e01b611871565b15610988575f8061185d846001600160e01b0319611892565b915091508180156107005750159392505050565b5f5f5f61187e8585611892565b9150915081801561094e5750949350505050565b6301ffc9a760e01b5f818152600483905290819060208260248188617530fa92505f511515601f3d11169150509250929050565b5f602082840312156118d6575f5ffd5b81356001600160e01b031981168114610966575f5ffd5b5f5f83601f8401126118fd575f5ffd5b50813567ffffffffffffffff811115611914575f5ffd5b6020830191508360208260051b850101111561192e575f5ffd5b9250929050565b5f5f60208385031215611946575f5ffd5b823567ffffffffffffffff81111561195c575f5ffd5b611968858286016118ed565b90969095509350505050565b6001600160a01b0381168114610647575f5ffd5b8015158114610647575f5ffd5b5f5f604083850312156119a6575f5ffd5b82356119b181611974565b915060208301356119c181611988565b809150509250929050565b5f602082840312156119dc575f5ffd5b5035919050565b5f5f5f5f608085870312156119f6575f5ffd5b8435611a0181611974565b93506020850135611a1181611974565b92506040850135611a2181611974565b9396929550929360600135925050565b5f60208284031215611a41575f5ffd5b813561096681611974565b602080825282518282018190525f918401906040840190835b81811015611a8c5783516001600160a01b0316835260209384019390920191600101611a65565b509095945050505050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b5f5f60408385031215611add575f5ffd5b8235611ae881611974565b946020939093013593505050565b60ff81168114610647575f5ffd5b5f60208284031215611b14575f5ffd5b813561096681611af6565b5f5f5f60608486031215611b31575f5ffd5b8335611b3c81611974565b92506020840135611b4c81611974565b929592945050506040919091013590565b5f5f5f60408486031215611b6f575f5ffd5b833567ffffffffffffffff811115611b85575f5ffd5b611b91868287016118ed565b9094509250506020840135611ba581611988565b809150509250925092565b634e487b7160e01b5f52603260045260245ffd5b604080825281018390525f8460608301825b86811015611c06578235611be981611974565b6001600160a01b0316825260209283019290910190600101611bd6565b5080925050508215156020830152949350505050565b5f60208284031215611c2c575f5ffd5b815161096681611988565b634e487b7160e01b5f52604160045260245ffd5b5f60208284031215611c5b575f5ffd5b815167ffffffffffffffff811115611c71575f5ffd5b8201601f81018413611c81575f5ffd5b805167ffffffffffffffff811115611c9b57611c9b611c37565b604051601f8201601f19908116603f0116810167ffffffffffffffff81118282101715611cca57611cca611c37565b604052818152828201602001861015611ce1575f5ffd5b8160208401602083015e5f91810160200191909152949350505050565b5f60208284031215611d0e575f5ffd5b815161096681611af6565b5f5f85851115611d27575f5ffd5b83861115611d33575f5ffd5b5050820193919092039150565b80356bffffffffffffffffffffffff19811690601484101561182b576bffffffffffffffffffffffff1960149490940360031b84901b1690921692915050565b818103818111156105a557634e487b7160e01b5f52601160045260245ffd5b634e487b7160e01b5f52603160045260245ffdfea26469706673582212208b02f7ee6873c97209fdcf3b38f7f61aa232ea774b41b32d32be43f587b0165e64736f6c63430008250033","sourceMap":"788:1905:35:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;2290:319:34;;;;;;:::i;:::-;;:::i;:::-;;;470:14:83;;463:22;445:41;;433:2;418:18;2290:319:34;;;;;;;;1872:205:70;;;;;;:::i;:::-;;:::i;:::-;;2125:251;;;;;;:::i;:::-;;:::i;3487:150:69:-;;;;;;:::i;:::-;;:::i;2583:330:28:-;;;;;;:::i;:::-;;:::i;2979:137:71:-;;;;;;:::i;:::-;;:::i;3404:141::-;;;;;;:::i;:::-;;:::i;5029:136:69:-;;;:::i;:::-;;;;;;;:::i;4333:158::-;;;;;;:::i;:::-;;:::i;737:129:72:-;852:7;;;;;;;;;;;;-1:-1:-1;;;852:7:72;;;;737:129;;;;;;;:::i;1874:137:15:-;;;;;;:::i;:::-;1749:17;-1:-1:-1;;;;;1973:31:15;;;;;;;1874:137;3239:155:28;;;;;;:::i;:::-;;:::i;2211:383:68:-;;;:::i;:::-;;;-1:-1:-1;;;;;4963:32:83;;;4945:51;;4933:2;4918:18;2211:383:68;4799:203:83;3949:124:69;4057:9;;3949:124;;;5153:25:83;;;5141:2;5126:18;3949:124:69;5007:177:83;2293:101:10;;;:::i;5266:311:28:-;;;;;;:::i;:::-;;:::i;1876:175:34:-;;;:::i;1666:107:15:-;1749:17;1666:107;;4621:240:28;;;;;;:::i;:::-;;:::i;2982:212::-;;;;;;:::i;:::-;;:::i;3439:161::-;;;;;;:::i;:::-;;:::i;1638:85:10:-;1710:6;;-1:-1:-1;;;;;1710:6:10;1638:85;;3636:133:71;;;;;;:::i;:::-;;:::i;2691:117:69:-;;;:::i;2150:477::-;;;;;;:::i;:::-;;:::i;2424:478:70:-;;;;;;:::i;:::-;;:::i;4137:132:69:-;;;:::i;1623:201:70:-;;;;;;:::i;:::-;;:::i;4289:282:28:-;;;;;;:::i;:::-;;:::i;:::-;;;7269:4:83;7257:17;;;7239:36;;7227:2;7212:18;4289:282:28;7097:184:83;3991:242:28;;;;;;:::i;:::-;;:::i;4555:410:69:-;;;;;;:::i;:::-;;:::i;3001:151:70:-;;;;;;:::i;:::-;-1:-1:-1;;;;;3113:32:70;3090:4;3113:32;;;:25;:32;;;;;;;;;3001:151;3701:133:69;;;;;;:::i;:::-;;:::i;1232:99:11:-;1311:13;;-1:-1:-1;;;;;1311:13:11;1232:99;;3040:383:69;;;;;;:::i;:::-;;:::i;4925:281:28:-;;;;;;:::i;:::-;;:::i;3200:127:70:-;;;:::i;1365:209:34:-;;;;;;:::i;:::-;;:::i;493:46:80:-;;537:2;493:46;;2290:319:34;2440:4;-1:-1:-1;;;;;;2467:65:34;;-1:-1:-1;;;2467:65:34;;:135;;;2548:54;2590:11;2548:41;:54::i;:::-;2460:142;2290:319;-1:-1:-1;;2290:319:34:o;1872:205:70:-;2185:26:71;:24;:26::i;:::-;1984:9:70::1;1979:92;1999:17:::0;;::::1;1979:92;;;2037:23;2050:6;;2057:1;2050:9;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;2037:12;:23::i;:::-;2018:3;;1979:92;;;;1872:205:::0;;:::o;2125:251::-;2185:26:71;:24;:26::i;:::-;-1:-1:-1;;;;;2258:19:70;::::1;2250:64;;;;-1:-1:-1::0;;;2250:64:70::1;;;;;;;;;;;;2324:45;2353:5;2360:8;2324:28;:45::i;:::-;2125:251:::0;;:::o;3487:150:69:-;880:24;:22;:24::i;:::-;3607:23:::1;3620:9;3607:12;:23::i;:::-;3487:150:::0;:::o;2583:330:28:-;2002:18:71;:16;:18::i;:::-;2846:60:28::1;2881:7;2890:4;2896:2;2900:5;2846:34;:60::i;:::-;2583:330:::0;;;;:::o;2979:137:71:-;3047:35;3076:5;3047:28;:35::i;:::-;3092:17;3103:5;3092:10;:17::i;3404:141::-;3474:35;3503:5;3474:28;:35::i;:::-;3519:19;3532:5;3519:12;:19::i;5029:136:69:-;5108:16;5143:15;:6;:13;:15::i;:::-;5136:22;;5029:136;:::o;4333:158::-;4430:4;4453:31;4430:4;4477:5;4453:15;:31::i;3239:155:28:-;2002:18:71;:16;:18::i;:::-;3352:35:28::1;3373:1;3377:2;3381:5;3352:12;:35::i;2211:383:68:-:0;2274:7;2321:1;2297:21;:12;:19;:21::i;:::-;:25;2293:295;;;2510:19;:12;2527:1;2510:16;:19::i;2293:295::-;-1:-1:-1;2575:1:68;;2211:383::o;2293:101:10:-;1531:13;:11;:13::i;:::-;2357:30:::1;2384:1;2357:18;:30::i;:::-;2293:101::o:0;5266:311:28:-;5447:4;;5474:55;5504:7;5513:4;5519:2;5523:5;5474:29;:55::i;:::-;:96;;;5467:103;;5266:311;;;;;;;:::o;1876:175:34:-;1937:67;1991:12;:10;:12::i;:::-;1937:53;:67::i;:::-;2014:30;:28;:30::i;4621:240:28:-;4771:13;4807:47;4838:15;4807:30;:47::i;2982:212::-;2002:18:71;:16;:18::i;:::-;3158:29:28::1;3171:4;3177:2;3181:5;3158:12;:29::i;3439:161::-:0;2002:18:71;:16;:18::i;:::-;3556:37:28::1;3569:4;3583:1;3587:5;3556:12;:37::i;3636:133:71:-:0;3711:4;3734:28;:12;3756:5;3734:21;:28::i;2691:117:69:-;794:19;:17;:19::i;:::-;2788:13:::1;:11;:13::i;2150:477::-:0;794:19;:17;:19::i;:::-;2293:1:::1;2276:18:::0;;;2268:76:::1;;;;-1:-1:-1::0;;;2268:76:69::1;;;;;;;;;;;;2379:9;::::0;2362:26;;::::1;;2354:97;;;;-1:-1:-1::0;;;2354:97:69::1;;;;;;5153:25:83::0;;5141:2;5126:18;;5007:177;2354:97:69::1;;;;;;;;;;2483:1;2465:15;:6;:13;:15::i;:::-;:19;2461:63;;;2500:13;:11;:13::i;:::-;2538:9;2533:88;2553:17:::0;;::::1;2533:88;;;2591:19;2600:6;;2607:1;2600:9;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;2591:8;:19::i;:::-;2572:3;;2533:88;;2424:478:70::0;2185:26:71;:24;:26::i;:::-;2607:9:70::1;2602:229;2622:17:::0;;::::1;2602:229;;;2660:13;2676:6;;2683:1;2676:9;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;2660:25:::0;-1:-1:-1;;;;;;2707:19:70;::::1;2699:64;;;;-1:-1:-1::0;;;2699:64:70::1;;;;;;;;;;;;-1:-1:-1::0;;;;;2777:32:70::1;;::::0;;;:25:::1;:32;::::0;;;;:43;;-1:-1:-1;;2777:43:70::1;::::0;::::1;;;::::0;;-1:-1:-1;2641:3:70::1;2602:229;;;;2845:50;2878:6;;2886:8;2845:50;;;;;;;;:::i;:::-;;;;;;;;2424:478:::0;;;:::o;4137:132:69:-;4221:7;4247:15;:6;:13;:15::i;1623:201:70:-;2185:26:71;:24;:26::i;:::-;1733:9:70::1;1728:90;1748:17:::0;;::::1;1728:90;;;1786:21;1797:6;;1804:1;1797:9;;;;;;;:::i;:::-;;;;;;;;;;;;;;:::i;:::-;1786:10;:21::i;:::-;1767:3;;1728:90;;4289:282:28::0;4480:5;4508:56;4539:7;4548:4;4554:2;4558:5;4508:30;:56::i;:::-;4501:63;4289:282;-1:-1:-1;;;;;4289:282:28:o;3991:242::-;4155:5;4183:43;4210:4;4216:2;4220:5;4183:26;:43::i;:::-;4176:50;;3991:242;;;;;;:::o;4555:410:69:-;4647:7;4679:15;:6;:13;:15::i;:::-;4670:6;:24;4666:293;;;4882:18;:6;4893;4882:10;:18::i;4666:293::-;-1:-1:-1;4946:1:69;;4555:410;-1:-1:-1;4555:410:69:o;3701:133::-;794:19;:17;:19::i;:::-;3809:18:::1;3821:5;3809:11;:18::i;3040:383::-:0;794:19;:17;:19::i;:::-;3274:9:::1;::::0;;3301:15:::1;3254:17;3301:13;:15::i;:::-;:27;3380:9;3293:98;;;;;-1:-1:-1::0;;;3293:98:69::1;;;;;;5153:25:83::0;;5141:2;5126:18;;5007:177;3293:98:69::1;;3401:15;3410:5;3401:8;:15::i;4925:281:28:-:0;5089:4;;5116:42;5142:4;5148:2;5152:5;5116:25;:42::i;:::-;:83;;;;4925:281;-1:-1:-1;;;;4925:281:28:o;3200:127:70:-;3264:16;3299:21;:12;:19;:21::i;1365:209:34:-;1531:13:10;:11;:13::i;:::-;1454:63:34::1;1508:8;1454:53;:63::i;:::-;1527:40;1558:8;1527:30;:40::i;1556:288:29:-:0;1658:4;1681:45;1714:11;1681:32;:45::i;:::-;:103;;;-1:-1:-1;;;;;;;1730:54:29;;-1:-1:-1;;;1730:54:29;1681:103;:156;;;-1:-1:-1;;;;;;;;;;829:40:22;;;1800:37:29;730:146:22;2998:103:68;3070:24;:22;:24::i;2008:174:67:-;2129:46;2169:5;2129:39;:46::i;4883:204:70:-;-1:-1:-1;;;;;4978:32:70;;;;;;:25;:32;;;;;;;;;:43;;-1:-1:-1;;4978:43:70;;;;;;;;;;5036:44;;445:41:83;;;5036:44:70;;418:18:83;5036:44:70;;;;;;;4883:204;;:::o;2881:72:34:-;1531:13:10;:11;:13::i;6050:225:69:-;6126:9;6139:1;6126:14;6118:82;;;;-1:-1:-1;;;6118:82:69;;;;;;;;;;;;6210:9;:21;;;6246:22;;5153:25:83;;;6246:22:69;;5141:2:83;5126:18;6246:22:69;;;;;;;;6050:225;:::o;6902:144:71:-;6970:33;:12;6992:10;6970:21;:33::i;:::-;6962:77;;;;-1:-1:-1;;;6962:77:71;;;;;;;;;;;9164:285:69;9271:19;9293:15;:6;:13;:15::i;:::-;9271:37;-1:-1:-1;9323:9:69;9318:125;9342:11;9338:1;:15;9318:125;;;9380:13;:6;9391:1;9380:10;:13::i;:::-;9374:58;;-1:-1:-1;;;9374:58:69;;-1:-1:-1;;;;;8575:32:83;;;9374:58:69;;;8557:51:83;8644:32;;;8624:18;;;8617:60;8713:32;;;8693:18;;;8686:60;8762:18;;;8755:34;;;9374:32:69;;;;;;;8529:19:83;;9374:58:69;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;9355:3;;;;;9318:125;;;;9261:188;9164:285;;;;:::o;1475:234:67:-;1640:62;1696:5;1640:55;:62::i;4440:400:71:-;-1:-1:-1;;;;;4510:19:71;;4502:64;;;;-1:-1:-1;;;4502:64:71;;;;;;;;;;;;4576:26;4596:5;4576:19;:26::i;:::-;4743:23;:12;4760:5;4743:16;:23::i;:::-;4735:66;;;;-1:-1:-1;;;4735:66:71;;;;;;;;;;;;4816:17;;-1:-1:-1;;;;;4963:32:83;;4945:51;;4816:17:71;;4933:2:83;4918:18;4816:17:71;4799:203:83;19500:273:27;19563:16;19591:22;19616:19;19624:3;19616:7;:19::i;17414:165::-;-1:-1:-1;;;;;17547:23:27;17494:4;5238:21;;;:14;;;;;:21;;;;;;:26;;;17414:165::o;8250:259:69:-;8340:19;8362:15;:6;:13;:15::i;:::-;8340:37;-1:-1:-1;8392:9:69;8387:116;8411:11;8407:1;:15;8387:116;;;8449:13;:6;8460:1;8449:10;:13::i;:::-;8443:49;;-1:-1:-1;;;8443:49:69;;-1:-1:-1;;;;;9020:32:83;;;8443:49:69;;;9002:51:83;9089:32;;;9069:18;;;9062:60;9138:18;;;9131:34;;;8443:32:69;;;;;;;8975:18:83;;8443:49:69;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;8424:3;;;;;8387:116;;;;8330:179;8250:259;;;:::o;17660:115:27:-;17723:7;17749:19;17757:3;5434:18;;5352:107;18802:158;18877:7;18927:23;18932:3;18944:5;18927:4;:23::i;1796:162:10:-;1866:12;:10;:12::i;:::-;-1:-1:-1;;;;;1855:23:10;:7;1710:6;;-1:-1:-1;;;;;1710:6:10;;1638:85;1855:7;-1:-1:-1;;;;;1855:23:10;;1851:101;;1928:12;:10;:12::i;:::-;1901:40;;-1:-1:-1;;;1901:40:10;;-1:-1:-1;;;;;4963:32:83;;;1901:40:10;;;4945:51:83;4918:18;;1901:40:10;4799:203:83;2011:153:11;2100:13;2093:20;;-1:-1:-1;;;;;;2093:20:11;;;2123:34;2148:8;2123:24;:34::i;1854:154:35:-;1941:14;1974:27;:25;:27::i;2022:206:29:-;2120:29;2139:8;2120:12;:29::i;:::-;2119:30;2111:110;;;;-1:-1:-1;;;2111:110:29;;;;;;;;;;;2244:229:11;2296:14;2313:12;:10;:12::i;:::-;2296:29;;2357:6;-1:-1:-1;;;;;2339:24:11;:14;1311:13;;-1:-1:-1;;;;;1311:13:11;;1232:99;2339:14;-1:-1:-1;;;;;2339:24:11;;2335:96;;2386:34;;-1:-1:-1;;;2386:34:11;;-1:-1:-1;;;;;4963:32:83;;2386:34:11;;;4945:51:83;4918:18;;2386:34:11;4799:203:83;2335:96:11;2440:26;2459:6;2440:18;:26::i;8179:594:28:-;8273:13;8302:56;;;8298:110;;-1:-1:-1;;8381:16:28;;;;;;;;;;;;-1:-1:-1;;;8381:16:28;;;;;8179:594::o;8298:110::-;8417:19;8439:15;:6;:13;:15::i;:::-;8417:37;-1:-1:-1;8469:9:28;8464:267;8488:11;8484:1;:15;8464:267;;;8520:11;8540:13;8520:11;8551:1;8540:10;:13::i;:::-;8572:55;;-1:-1:-1;;;8572:55:28;;7269:4:83;7257:17;;8572:55:28;;;7239:36:83;8520:34:28;;-1:-1:-1;;;;;;8572:38:28;;;;;7212:18:83;;8572:55:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;8568:153;;;8654:52;;-1:-1:-1;;;8654:52:28;;7269:4:83;7257:17;;8654:52:28;;;7239:36:83;-1:-1:-1;;;;;8654:35:28;;;;;7212:18:83;;8654:52:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;-1:-1:-1;;8654:52:28;;;;;;;;;;;;:::i;8568:153::-;-1:-1:-1;8501:3:28;;8464:267;;;-1:-1:-1;;8747:19:28;;;;;;;;;;;;;;;;;;8179:594;-1:-1:-1;;8179:594:28:o;5444:98:69:-;5499:12;;;;;;;5521:14;:6;:12;:14::i;6762:312::-;6820:26;6839:5;6820:10;:26::i;:::-;6957;:6;6976:5;6957:10;:26::i;:::-;6949:89;;;;-1:-1:-1;;;6949:89:69;;;;;;;;;;;;7053:14;;-1:-1:-1;;;;;7053:14:69;;;;;;;;6762:312;:::o;6974:537:28:-;7135:5;7156:19;7178:15;:6;:13;:15::i;:::-;7156:37;-1:-1:-1;7208:9:28;7203:248;7227:11;7223:1;:15;7203:248;;;7259:17;7285:13;7259:17;7296:1;7285:10;:13::i;:::-;7279:76;;-1:-1:-1;;;7279:76:28;;-1:-1:-1;;;;;8575:32:83;;;7279:76:28;;;8557:51:83;8644:32;;;8624:18;;;8617:60;8713:32;;;8693:18;;;8686:60;8762:18;;;8755:34;;;7279:50:28;;;;;;;8529:19:83;;7279:76:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;7259:96;-1:-1:-1;7373:15:28;;;;7369:72;;7415:11;-1:-1:-1;7408:18:28;;-1:-1:-1;;7408:18:28;7369:72;-1:-1:-1;7240:3:28;;7203:248;;;-1:-1:-1;7473:30:28;7460:44;6974:537;-1:-1:-1;;;;;;6974:537:28:o;6110:467::-;6218:5;6235:19;6257:15;:6;:13;:15::i;:::-;6235:37;-1:-1:-1;6287:9:28;6282:235;6306:11;6302:1;:15;6282:235;;;6338:17;6364:13;6338:17;6375:1;6364:10;:13::i;:::-;6358:63;;-1:-1:-1;;;6358:63:28;;-1:-1:-1;;;;;9020:32:83;;;6358:63:28;;;9002:51:83;9089:32;;;9069:18;;;9062:60;9138:18;;;9131:34;;;6358:46:28;;;;;;;8975:18:83;;6358:63:28;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;6338:83;-1:-1:-1;6439:15:28;;;;6435:72;;6481:11;-1:-1:-1;6474:18:28;;-1:-1:-1;;6474:18:28;6435:72;-1:-1:-1;6319:3:28;;6282:235;;;-1:-1:-1;6539:30:28;6526:44;6110:467;-1:-1:-1;;;;;6110:467:28:o;7335:255:69:-;7470:29;:6;7492:5;7470:13;:29::i;:::-;7462:89;;;;-1:-1:-1;;;7462:89:69;;;;;;;;;;;;7566:17;;-1:-1:-1;;;;;7566:17:69;;;;;;;;7335:255;:::o;1649:178:11:-;1531:13:10;:11;:13::i;:::-;1738::11::1;:24:::0;;-1:-1:-1;;;;;1738:24:11;::::1;-1:-1:-1::0;;;;;;1738:24:11;;::::1;::::0;::::1;::::0;;;1802:7:::1;1710:6:10::0;;-1:-1:-1;;;;;1710:6:10;;1638:85;1802:7:11::1;-1:-1:-1::0;;;;;1777:43:11::1;;;;;;;;;;;1649:178:::0;:::o;11440:599:28:-;11533:4;-1:-1:-1;;;;;;11556:61:28;;-1:-1:-1;;;11556:61:28;;:132;;-1:-1:-1;;;;;;;11633:55:28;;-1:-1:-1;;;11633:55:28;11556:132;:214;;;-1:-1:-1;;;;;;;11704:66:28;;-1:-1:-1;;;11704:66:28;11556:214;:298;;;-1:-1:-1;;;;;;;11786:68:28;;-1:-1:-1;;;11786:68:28;11556:298;:391;;;-1:-1:-1;;;;;;;11870:77:28;;-1:-1:-1;;;11870:77:28;11556:391;:476;;;-1:-1:-1;;;;;;;11963:69:28;;-1:-1:-1;;;11963:69:28;11549:483;11440:599;-1:-1:-1;;11440:599:28:o;4275:255:70:-;4348:38;4380:5;4348:31;:38::i;:::-;4400:10;-1:-1:-1;;;;;4400:19:70;;;;;;:55;;-1:-1:-1;;;;;;4423:32:70;;;;;;:25;:32;;;;;;;;4400:55;4396:128;;;4471:42;4500:5;4507;4471:28;:42::i;5759:223::-;5852:10;-1:-1:-1;;;;;5852:19:70;;;:55;;;;-1:-1:-1;;;;;;5875:32:70;;;;;;:25;:32;;;;;;;;5852:55;5848:92;;;5759:223;:::o;5848:92::-;5949:26;:24;:26::i;9793:195:28:-;9887:22;:6;9903:5;9887:15;:22::i;16462:150:27:-;16532:4;16555:50;16560:3;-1:-1:-1;;;;;16580:23:27;;16555:4;:50::i;6460:109::-;6516:16;6551:3;:11;;6544:18;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;6460:109;;;:::o;5801:119::-;5869:7;5895:3;:11;;5907:5;5895:18;;;;;;;;:::i;:::-;;;;;;;;;5888:25;;5801:119;;;;:::o;2912:187:10:-;3004:6;;;-1:-1:-1;;;;;3020:17:10;;;-1:-1:-1;;;;;;3020:17:10;;;;;;;3052:40;;3004:6;;;3020:17;3004:6;;3052:40;;2985:16;;3052:40;2975:124;2912:187;:::o;2248:471:15:-;2310:7;2354:8;3609:2;2445:37;;;;;;:71;;-1:-1:-1;1749:17:15;-1:-1:-1;;;;;1973:31:15;2505:10;1973:31;2486:30;2441:272;;;2583:47;:8;2592:36;;;2583:8;;:47;:::i;:::-;2575:56;;;:::i;:::-;2567:65;;2560:72;;;;2248:471;:::o;2441:272::-;735:10:18;2677:25:15;;;;2248:471;:::o;17250:83:27:-;17308:18;17315:3;17308:6;:18::i;9061:324:28:-;9137:39;9170:5;9137:32;:39::i;:::-;9195:28;:12;9217:5;9195:21;:28::i;:::-;9194:29;9186:109;;;;-1:-1:-1;;;9186:109:28;;;;;;;;;;;;9313:29;9336:5;9313:22;:29::i;:::-;9305:73;;;;-1:-1:-1;;;9305:73:28;;;;;;;;;;;16780:156:27;16853:4;16876:53;16884:3;-1:-1:-1;;;;;16904:23:27;;16876:7;:53::i;5410:294:71:-;5605:26;:12;5625:5;5605:19;:26::i;:::-;5597:65;;;;-1:-1:-1;;;5597:65:71;;;;;;;;;;;;5678:19;;-1:-1:-1;;;;;4963:32:83;;4945:51;;5678:19:71;;4933:2:83;4918:18;5678:19:71;4799:203:83;2538:406:27;2601:4;5238:21;;;:14;;;:21;;;;;;2617:321;;-1:-1:-1;2659:23:27;;;;;;;;:11;:23;;;;;;;;;;;;;2841:18;;2817:21;;;:14;;;:21;;;;;;:42;;;;2873:11;;2617:321;-1:-1:-1;2922:5:27;2915:12;;4824:237;4875:11;4889:12;4897:3;5434:18;;5352:107;4889:12;4875:26;-1:-1:-1;4916:9:27;4911:96;4935:3;4931:1;:7;4911:96;;;4966:3;:14;;:30;4981:3;:11;;4993:1;4981:14;;;;;;;;:::i;:::-;;;;;;;;;4966:30;;;;;;;;;;;4959:37;;;4940:3;;;;;4911:96;;;-1:-1:-1;;5039:11:27;34209:23:16;;2125:251:70:o;9974:164:69:-;-1:-1:-1;;;;;10049:19:69;;10041:90;;;;-1:-1:-1;;;10041:90:69;;;;;;;;;;;10702:397:28;10780:4;10801:35;10830:5;10801:28;:35::i;:::-;10796:79;;-1:-1:-1;10859:5:28;;10702:397;-1:-1:-1;10702:397:28:o;10796:79::-;10891:89;10938:5;-1:-1:-1;;;10891:46:28;:89::i;:::-;:201;;;-1:-1:-1;10996:96:28;11043:5;-1:-1:-1;;;10996:46:28;:96::i;3112:1368:27:-;3178:4;3307:21;;;:14;;;:21;;;;;;3343:13;;3339:1135;;3710:18;3731:12;3742:1;3731:8;:12;:::i;:::-;3777:18;;3710:33;;-1:-1:-1;3757:17:27;;3777:22;;3798:1;;3777:22;:::i;:::-;3757:42;;3832:9;3818:10;:23;3814:378;;3861:17;3881:3;:11;;3893:9;3881:22;;;;;;;;:::i;:::-;;;;;;;;;3861:42;;4028:9;4002:3;:11;;4014:10;4002:23;;;;;;;;:::i;:::-;;;;;;;;;;;;:35;;;;4141:25;;;:14;;;:25;;;;;:36;;;3814:378;4270:17;;:3;;:17;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;4373:3;:14;;:21;4388:5;4373:21;;;;;;;;;;;4366:28;;;4416:4;4409:11;;;;;;;3339:1135;4458:5;4451:12;;;;;3339:1135;3184:1296;3112:1368;;;;:::o;719:528:23:-;783:4;976:68;1009:7;-1:-1:-1;;;976:32:23;:68::i;:::-;972:269;;;1061:12;;1093:52;1115:7;-1:-1:-1;;;;;;1093:21:23;:52::i;:::-;1060:85;;;;1166:7;:21;;;;-1:-1:-1;1177:10:23;;1159:28;-1:-1:-1;;;719:528:23:o;4504:238::-;4606:4;4623:12;4637:14;4655:43;4677:7;4686:11;4655:21;:43::i;:::-;4622:76;;;;4715:7;:20;;;;-1:-1:-1;4726:9:23;4708:27;-1:-1:-1;;;;4504:238:23:o;5198:628::-;-1:-1:-1;;;5310:12:23;5452:22;;;5494:4;5487:25;;;5310:12;;;5581:4;5310:12;5569:4;5310:12;5554:7;5547:5;5536:50;5525:61;;5740:4;5734:11;5727:19;5720:27;5654:4;5636:16;5633:26;5612:198;5599:211;;5438:382;5198:628;;;;;:::o;14:286:83:-;72:6;125:2;113:9;104:7;100:23;96:32;93:52;;;141:1;138;131:12;93:52;167:23;;-1:-1:-1;;;;;;219:32:83;;209:43;;199:71;;266:1;263;256:12;497:367;560:8;570:6;624:3;617:4;609:6;605:17;601:27;591:55;;642:1;639;632:12;591:55;-1:-1:-1;665:20:83;;708:18;697:30;;694:50;;;740:1;737;730:12;694:50;777:4;769:6;765:17;753:29;;837:3;830:4;820:6;817:1;813:14;805:6;801:27;797:38;794:47;791:67;;;854:1;851;844:12;791:67;497:367;;;;;:::o;869:437::-;955:6;963;1016:2;1004:9;995:7;991:23;987:32;984:52;;;1032:1;1029;1022:12;984:52;1072:9;1059:23;1105:18;1097:6;1094:30;1091:50;;;1137:1;1134;1127:12;1091:50;1176:70;1238:7;1229:6;1218:9;1214:22;1176:70;:::i;:::-;1265:8;;1150:96;;-1:-1:-1;869:437:83;-1:-1:-1;;;;869:437:83:o;1311:131::-;-1:-1:-1;;;;;1386:31:83;;1376:42;;1366:70;;1432:1;1429;1422:12;1447:118;1533:5;1526:13;1519:21;1512:5;1509:32;1499:60;;1555:1;1552;1545:12;1570:382;1635:6;1643;1696:2;1684:9;1675:7;1671:23;1667:32;1664:52;;;1712:1;1709;1702:12;1664:52;1751:9;1738:23;1770:31;1795:5;1770:31;:::i;:::-;1820:5;-1:-1:-1;1877:2:83;1862:18;;1849:32;1890:30;1849:32;1890:30;:::i;:::-;1939:7;1929:17;;;1570:382;;;;;:::o;1957:226::-;2016:6;2069:2;2057:9;2048:7;2044:23;2040:32;2037:52;;;2085:1;2082;2075:12;2037:52;-1:-1:-1;2130:23:83;;1957:226;-1:-1:-1;1957:226:83:o;2188:650::-;2274:6;2282;2290;2298;2351:3;2339:9;2330:7;2326:23;2322:33;2319:53;;;2368:1;2365;2358:12;2319:53;2407:9;2394:23;2426:31;2451:5;2426:31;:::i;:::-;2476:5;-1:-1:-1;2533:2:83;2518:18;;2505:32;2546:33;2505:32;2546:33;:::i;:::-;2598:7;-1:-1:-1;2657:2:83;2642:18;;2629:32;2670:33;2629:32;2670:33;:::i;:::-;2188:650;;;;-1:-1:-1;2722:7:83;;2802:2;2787:18;2774:32;;-1:-1:-1;;2188:650:83:o;2843:247::-;2902:6;2955:2;2943:9;2934:7;2930:23;2926:32;2923:52;;;2971:1;2968;2961:12;2923:52;3010:9;2997:23;3029:31;3054:5;3029:31;:::i;3095:637::-;3285:2;3297:21;;;3367:13;;3270:18;;;3389:22;;;3237:4;;3468:15;;;3442:2;3427:18;;;3237:4;3511:195;3525:6;3522:1;3519:13;3511:195;;;3590:13;;-1:-1:-1;;;;;3586:39:83;3574:52;;3655:2;3681:15;;;;3646:12;;;;3622:1;3540:9;3511:195;;;-1:-1:-1;3723:3:83;;3095:637;-1:-1:-1;;;;;3095:637:83:o;4004:418::-;4153:2;4142:9;4135:21;4116:4;4185:6;4179:13;4228:6;4223:2;4212:9;4208:18;4201:34;4287:6;4282:2;4274:6;4270:15;4265:2;4254:9;4250:18;4244:50;4343:1;4338:2;4329:6;4318:9;4314:22;4310:31;4303:42;4413:2;4406;4402:7;4397:2;4389:6;4385:15;4381:29;4370:9;4366:45;4362:54;4354:62;;;4004:418;;;;:::o;4427:367::-;4495:6;4503;4556:2;4544:9;4535:7;4531:23;4527:32;4524:52;;;4572:1;4569;4562:12;4524:52;4611:9;4598:23;4630:31;4655:5;4630:31;:::i;:::-;4680:5;4758:2;4743:18;;;;4730:32;;-1:-1:-1;;;4427:367:83:o;5189:114::-;5273:4;5266:5;5262:16;5255:5;5252:27;5242:55;;5293:1;5290;5283:12;5308:243;5365:6;5418:2;5406:9;5397:7;5393:23;5389:32;5386:52;;;5434:1;5431;5424:12;5386:52;5473:9;5460:23;5492:29;5515:5;5492:29;:::i;5556:508::-;5633:6;5641;5649;5702:2;5690:9;5681:7;5677:23;5673:32;5670:52;;;5718:1;5715;5708:12;5670:52;5757:9;5744:23;5776:31;5801:5;5776:31;:::i;:::-;5826:5;-1:-1:-1;5883:2:83;5868:18;;5855:32;5896:33;5855:32;5896:33;:::i;:::-;5556:508;;5948:7;;-1:-1:-1;;;6028:2:83;6013:18;;;;6000:32;;5556:508::o;6526:566::-;6618:6;6626;6634;6687:2;6675:9;6666:7;6662:23;6658:32;6655:52;;;6703:1;6700;6693:12;6655:52;6743:9;6730:23;6776:18;6768:6;6765:30;6762:50;;;6808:1;6805;6798:12;6762:50;6847:70;6909:7;6900:6;6889:9;6885:22;6847:70;:::i;:::-;6936:8;;-1:-1:-1;6821:96:83;-1:-1:-1;;7021:2:83;7006:18;;6993:32;7034:28;6993:32;7034:28;:::i;:::-;7081:5;7071:15;;;6526:566;;;;;:::o;7286:127::-;7347:10;7342:3;7338:20;7335:1;7328:31;7378:4;7375:1;7368:15;7402:4;7399:1;7392:15;7550:771;7772:2;7784:21;;;7757:18;;7840:22;;;7724:4;7919:6;7893:2;7878:18;;7724:4;7953:281;7967:6;7964:1;7961:13;7953:281;;;8042:6;8029:20;8062:31;8087:5;8062:31;:::i;:::-;-1:-1:-1;;;;;8118:31:83;8106:44;;8179:4;8207:17;;;;8170:14;;;;8146:1;7982:9;7953:281;;;7957:3;8251;8243:11;;;;8306:6;8299:14;8292:22;8285:4;8274:9;8270:20;8263:52;7550:771;;;;;;:::o;9176:245::-;9243:6;9296:2;9284:9;9275:7;9271:23;9267:32;9264:52;;;9312:1;9309;9302:12;9264:52;9344:9;9338:16;9363:28;9385:5;9363:28;:::i;9426:127::-;9487:10;9482:3;9478:20;9475:1;9468:31;9518:4;9515:1;9508:15;9542:4;9539:1;9532:15;9558:935;9638:6;9691:2;9679:9;9670:7;9666:23;9662:32;9659:52;;;9707:1;9704;9697:12;9659:52;9740:9;9734:16;9773:18;9765:6;9762:30;9759:50;;;9805:1;9802;9795:12;9759:50;9828:22;;9881:4;9873:13;;9869:27;-1:-1:-1;9859:55:83;;9910:1;9907;9900:12;9859:55;9943:2;9937:9;9969:18;9961:6;9958:30;9955:56;;;9991:18;;:::i;:::-;10040:2;10034:9;10132:2;10094:17;;-1:-1:-1;;10090:31:83;;;10123:2;10086:40;10082:54;10070:67;;10167:18;10152:34;;10188:22;;;10149:62;10146:88;;;10214:18;;:::i;:::-;10250:2;10243:22;10274;;;10315:15;;;10332:2;10311:24;10308:37;-1:-1:-1;10305:57:83;;;10358:1;10355;10348:12;10305:57;10407:6;10402:2;10398;10394:11;10389:2;10381:6;10377:15;10371:43;10460:1;10434:19;;;10455:2;10430:28;10423:39;;;;10438:6;9558:935;-1:-1:-1;;;;9558:935:83:o;10498:247::-;10566:6;10619:2;10607:9;10598:7;10594:23;10590:32;10587:52;;;10635:1;10632;10625:12;10587:52;10667:9;10661:16;10686:29;10709:5;10686:29;:::i;10750:331::-;10855:9;10866;10908:8;10896:10;10893:24;10890:44;;;10930:1;10927;10920:12;10890:44;10959:6;10949:8;10946:20;10943:40;;;10979:1;10976;10969:12;10943:40;-1:-1:-1;;11005:23:83;;;11050:25;;;;;-1:-1:-1;10750:331:83:o;11086:374::-;11207:19;;-1:-1:-1;;11244:40:83;;;11304:2;11296:11;;11293:161;;;-1:-1:-1;;11366:2:83;11362:12;;;;11359:1;11355:20;11351:58;;;11343:67;11339:105;;;;11086:374;-1:-1:-1;;11086:374:83:o;11465:225::-;11532:9;;;11553:11;;;11550:134;;;11606:10;11601:3;11597:20;11594:1;11587:31;11641:4;11638:1;11631:15;11669:4;11666:1;11659:15;11695:127;11756:10;11751:3;11747:20;11744:1;11737:31;11787:4;11784:1;11777:15;11811:4;11808:1;11801:15","linkReferences":{},"immutableReferences":{"1430":[{"start":826,"length":32},{"start":980,"length":32},{"start":5392,"length":32}]}},"methodIdentifiers":{"DEFAULT_MAX_RULES()":"f76bf550","acceptOwnership()":"79ba5097","addRule(address)":"e3c4602c","bindToken(address)":"3ff5aa02","bindTokens(address[])":"c7c24b18","canTransfer(address,address,uint256)":"e46638e6","canTransferFrom(address,address,address,uint256)":"7157797f","clearRules()":"b043572e","containsRule(address)":"54e4b945","created(address,uint256)":"5f8dead3","destroyed(address,uint256)":"8d2ea772","detectTransferRestriction(address,address,uint256)":"d4ce1415","detectTransferRestrictionFrom(address,address,address,uint256)":"d32c7bb5","getTokenBound()":"6a3edf28","getTokenBounds()":"e54621d2","isTokenBound(address)":"993e8b95","isTokenSelfBindingApproved(address)":"db75d017","isTrustedForwarder(address)":"572b6c05","maxRules()":"6ae728c6","messageForTransferRestriction(uint8)":"7f4ab1dd","owner()":"8da5cb5b","pendingOwner()":"e30c3978","removeRule(address)":"df21950f","renounceOwnership()":"715018a6","rule(uint256)":"db18af6c","rules()":"52f6747a","rulesCount()":"bc13eacc","setMaxRules(uint256)":"3a56d6d5","setRules(address[])":"b27aef3a","setTokenSelfBindingApproval(address,bool)":"3284a9a5","setTokenSelfBindingApprovalBatch(address[],bool)":"bb4b6121","supportsInterface(bytes4)":"01ffc9a7","transferOwnership(address)":"f2fde38b","transferred(address,address,address,uint256)":"3e5af4ca","transferred(address,address,uint256)":"8baf29b4","trustedForwarder()":"7da0a877","unbindToken(address)":"40db3b50","unbindTokens(address[])":"1455d0e7","version()":"54fd4d50"},"rawMetadata":"{\"compiler\":{\"version\":\"0.8.37+commit.f401782d\"},\"language\":\"Solidity\",\"output\":{\"abi\":[{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner_\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"forwarderIrrevocable\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"tokenContract\",\"type\":\"address\"}],\"stateMutability\":\"nonpayable\",\"type\":\"constructor\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"owner\",\"type\":\"address\"}],\"name\":\"OwnableInvalidOwner\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"account\",\"type\":\"address\"}],\"name\":\"OwnableUnauthorizedAccount\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_AdminWithAddressZeroNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_RuleInvalidInterface\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_RulesManagementModule_ArrayIsEmpty\",\"type\":\"error\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"maxRules\",\"type\":\"uint256\"}],\"name\":\"RuleEngine_RulesManagementModule_MaxRulesExceeded\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_RulesManagementModule_MaxRulesZeroNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_RulesManagementModule_RuleAccountCannotReceivePrivileges\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_RulesManagementModule_RuleAddressZeroNotAllowed\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_RulesManagementModule_RuleAlreadyExists\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"RuleEngine_RulesManagementModule_RuleDoNotMatch\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TokenBinding_InvalidTokenAddress\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TokenBinding_TokenAlreadyBound\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TokenBinding_TokenNotBound\",\"type\":\"error\"},{\"inputs\":[],\"name\":\"TokenBinding_UnauthorizedCaller\",\"type\":\"error\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract IRule\",\"name\":\"rule\",\"type\":\"address\"}],\"name\":\"AddRule\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[],\"name\":\"ClearRules\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferStarted\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"previousOwner\",\"type\":\"address\"},{\"indexed\":true,\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"OwnershipTransferred\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"contract IRule\",\"name\":\"rule\",\"type\":\"address\"}],\"name\":\"RemoveRule\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"uint256\",\"name\":\"maxRules\",\"type\":\"uint256\"}],\"name\":\"SetMaxRules\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"TokenBound\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address[]\",\"name\":\"tokens\",\"type\":\"address[]\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"TokenSelfBindingApprovalBatchSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"TokenSelfBindingApprovalSet\",\"type\":\"event\"},{\"anonymous\":false,\"inputs\":[{\"indexed\":false,\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"TokenUnbound\",\"type\":\"event\"},{\"inputs\":[],\"name\":\"DEFAULT_MAX_RULES\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"acceptOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IRule\",\"name\":\"rule_\",\"type\":\"address\"}],\"name\":\"addRule\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"bindToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"tokens\",\"type\":\"address[]\"}],\"name\":\"bindTokens\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"canTransfer\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"canTransferFrom\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"clearRules\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IRule\",\"name\":\"rule_\",\"type\":\"address\"}],\"name\":\"containsRule\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"created\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"destroyed\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"detectTransferRestriction\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"detectTransferRestrictionFrom\",\"outputs\":[{\"internalType\":\"uint8\",\"name\":\"\",\"type\":\"uint8\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTokenBound\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"getTokenBounds\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"isTokenBound\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"isTokenSelfBindingApproved\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"forwarder\",\"type\":\"address\"}],\"name\":\"isTrustedForwarder\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"maxRules\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint8\",\"name\":\"restrictionCode\",\"type\":\"uint8\"}],\"name\":\"messageForTransferRestriction\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"owner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"pendingOwner\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IRule\",\"name\":\"rule_\",\"type\":\"address\"}],\"name\":\"removeRule\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"renounceOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"ruleId\",\"type\":\"uint256\"}],\"name\":\"rule\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"rules\",\"outputs\":[{\"internalType\":\"address[]\",\"name\":\"\",\"type\":\"address[]\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"rulesCount\",\"outputs\":[{\"internalType\":\"uint256\",\"name\":\"\",\"type\":\"uint256\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"maxRules_\",\"type\":\"uint256\"}],\"name\":\"setMaxRules\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"contract IRule[]\",\"name\":\"rules_\",\"type\":\"address[]\"}],\"name\":\"setRules\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"},{\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"setTokenSelfBindingApproval\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"tokens\",\"type\":\"address[]\"},{\"internalType\":\"bool\",\"name\":\"approved\",\"type\":\"bool\"}],\"name\":\"setTokenSelfBindingApprovalBatch\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"bytes4\",\"name\":\"interfaceId\",\"type\":\"bytes4\"}],\"name\":\"supportsInterface\",\"outputs\":[{\"internalType\":\"bool\",\"name\":\"\",\"type\":\"bool\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"newOwner\",\"type\":\"address\"}],\"name\":\"transferOwnership\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"spender\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"transferred\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"internalType\":\"address\",\"name\":\"to\",\"type\":\"address\"},{\"internalType\":\"uint256\",\"name\":\"value\",\"type\":\"uint256\"}],\"name\":\"transferred\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"trustedForwarder\",\"outputs\":[{\"internalType\":\"address\",\"name\":\"\",\"type\":\"address\"}],\"stateMutability\":\"view\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address\",\"name\":\"token\",\"type\":\"address\"}],\"name\":\"unbindToken\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"address[]\",\"name\":\"tokens\",\"type\":\"address[]\"}],\"name\":\"unbindTokens\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[],\"name\":\"version\",\"outputs\":[{\"internalType\":\"string\",\"name\":\"version_\",\"type\":\"string\"}],\"stateMutability\":\"view\",\"type\":\"function\"}],\"devdoc\":{\"details\":\"{RuleEngineOwnable2Step} plus an immutable trusted forwarder: administrative calls (owner-only functions) may be relayed by the forwarder (gasless transactions). Token identity is never resolved through the forwarder: the bound-token gate and token self-binding compare the raw `msg.sender`.\",\"errors\":{\"OwnableInvalidOwner(address)\":[{\"details\":\"The owner is not a valid owner account. (eg. `address(0)`)\"}],\"OwnableUnauthorizedAccount(address)\":[{\"details\":\"The caller account is not authorized to perform an operation.\"}]},\"events\":{\"AddRule(address)\":{\"params\":{\"rule\":\"The address of the rule contract that was added.\"}},\"RemoveRule(address)\":{\"params\":{\"rule\":\"The address of the rule contract that was removed.\"}},\"SetMaxRules(uint256)\":{\"params\":{\"maxRules\":\"The new rule cap.\"}},\"TokenBound(address)\":{\"details\":\"Same declaration as ERC-3643 `TokenBound(address _token)`, which does not index the token. Keep it non-indexed: `indexed` would move `token` from the data to a topic and break consumers decoding with the standard ERC-3643 ABI.\",\"params\":{\"token\":\"The address of the token that was bound.\"}},\"TokenSelfBindingApprovalBatchSet(address[],bool)\":{\"details\":\"`tokens` is the array as passed: it may contain tokens already at `approved` and duplicates, and is empty for an empty batch, so it lists the tokens that were set, not only those that changed. No {TokenSelfBindingApprovalSet} is emitted per token, so a filter on that event's indexed `token` does not see batch updates. `tokens` is not indexed: an indexed array is stored as a hash and cannot be filtered per token.\",\"params\":{\"approved\":\"True if token self-bind/unbind is allowed, false otherwise.\",\"tokens\":\"The token addresses whose self-binding permission was set, as passed to the call.\"}},\"TokenSelfBindingApprovalSet(address,bool)\":{\"details\":\"Emitted on every call, also when `approved` equals the current value. Not emitted by {setTokenSelfBindingApprovalBatch}, which emits {TokenSelfBindingApprovalBatchSet} instead: a consumer reconstructing the approvals, or filtering on `token`, must handle both events, or read {isTokenSelfBindingApproved}, which is authoritative.\",\"params\":{\"approved\":\"True if token self-bind/unbind is allowed, false otherwise.\",\"token\":\"The token address whose self-binding permission was set.\"}},\"TokenUnbound(address)\":{\"details\":\"Same declaration as ERC-3643 `TokenUnbound(address _token)`; kept non-indexed for the same reason as {TokenBound}.\",\"params\":{\"token\":\"The address of the token that was unbound.\"}}},\"kind\":\"dev\",\"methods\":{\"acceptOwnership()\":{\"details\":\"Repeats the rule-account check of {transferOwnership}: an address nominated while it was not a rule, then added as a rule, cannot accept until it is removed from the rule set.\"},\"addRule(address)\":{\"details\":\"Reverts when the configured maximum number of rules is already reached. Security convention: do not grant {RULES_MANAGEMENT_ROLE} to rule contracts.\",\"params\":{\"rule_\":\"The IRule contract to add.\"}},\"bindToken(address)\":{\"custom:security-note\":\"\\\"Multi-tenant\\\" means one instance is shared by multiple token contracts. Downstream state (for the RuleEngine: the per-address accounting held by stateful rules) is shared across all bound tokens, so binding tokens from different issuers silently cross-contaminates it. Only bind tokens that are equally trusted and governed together.\",\"details\":\"Authorized by {_authorizeTokenBindingChange}.\",\"params\":{\"token\":\"The address of the token to bind.\"}},\"bindTokens(address[])\":{\"custom:security-note\":\"See {bindToken} for multi-tenant state risks. All tokens bound in this batch share the same downstream state. Only bind tokens that are equally trusted and governed together.\",\"details\":\"Must be restricted by implementation-specific access control. Atomic: reverts if any token is invalid or already bound (or listed twice), and then binds none of them. This deliberately departs from the usual batch convention of skipping elements already in the target state: a binding change is security-relevant, and a token that is already bound in the list is most likely an operator mistake that should stop the whole operation. An empty array is a no-op.\",\"params\":{\"tokens\":\"The token addresses to bind.\"}},\"canTransfer(address,address,uint256)\":{\"details\":\"Don't check the balance and the user's right (access control)\",\"params\":{\"from\":\"The address sending tokens.\",\"to\":\"The address receiving tokens.\",\"value\":\"The amount of tokens to transfer.\"},\"returns\":{\"_0\":\"True if the transfer is valid, false otherwise.\"}},\"canTransferFrom(address,address,address,uint256)\":{\"details\":\"Does not check balances or access rights (Access Control).\",\"params\":{\"from\":\"The source address.\",\"spender\":\"The address performing the transfer.\",\"to\":\"The destination address.\",\"value\":\"The number of tokens to transfer.\"},\"returns\":{\"_0\":\"isCompliant True if the transfer complies with policy.\"}},\"clearRules()\":{\"details\":\"After calling this function, no rules will remain set. Cost is O(n) in the number of configured rules. With the default cap of 10 this is negligible, but a high {maxRules} setting re-exposes unbounded cost here even though per-transfer cost remains bounded.\"},\"constructor\":{\"params\":{\"forwarderIrrevocable\":\"Address of the trusted ERC-2771 forwarder, immutable after construction.\",\"owner_\":\"Address of the initial contract owner (ERC-173).\",\"tokenContract\":\"Token to bind at deployment, or the zero address to bind none.\"}},\"containsRule(address)\":{\"details\":\"Complexity: O(1).\",\"params\":{\"rule_\":\"The IRule contract to check for membership.\"},\"returns\":{\"_0\":\"True if the rule is present, false otherwise.\"}},\"created(address,uint256)\":{\"details\":\"Called by the token contract when new tokens are issued to an account. Reverts if the minting does not comply with the rules.\",\"params\":{\"to\":\"The address receiving the minted tokens.\",\"value\":\"The number of tokens created.\"}},\"destroyed(address,uint256)\":{\"details\":\"Called by the token contract when tokens are redeemed or burned. Reverts if the burning does not comply with the rules.\",\"params\":{\"from\":\"The address whose tokens are being destroyed.\",\"value\":\"The number of tokens destroyed.\"}},\"detectTransferRestriction(address,address,uint256)\":{\"params\":{\"from\":\"the origin address\",\"to\":\"the destination address\",\"value\":\"to transfer\"},\"returns\":{\"_0\":\"The restriction code or REJECTED_CODE_BASE.TRANSFER_OK (0) if the transfer is valid\"}},\"detectTransferRestrictionFrom(address,address,address,uint256)\":{\"details\":\" See {ERC-1404} Add an additionnal argument `spender` This function is where an issuer enforces the restriction logic of their token transfers. Some examples of this might include: - checking if the token recipient is whitelisted, - checking if a sender's tokens are frozen in a lock-up period, etc.\",\"params\":{\"from\":\"The address sending tokens.\",\"spender\":\"The address initiating the delegated transfer.\",\"to\":\"The address receiving tokens.\",\"value\":\"amount of tokens to transfer\"},\"returns\":{\"_0\":\"uint8 restricted code, 0 means the transfer is authorized\"}},\"getTokenBound()\":{\"details\":\"If multiple tokens are supported, consider using getTokenBounds().\",\"returns\":{\"_0\":\"The address of the currently bound token.\"}},\"getTokenBounds()\":{\"details\":\"This operation copies the entire storage set to memory and is mainly intended for off-chain reads.\",\"returns\":{\"_0\":\"An array of bound token addresses.\"}},\"isTokenBound(address)\":{\"details\":\"Complexity: O(1).\",\"params\":{\"token\":\"The token address to verify.\"},\"returns\":{\"_0\":\"True if the token is bound, false otherwise.\"}},\"isTokenSelfBindingApproved(address)\":{\"params\":{\"token\":\"The token address to query.\"},\"returns\":{\"_0\":\"True if self-binding is approved for `token`, false otherwise.\"}},\"isTrustedForwarder(address)\":{\"details\":\"Indicates whether any particular address is the trusted forwarder.\"},\"maxRules()\":{\"returns\":{\"_0\":\"The maximum number of rules that can be configured.\"}},\"messageForTransferRestriction(uint8)\":{\"details\":\"See {ERC-1404} This function is effectively an accessor for the \\\"message\\\", a human-readable explanation as to why a transaction is restricted.\",\"params\":{\"restrictionCode\":\"The restriction code to translate into a message.\"},\"returns\":{\"_0\":\"The human-readable message corresponding to `restrictionCode`.\"}},\"owner()\":{\"details\":\"Returns the address of the current owner.\"},\"pendingOwner()\":{\"details\":\"Returns the address of the pending owner.\"},\"removeRule(address)\":{\"details\":\"Reverts if the provided rule is not found or does not match the stored rule at its index. Complexity: O(1).\",\"params\":{\"rule_\":\"The IRule contract to remove.\"}},\"renounceOwnership()\":{\"details\":\"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner.\"},\"rule(uint256)\":{\"details\":\"Reverts if `ruleId` is out of bounds. Complexity: O(1). Note that there are no guarantees on the ordering of values inside the array, and it may change when more values are added or removed.\",\"params\":{\"ruleId\":\"The index of the desired rule in the array.\"},\"returns\":{\"_0\":\"The address of the corresponding IRule contract, return the `zero address` is out of bounds.\"}},\"rules()\":{\"details\":\"This is a view-only function that does not modify state. This operation will copy the entire storage to memory, which can be quite expensive. This is designed to mostly be used by view accessors that are queried without any gas fees.\",\"returns\":{\"_0\":\"An array of all active rule contract addresses.\"}},\"rulesCount()\":{\"details\":\"Equivalent to the length of the internal rules array. Complexity: O(1)\",\"returns\":{\"_0\":\"The number of active rules.\"}},\"setMaxRules(uint256)\":{\"details\":\"Access control is implementation specific (admin/owner). Setting a very high cap re-exposes unbounded gas cost for administrative operations such as {clearRules} even though normal per-transfer cost remains bounded.\",\"params\":{\"maxRules_\":\"New maximum number of rules.\"}},\"setRules(address[])\":{\"details\":\"Replaces the entire rule set atomically. Reverts if `rules_` is empty. Use {clearRules} to remove all rules explicitly. To transition from one non-empty set to another without an enforcement gap, call this function directly with the new set. Emits {ClearRules} when the existing rule set is non-empty, then emits {AddRule} for each new rule. Off-chain indexers must handle both events to reconstruct state. Security convention: rule contracts should be treated as trusted business logic, but should not also be granted {RULES_MANAGEMENT_ROLE}.\",\"params\":{\"rules_\":\"The array of addresses representing the new rules to be set.\"}},\"setTokenSelfBindingApproval(address,bool)\":{\"details\":\"Must be restricted by implementation-specific access control. An approval stays in force until it is revoked here or until the binding manager unbinds the token ({unbindToken} or {unbindTokens}), which revokes it and emits {TokenSelfBindingApprovalSet} with `false`. A token that unbinds itself keeps its approval, so it can bind itself again later.\",\"params\":{\"approved\":\"Whether self-binding is approved for `token`.\",\"token\":\"The token address to configure.\"}},\"setTokenSelfBindingApprovalBatch(address[],bool)\":{\"details\":\"Must be restricted by implementation-specific access control. Reverts if any token in `tokens` is the zero address. Emits a single {TokenSelfBindingApprovalBatchSet} with the input array, not one {TokenSelfBindingApprovalSet} per token.\",\"params\":{\"approved\":\"Whether self-binding is approved for all provided tokens.\",\"tokens\":\"The token addresses to configure.\"}},\"supportsInterface(bytes4)\":{\"params\":{\"interfaceId\":\"The interface identifier to check.\"},\"returns\":{\"_0\":\"True if the interface is supported, false otherwise.\"}},\"transferOwnership(address)\":{\"details\":\"Reverts when `newOwner` is already configured as a rule.\",\"params\":{\"newOwner\":\"The address of the new owner.\"}},\"transferred(address,address,address,uint256)\":{\"details\":\"Must revert if the transfer is invalid Same name as ERC-3643 but with one supplementary argument `spender` This function can be used to update state variables of the RuleEngine contract This function can be called ONLY by the token contract bound to the RuleEngine Which overload the token calls (since CMTAT v3.3.0): - this 4-argument overload for `transferFrom` (`spender` = approved spender) and for every operation initiated by an operator, with the operator as `spender`: mint (`from == address(0)`), burn (`to == address(0)`), including `burnFrom`, self-burn and cross-chain mint/burn, and the minter `batchTransfer`; - the 3-argument ERC-3643 overload `transferred(from, to, value)`, inherited from {IERC3643IComplianceContract}, only for a direct `transfer`. Up to CMTAT v3.2.0, mint, burn and the minter transfer used the 3-argument overload. WARNING - zero-value calls are permissionless. ERC-20 requires transfers of `0` to be treated as normal transfers, and OpenZeppelin's `_spendAllowance` consumes no allowance when `value == 0`. Any address can therefore call `transferFrom(victim, anyone, 0)` on the token and reach this callback for an arbitrary `from`, with itself as `spender`, without ever having been approved. The token deliberately does not suppress the notification, because doing so would make its compliance notifications inconsistent with its own ERC-20 transfer semantics. Implementations MUST therefore treat `value == 0` as carrying no economic meaning: any stateful rule (cooldown, holding period, quota, tax bucket, counter, holder tracking, ...) MUST be a no-op for a zero value, otherwise an attacker can desynchronize policy state from balances, or keep a holder permanently restricted, at no cost. The same applies to the 3-argument ERC-3643 overload, which a zero-value `transfer(to, 0)` reaches the same way.\",\"params\":{\"from\":\"token holder address\",\"spender\":\"spender address (sender)\",\"to\":\"receiver address\",\"value\":\"value of tokens involved in the transfer; MAY be `0` \\u2014 see the warning above\"}},\"transferred(address,address,uint256)\":{\"details\":\" This function can be used to update state variables of the compliance contract This function can be called ONLY by the token contract bound to the compliance\",\"params\":{\"from\":\"The address of the sender\",\"to\":\"The address of the receiver\",\"value\":\"value of tokens involved in the transfer\"}},\"trustedForwarder()\":{\"details\":\"Returns the address of the trusted forwarder.\"},\"unbindToken(address)\":{\"details\":\"Authorized by {_authorizeTokenBindingChange}. Operator warning: unbinding is an administrative operation and does not erase any state already stored downstream in a previously shared (\\\"multi-tenant\\\") setup.\",\"params\":{\"token\":\"The address of the token to unbind.\"}},\"unbindTokens(address[])\":{\"details\":\"Must be restricted by implementation-specific access control. Atomic: reverts if any token is not currently bound, and then unbinds none of them. Deliberately not the skip-if-already-done batch convention, for the same reason as {bindTokens}. An empty array is a no-op. Like a manager's {unbindToken}, revokes each token's self-binding approval (see {setTokenSelfBindingApproval}).\",\"params\":{\"tokens\":\"The token addresses to unbind.\"}},\"version()\":{\"details\":\"This value is useful to know which smart contract version has been used\",\"returns\":{\"version_\":\"A string representing the version of the token implementation (e.g., \\\"1.0.0\\\").\"}}},\"title\":\"Implementation of a ruleEngine with ERC-173 Ownable2Step access control and ERC-2771\",\"version\":1},\"userdoc\":{\"errors\":{\"TokenBinding_InvalidTokenAddress()\":[{\"notice\":\"Thrown when the zero address is passed as a token to bind or to approve.\"}],\"TokenBinding_TokenAlreadyBound()\":[{\"notice\":\"Thrown when binding a token that is already bound.\"}],\"TokenBinding_TokenNotBound()\":[{\"notice\":\"Thrown when unbinding a token that is not currently bound.\"}],\"TokenBinding_UnauthorizedCaller()\":[{\"notice\":\"Thrown when a caller that is not a bound token calls a bound-token entry point.\"}]},\"events\":{\"AddRule(address)\":{\"notice\":\"Emitted when a new rule is added to the rule set.\"},\"ClearRules()\":{\"notice\":\"Emitted when all rules are cleared from the rule set.\"},\"RemoveRule(address)\":{\"notice\":\"Emitted when a rule is removed from the rule set.\"},\"SetMaxRules(uint256)\":{\"notice\":\"Emitted when the maximum allowed number of rules is updated.\"},\"TokenBound(address)\":{\"notice\":\"Emitted when a token is successfully bound.\"},\"TokenSelfBindingApprovalBatchSet(address[],bool)\":{\"notice\":\"Emitted once by {setTokenSelfBindingApprovalBatch}, with the input array.\"},\"TokenSelfBindingApprovalSet(address,bool)\":{\"notice\":\"Emitted by {setTokenSelfBindingApproval} when self-binding permission is set for a token.\"},\"TokenUnbound(address)\":{\"notice\":\"Emitted when a token is successfully unbound.\"}},\"kind\":\"user\",\"methods\":{\"DEFAULT_MAX_RULES()\":{\"notice\":\"Default upper bound on the number of rules a RuleEngine may hold.\"},\"acceptOwnership()\":{\"notice\":\"Completes the ownership transfer; callable by the pending owner only.\"},\"addRule(address)\":{\"notice\":\"Adds a new rule to the current rule set.\"},\"bindToken(address)\":{\"notice\":\"Binds a token contract, allowing it to call the bound-token entry points.\"},\"bindTokens(address[])\":{\"notice\":\"Binds several token contracts in a single call.\"},\"canTransfer(address,address,uint256)\":{\"notice\":\"Returns true if the transfer is valid, and false otherwise.\"},\"canTransferFrom(address,address,address,uint256)\":{\"notice\":\"Checks if `spender` can transfer `value` tokens from `from` to `to` under compliance rules.\"},\"clearRules()\":{\"notice\":\"Removes all configured rules.\"},\"constructor\":{\"notice\":\"Deploys a RuleEngine with ERC-173 Ownable2Step access control and a trusted forwarder.\"},\"containsRule(address)\":{\"notice\":\"Checks whether a specific rule is currently configured.\"},\"created(address,uint256)\":{\"notice\":\"Updates the compliance contract state when tokens are created (minted).\"},\"destroyed(address,uint256)\":{\"notice\":\"Updates the compliance contract state when tokens are destroyed (burned).\"},\"detectTransferRestriction(address,address,uint256)\":{\"notice\":\"Queries every rule, in order, and returns the first restriction code that is not zero\"},\"detectTransferRestrictionFrom(address,address,address,uint256)\":{\"notice\":\"Returns a uint8 code to indicate if a transfer is restricted or not\"},\"getTokenBound()\":{\"notice\":\"Returns the single token currently bound to this compliance contract.\"},\"getTokenBounds()\":{\"notice\":\"Returns all tokens currently bound.\"},\"isTokenBound(address)\":{\"notice\":\"Checks whether a token is currently bound.\"},\"isTokenSelfBindingApproved(address)\":{\"notice\":\"Returns whether a token is approved to bind and unbind itself.\"},\"maxRules()\":{\"notice\":\"Returns the maximum number of rules allowed in the engine.\"},\"removeRule(address)\":{\"notice\":\"Removes a specific rule from the current rule set.\"},\"rule(uint256)\":{\"notice\":\"Retrieves the rule address at a specific index.\"},\"rules()\":{\"notice\":\"Returns the full list of currently configured rules.\"},\"rulesCount()\":{\"notice\":\"Returns the total number of currently configured rules.\"},\"setMaxRules(uint256)\":{\"notice\":\"Updates the maximum number of rules allowed in the engine.\"},\"setRules(address[])\":{\"notice\":\"Defines the rules for the rule engine.\"},\"setTokenSelfBindingApproval(address,bool)\":{\"notice\":\"Sets whether a token is allowed to bind and unbind itself.\"},\"setTokenSelfBindingApprovalBatch(address[],bool)\":{\"notice\":\"Sets self-binding approval for multiple tokens in one transaction.\"},\"supportsInterface(bytes4)\":{\"notice\":\"ERC-165 interface detection.\"},\"transferOwnership(address)\":{\"notice\":\"Starts ownership transfer to `newOwner`.\"},\"transferred(address,address,address,uint256)\":{\"notice\":\"Function called whenever tokens are transferred from one wallet to another, minted or burned, when the token knows the account that initiated the operation (`spender`).\"},\"transferred(address,address,uint256)\":{\"notice\":\"Function called whenever tokens are transferred from one wallet to another\"},\"unbindToken(address)\":{\"notice\":\"Unbinds a token contract, revoking its access to the bound-token entry points.\"},\"unbindTokens(address[])\":{\"notice\":\"Unbinds several token contracts in a single call.\"},\"version()\":{\"notice\":\"Returns the current version of the token contract.\"}},\"version\":1}},\"settings\":{\"compilationTarget\":{\"src/deployment/ownable/RuleEngineOwnable2Step2771.sol\":\"RuleEngineOwnable2Step2771\"},\"evmVersion\":\"osaka\",\"libraries\":{},\"metadata\":{\"bytecodeHash\":\"ipfs\"},\"optimizer\":{\"enabled\":true,\"runs\":200},\"remappings\":[\":@chainlink/contracts-ccip/=lib/Rules/lib/chainlink-ace/node_modules/@chainlink/contracts-ccip/chains/evm/contracts/\",\":@chainlink/contracts/=lib/Rules/lib/chainlink-ace/node_modules/@chainlink/contracts/\",\":@chainlink/contracts@1.4.0/=lib/Rules/lib/chainlink-doc/node_modules/@chainlink/contracts-1.4.0/\",\":@chainlink/cross-chain-identity/=lib/Rules/lib/chainlink-ace/packages/cross-chain-identity/src/\",\":@chainlink/local/=lib/Rules/lib/chainlink-doc/node_modules/@chainlink/local/\",\":@chainlink/policy-management/=lib/Rules/lib/chainlink-ace/packages/policy-management/src/\",\":@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/\",\":@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/\",\":@openzeppelin/contracts@4.7.3/=lib/Rules/lib/chainlink-doc/node_modules/@openzeppelin/contracts-4.7.3/\",\":@openzeppelin/contracts@4.8.3/=lib/Rules/lib/chainlink-ace/node_modules/@openzeppelin/contracts-4.8.3/\",\":@openzeppelin/contracts@4.9.6/=lib/Rules/lib/chainlink-doc/node_modules/@openzeppelin/contracts-4.9.6/\",\":@openzeppelin/contracts@5.0.2/=lib/Rules/lib/chainlink-ace/node_modules/@openzeppelin/contracts/\",\":@openzeppelin/contracts@5.1.0/=lib/Rules/lib/chainlink-doc/node_modules/@openzeppelin/contracts-5.1.0/\",\":@openzeppelin/contracts@5.3.0/=lib/Rules/lib/chainlink-ace/node_modules/@openzeppelin/contracts-5.3.0/\",\":CMTAT/=lib/CMTAT/contracts/\",\":CMTATv3.0.0/=lib/CMTATv3.0.0/contracts/\",\":ERC-3643/=lib/ERC-3643/contracts/\",\":ERC3643/=lib/Rules/lib/ERC-3643/contracts/\",\":RuleEngine/=lib/Rules/lib/RuleEngine/\",\":Rules/=lib/Rules/\",\":chainlink-ace/=lib/Rules/lib/chainlink-ace/\",\":chainlink-doc/=lib/Rules/lib/\",\":erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/\",\":forge-std/=lib/forge-std/src/\",\":halmos-cheatcodes/=lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/\",\":openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/\",\":openzeppelin-contracts/=lib/openzeppelin-contracts/\"]},\"sources\":{\"lib/CMTAT/contracts/interfaces/engine/IRuleEngine.sol\":{\"keccak256\":\"0xeda899e2e46a9b9c3516acb61a7f7e92ed098928379010655c330da721aaffa7\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://60f8555330fc531dff7d0d71a862696fb286a0ba3290e41efbbbf4dd25947a3c\",\"dweb:/ipfs/QmWvbsBGWPtNMNN2EEedwdzzvQG7NtSj9VD2fmNgqVtCXN\"]},\"lib/CMTAT/contracts/interfaces/technical/IERC5679.sol\":{\"keccak256\":\"0x5bee30750c9a65438469a6c5bd8465e1603eec3aeeb94c07bd64ba3e9ee766e1\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://ef7a5c5f0d47135c97ab5d7456d31e513a71c849ae7f2f5395f860be125c4fbc\",\"dweb:/ipfs/Qmezem3qqSjij6ggyB34wC2S15KrY9fu42oymyS9epAYCQ\"]},\"lib/CMTAT/contracts/interfaces/tokenization/IERC3643Partial.sol\":{\"keccak256\":\"0x5c84c2e2442824e98625c471482fb3c9502f43f4c345e7c0fb07fa549be02e26\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://19071f2d12fb580d37eeee07885461f193568df34f3f69d2c5d65ce655d84435\",\"dweb:/ipfs/QmRqHwC7LksE3YPohMtxFieiPerhWdoDNUUMMLbB4XYvhK\"]},\"lib/CMTAT/contracts/interfaces/tokenization/draft-IERC1404.sol\":{\"keccak256\":\"0xc27cdac182d930a94391d589bdafa15364b6f8d9bf211175781dba661f1c0336\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://b509fa7f3cfd785632569f6ae3bec846aa0beefd73c1d5bde233440cae919f0f\",\"dweb:/ipfs/QmPCAdiEun8gaMqS8KhwPpRZV2zXAPfURRaF4C2KjX5Kby\"]},\"lib/CMTAT/contracts/interfaces/tokenization/draft-IERC7551.sol\":{\"keccak256\":\"0x84b73eb77ec82d6d7b313eff2d87f58d3b795840d004aaa10c611b360b827e30\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://a5b8c99fb3600369065a422d3821ba441dc06fc64f50ce0f33950a76ad82b51b\",\"dweb:/ipfs/QmbviJsZPY3xuLU3cHUWJx11aJCPAuN4WKnCufN4kVLm2U\"]},\"lib/CMTAT/contracts/interfaces/tokenization/draft-IERC7943.sol\":{\"keccak256\":\"0xc69588a72da81057ee278e961e8e3bb61a28d64c3c6cebe494ce00809c1cef15\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://148f117d9c463de441f81e6c0a67e95f1f14a61db209492dd0a1767b5572f21a\",\"dweb:/ipfs/QmUjT5uyJfNSYgUWn5Dxhf6Sx9Y1z8CNf3PuTEaGoAx3za\"]},\"lib/CMTAT/contracts/library/ERC1404ExtendInterfaceId.sol\":{\"keccak256\":\"0xf8268f4eb3a6b2e26c32cf76c5c76b6c17df3385c150f05953538a2472149247\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://05108de7a7ba2a0a67978bdfe8e500360674db6d894f42970bb1016b36639056\",\"dweb:/ipfs/QmRux9Qj1GomATseS6Tyq9uiPPNNipuxg2HjdjnPjgSQds\"]},\"lib/CMTAT/contracts/library/RuleEngineInterfaceId.sol\":{\"keccak256\":\"0x1152a49cba4232d943e295d259eb8a1b216d815067367410a5729a256dae4051\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://470f4435a5e62b0ba0ad70f8657b2db0e4cc3b7f2561772adb944ce010551ee6\",\"dweb:/ipfs/QmXECahRr8rK9XJPZwBCnemLDVPdFvPEBusezhaBqbLBqp\"]},\"lib/openzeppelin-contracts/contracts/access/Ownable.sol\":{\"keccak256\":\"0xff6d0bb2e285473e5311d9d3caacb525ae3538a80758c10649a4d61029b017bb\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://8ed324d3920bb545059d66ab97d43e43ee85fd3bd52e03e401f020afb0b120f6\",\"dweb:/ipfs/QmfEckWLmZkDDcoWrkEvMWhms66xwTLff9DDhegYpvHo1a\"]},\"lib/openzeppelin-contracts/contracts/access/Ownable2Step.sol\":{\"keccak256\":\"0xdcad8898fda432696597752e8ec361b87d85c82cb258115427af006dacf7128c\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://e2c9d517f0c136d54bd00cd57959d25681d4d6273f5bbbc263afe228303772f0\",\"dweb:/ipfs/QmReNFjXBiufByiAAzfSQ2SM5r3qeUErn46BmN3yVRvrek\"]},\"lib/openzeppelin-contracts/contracts/interfaces/IERC165.sol\":{\"keccak256\":\"0x0afcb7e740d1537b252cb2676f600465ce6938398569f09ba1b9ca240dde2dfc\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://1c299900ac4ec268d4570ecef0d697a3013cd11a6eb74e295ee3fbc945056037\",\"dweb:/ipfs/Qmab9owJoxcA7vJT5XNayCMaUR1qxqj1NDzzisduwaJMcZ\"]},\"lib/openzeppelin-contracts/contracts/metatx/ERC2771Context.sol\":{\"keccak256\":\"0x9695d220b99dcf62910533bdf5d40d4cf6a4e04d5b106b6803a80586486dc7f7\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://83b7aecd65882d8953643dce144efe91367082cc01830c9c4ed3c8a4837fb558\",\"dweb:/ipfs/QmQ5HxGavcCKjuhd8buv177qjG6A4kvxx4pZviceKdspdM\"]},\"lib/openzeppelin-contracts/contracts/utils/Arrays.sol\":{\"keccak256\":\"0x772f0c778626a7bdcbcbabca74b825ae9b9dc89d2a47a98b402b1187fbaa63a4\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://eba1d46e58e8880b45c6d51245dc94585b81d6d7290ca77ef50037a6193ed301\",\"dweb:/ipfs/Qme3CWun5qQACjGEerT2MCvhs6brKGFfJirGnzV1ypKTXA\"]},\"lib/openzeppelin-contracts/contracts/utils/Comparators.sol\":{\"keccak256\":\"0x302eecd8cf323b4690e3494a7d960b3cbce077032ab8ef655b323cdd136cec58\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://49ba706f1bc476d68fe6c1fad75517acea4e9e275be0989b548e292eb3a3eacd\",\"dweb:/ipfs/QmeBpvcdGWzWMKTQESUCEhHgnEQYYATVwPxLMxa6vMT7jC\"]},\"lib/openzeppelin-contracts/contracts/utils/Context.sol\":{\"keccak256\":\"0x493033a8d1b176a037b2cc6a04dad01a5c157722049bbecf632ca876224dd4b2\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://6a708e8a5bdb1011c2c381c9a5cfd8a9a956d7d0a9dc1bd8bcdaf52f76ef2f12\",\"dweb:/ipfs/Qmax9WHBnVsZP46ZxEMNRQpLQnrdE4dK8LehML1Py8FowF\"]},\"lib/openzeppelin-contracts/contracts/utils/Panic.sol\":{\"keccak256\":\"0xf7fe324703a64fc51702311dc51562d5cb1497734f074e4f483bfb6717572d7a\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c6a5ff4f9fd8649b7ee20800b7fa387d3465bd77cf20c2d1068cd5c98e1ed57a\",\"dweb:/ipfs/QmVSaVJf9FXFhdYEYeCEfjMVHrxDh5qL4CGkxdMWpQCrqG\"]},\"lib/openzeppelin-contracts/contracts/utils/SlotDerivation.sol\":{\"keccak256\":\"0x94045fd4f268edf2b2d01ef119268548c320366d6f5294ad30c1b8f9d4f5225f\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://edfda81f426f8948b3834115c21e83c48180e6db0d2a8cd2debb2185ed349337\",\"dweb:/ipfs/QmdYZneFyDAux1BuWQxLAdqtABrGS2k9WYCa7C9dvpKkWv\"]},\"lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol\":{\"keccak256\":\"0xcf74f855663ce2ae00ed8352666b7935f6cddea2932fdf2c3ecd30a9b1cd0e97\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://9f660b1f351b757dfe01438e59888f31f33ded3afcf5cb5b0d9bf9aa6f320a8b\",\"dweb:/ipfs/QmarDJ5hZEgBtCmmrVzEZWjub9769eD686jmzb2XpSU1cM\"]},\"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol\":{\"keccak256\":\"0x2d9dc2fe26180f74c11c13663647d38e259e45f95eb88f57b61d2160b0109d3e\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://81233d1f98060113d9922180bb0f14f8335856fe9f339134b09335e9f678c377\",\"dweb:/ipfs/QmWh6R35SarhAn4z2wH8SU456jJSYL2FgucfTFgbHJJN4E\"]},\"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165Checker.sol\":{\"keccak256\":\"0x7c7ad70641a7f8cd44def0857ec97b0e40bfd073b2d6037a5f57ce9527ee9bc5\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://e05c6572dfe769f7aea6f3a8002951cc12d143d980dad29f6c5feedf9408bc14\",\"dweb:/ipfs/QmXM7C8YEptxisZiEefXUrwdXt3zMaCobmkCchxTtDg1oK\"]},\"lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol\":{\"keccak256\":\"0x8891738ffe910f0cf2da09566928589bf5d63f4524dd734fd9cedbac3274dd5c\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://971f954442df5c2ef5b5ebf1eb245d7105d9fbacc7386ee5c796df1d45b21617\",\"dweb:/ipfs/QmadRjHbkicwqwwh61raUEapaVEtaLMcYbQZWs9gUkgj3u\"]},\"lib/openzeppelin-contracts/contracts/utils/math/Math.sol\":{\"keccak256\":\"0x59973a93b1f983f94e10529f46ca46544a9fec2b5f56fb1390bbe9e0dc79f857\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://c55ef8f0b9719790c2ae6f81d80a59ffb89f2f0abe6bc065585bd79edce058c5\",\"dweb:/ipfs/QmNNmCbX9NjPXKqHJN8R1WC2rNeZSQrPZLd6FF6AKLyH5Y\"]},\"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol\":{\"keccak256\":\"0xc8cae21c9ae4a46e5162ff9bf5b351d6fa6a6eba72d515f3bc1bdfeda7fdf083\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://ce830ebcf28e31643caba318996db3763c36d52cd0f23798ba83c135355d45e9\",\"dweb:/ipfs/QmdGPcvptHN7UBCbUYBbRX3hiRVRFLRwno8b4uga6uFNif\"]},\"lib/openzeppelin-contracts/contracts/utils/structs/EnumerableSet.sol\":{\"keccak256\":\"0xd553ff8b7d55679f0711f1598600ac292dbd8cfdf4b2419b9cabe4c931172895\",\"license\":\"MIT\",\"urls\":[\"bzz-raw://7905ccb27e2308fd0d90dc1212161003ab6964e1c176593db1ccedef705bcc09\",\"dweb:/ipfs/QmW37vm2PcrWLKnN74sKkvAzqSwntCEfCp4EoSEvbBHWkj\"]},\"src/RuleEngineBase.sol\":{\"keccak256\":\"0xb3d832fa55b615574d80b0e0ad76620ad236aa046523617ed5daa46ae07bf853\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://7be31bf5dbd3fa1be025cdc4b7674b76bf40e1c14ce89ec78f792cb3d7ed804e\",\"dweb:/ipfs/QmPq4xBiB3XwXerWtuonZLGiWHMqvz5tKvjhTh9AiWkbww\"]},\"src/RuleEngineOwnableShared.sol\":{\"keccak256\":\"0xa78493398d8b0554e72def7f14d7439109bd4dbd5e07f1466b40acea2bb7dc02\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://ebd87d69b4f6eb193c5d03476381ac132f9587248422d3306dda95b79fd4e470\",\"dweb:/ipfs/QmWYDLvPWjRcfxdR2KhXAij8U9TrFjeM77fsJRX25jWQmY\"]},\"src/deployment/ownable/RuleEngineOwnable2Step.sol\":{\"keccak256\":\"0xf8d7f52cf7857f0d89adeb7dfa42444dbaf371dd6cca712c797181baf7a3fe97\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://f3307f7a2800dfc1b23c89cf6eebcbf21fd283eeb19343a374bc5bc771b7a4ef\",\"dweb:/ipfs/QmbFjoQ97zF74QCWwbswVwKL7wB1Gx4pfRdu7jp2vE36DB\"]},\"src/deployment/ownable/RuleEngineOwnable2Step2771.sol\":{\"keccak256\":\"0x1980b872a8d8fac8e37bf8d032ef7a6b01d205abb8723b8b0b18ba64ed566e94\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://031a2672f52384fc76b123bcec8a6b86d5c70607920ea3d347326275652cf482\",\"dweb:/ipfs/QmXLwxAmpXJmjcwMrLuJKnnPkZMHrqg9bPcLJ1jupsKF2x\"]},\"src/interfaces/IERC3643Compliance.sol\":{\"keccak256\":\"0xd0edd6697d67135853576ac6a40cadaffd787cedea98071708bbfb189c7ee5bc\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://4ed3cd3af64fccff17a1f33989cdfbdacbc0e4f32a56de11a072cf9e2277a1f6\",\"dweb:/ipfs/QmenRqRw1Yy39yDv1pJgBmnHtwuZhDdHE4omchL41CjXjb\"]},\"src/interfaces/IERC3643ComplianceExtended.sol\":{\"keccak256\":\"0x4a43bf330c7a904cba110acf52f519718d8409514c377912d5bd063c9d963729\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://c671879c591760ecbc2691e2f24adfb215a658c9fe6eb0c05dd1ca980054e585\",\"dweb:/ipfs/QmdbA19PFpJgHraF46YrcMNzUgswbTRA92atL2Lha63JLY\"]},\"src/interfaces/IRule.sol\":{\"keccak256\":\"0x81580b67f7be09049aa64d93cc1d8d691a87c639adc1cf169dc6073e1e543a5c\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://6f1808c3ed18ef1acbccdd9b30011b6e7220d388cfd66cba40b1ef0b485306a1\",\"dweb:/ipfs/QmcUCQ5MYcf7KTtoeqMKsTutPPSJhNTaK1ntHV21ioS9Fm\"]},\"src/interfaces/IRulesManagementModule.sol\":{\"keccak256\":\"0x082dd58070e83b02f275584afa872c4583ac4ca8ad12eb329fc11301470147f9\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://e2d0ad78dc323881864f406acd44976f5de39cdc97a6c99a724d8458b993e2e2\",\"dweb:/ipfs/QmRFfMbXbdiAYV3vQyNppXG7tHTji6mV1Y5Cu3ZzEQm5ng\"]},\"src/interfaces/ITokenBinding.sol\":{\"keccak256\":\"0x34dfea4e118c966adf867c0899844515566251819b4e4510fd8ee424555493fd\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://1d054ed49874816688a6e71f76d611bbdefd492d122ae386cb804c6f5af677a7\",\"dweb:/ipfs/QmRaYX4aJWYSNWNa1D4Nich3k7hkGM9rTfc9s2XaVqyRjy\"]},\"src/interfaces/ITokenBindingExtended.sol\":{\"keccak256\":\"0x01f3ab56dffce860d03e72d10e9f2d13b6bfc9004cf058c63a0b23e3b226da99\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://521e0c9651632b70d61c4c3bd0b14c6f05d818166fe65dbed8e3253158b7637e\",\"dweb:/ipfs/QmY2xEVvfV1dgtFYw6coHX3Z7Fm7yRhzPaGyt6cYBMVf76\"]},\"src/modules/ERC2771ModuleStandalone.sol\":{\"keccak256\":\"0x2135408cd37646f3a27b4a2cdb6f1b9b622541fed4f4b6311a06f986f6eb75d1\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://82229782c9664a8c039fd5a3ecedca8a827fcec190be6c527c1236c864c0418f\",\"dweb:/ipfs/QmXQmX1BFFupTPB27uJweT1tSc6nce3JXDSDa9Ztpf6cKk\"]},\"src/modules/ERC3643ComplianceExtendedModule.sol\":{\"keccak256\":\"0x6f808b068517e9e15f09fc6a9d4190001ec8c2314a10e27a85a2d43e44c84fb1\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://c62c0b77fdd8b6e7bf7aa5bf8134a78ff024d6489a23f746874a99df38a8a265\",\"dweb:/ipfs/QmV7PG3ZUUzwDs9tpooC3hmBu5e39buJnJ4TRditojJ3hu\"]},\"src/modules/ERC3643ComplianceModule.sol\":{\"keccak256\":\"0x7cda81af8687328ac2089f9d1d78352e0e75d0f70a4ba8e2b3ac82896f22863f\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://50711cb94d69ea63d787a8bb19c38c0b99539029ec8fb957a8eff00880fc11fc\",\"dweb:/ipfs/QmSapDWh5mpvWn1q6JteZisJfVGPrCz47WP2BBrJCccEjV\"]},\"src/modules/RulesManagementModule.sol\":{\"keccak256\":\"0xe4d9425613284e71a5e3d590d5433167a9751d9496f57efa914baa81f493e66d\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://d07a16e6869df86c526ef89e7e359e34a9553dc4288b262abd2979359ecf720e\",\"dweb:/ipfs/QmRy2JEsyhkv1mxv7eFaSbEWN4A3gtpPSUnnV48W2KiV4u\"]},\"src/modules/TokenBindingExtendedModule.sol\":{\"keccak256\":\"0x4e1ca7b2ec78608c3a7960bec7102a1780bdf3ec7ff544b612bafaf738b34d05\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://657bcdd303fd5a7fbe733b283f69d8e8aa73efeeeaf95c0ae7479769ac573693\",\"dweb:/ipfs/QmXiWPrv8pEqvBQck8jxC7NwB1MUdGQfLjihK6etYcZ54j\"]},\"src/modules/TokenBindingModule.sol\":{\"keccak256\":\"0xf65f46311d0078f60c30e3359dca988e39cba45b9eee53a09d618bfa70e6ef9b\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://e8c458ecfd41df5fb4a391e7ef837fd5ed5c999e61ccc0e6b4bd23023a739832\",\"dweb:/ipfs/Qmdsr765aw9fPFN2M9cSCP69o1o41FNCqhrXjHgEXNwbXV\"]},\"src/modules/VersionModule.sol\":{\"keccak256\":\"0x35daf007be8b9bb1cb9196ae2decb3e5ad4b574f6390f8fc010b78796ac42f73\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://b1b29d75e1c5023a0c6cb8c56638a17d855a3fdc051a60b9d2f304b99f7876d2\",\"dweb:/ipfs/QmXSCVjLuViC8916LwNpKtw8hqyH78Ptag3xH1n7F1fY4g\"]},\"src/modules/library/ComplianceInterfaceId.sol\":{\"keccak256\":\"0xd54bed5328e732f753d2886aeaa2761b2d66536d5247d4548e0ac1c83c7a0dac\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://ad695339fdfe72446a69d2dfbe39373affe2f37299ad921e57016069a7bc3592\",\"dweb:/ipfs/QmWathGt3E85hLfy5rrAYdb291W8VoTa4gpGPoxtWGvNNA\"]},\"src/modules/library/ERC1404InterfaceId.sol\":{\"keccak256\":\"0x07dc6905e137096cd0ae88be29b112d0e54a83ddf8ca527a281718010f6abcce\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://9249dce67cb59432bdbc9e49978c6cac0346cda3d3fca97c5a310e0f424e1600\",\"dweb:/ipfs/QmRi5awH3hjwvd3k3td48y5Cf64n1wvX9wCWy6fQLayuKs\"]},\"src/modules/library/Ownable2StepInterfaceId.sol\":{\"keccak256\":\"0xe4c5bd8569553d93b7283118318993fea44410a608e7bda490ff27bc3e848f89\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://8145a588e30eb836199f489e16464123082cd2af9989c9aeca1038c69ac3da6f\",\"dweb:/ipfs/QmNrQJ2mQQjqx3UY86mKB2M1vCgLQakumumKxVhvqX6AhF\"]},\"src/modules/library/OwnableInterfaceId.sol\":{\"keccak256\":\"0xdbe06b3203e21e41d1fd2a3ef373a80727193443dfd981de6821422158015d4f\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://ebe8699ae8af81c5cd82f25a1609d9396d72ae957647c33aaa745aadcdac8d18\",\"dweb:/ipfs/QmV73gwDJPFthn8VspdYE6GsoAcQMAR7TachUK8YrPonuT\"]},\"src/modules/library/RuleEngineInvariantStorage.sol\":{\"keccak256\":\"0x50a212f09f1695662965e5fba643b42a1978bec2a8368abbf43983489c983096\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://6137f01df7630527c985d85d2f7446359c678fcb933b66c55b51f583757b5c4a\",\"dweb:/ipfs/QmeHo47WQm1V99xZHS4soMk68UdtXtZhtWhV3dQC5BtA7u\"]},\"src/modules/library/RuleInterfaceId.sol\":{\"keccak256\":\"0x0d86820eee4c92b21d6704bea8ce7bd2cc1b35f6e4a1ceabbcf2a10f1c6b02ec\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://cfb560cb8588983b8c79a973d03c214a149bf1ac034fa9130ce93f0031a404d7\",\"dweb:/ipfs/Qmc6qt4E4BHdDyLUegCsgxqhf7ZFUiX4ahj8FjM54V7wpY\"]},\"src/modules/library/RulesManagementModuleInvariantStorage.sol\":{\"keccak256\":\"0xb81ea3a54c6e8d47b87d6c3d9fb5aae80c3430021b8cd66d9adeef7f5fc95893\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://cfcbadc2011f60de7189273c278dda1df2218aeeb153bee3b8a93447ec95df21\",\"dweb:/ipfs/Qmem5FqCLEfBJQdJzS7Xzd3zSfyL8Muf9Wv5WvCiBVsqfh\"]},\"src/modules/library/TokenBindingModuleInvariantStorage.sol\":{\"keccak256\":\"0x9bab8e5b265068da356fd46e343a7c6c73776f3964fdeaeff056e8ce104d40a5\",\"license\":\"MPL-2.0\",\"urls\":[\"bzz-raw://e2e75d2d52b1e4f5cbb832d194266de9a1b3a8cc2101e875dce43a2664c31a05\",\"dweb:/ipfs/QmUsd5cTPsE89WKm3kTUWsobR9JsBDUY8NdxDU5RPYpvP6\"]}},\"version\":1}","metadata":{"compiler":{"version":"0.8.37+commit.f401782d"},"language":"Solidity","output":{"abi":[{"inputs":[{"internalType":"address","name":"owner_","type":"address"},{"internalType":"address","name":"forwarderIrrevocable","type":"address"},{"internalType":"address","name":"tokenContract","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"owner","type":"address"}],"type":"error","name":"OwnableInvalidOwner"},{"inputs":[{"internalType":"address","name":"account","type":"address"}],"type":"error","name":"OwnableUnauthorizedAccount"},{"inputs":[],"type":"error","name":"RuleEngine_AdminWithAddressZeroNotAllowed"},{"inputs":[],"type":"error","name":"RuleEngine_RuleInvalidInterface"},{"inputs":[],"type":"error","name":"RuleEngine_RulesManagementModule_ArrayIsEmpty"},{"inputs":[{"internalType":"uint256","name":"maxRules","type":"uint256"}],"type":"error","name":"RuleEngine_RulesManagementModule_MaxRulesExceeded"},{"inputs":[],"type":"error","name":"RuleEngine_RulesManagementModule_MaxRulesZeroNotAllowed"},{"inputs":[],"type":"error","name":"RuleEngine_RulesManagementModule_RuleAccountCannotReceivePrivileges"},{"inputs":[],"type":"error","name":"RuleEngine_RulesManagementModule_RuleAddressZeroNotAllowed"},{"inputs":[],"type":"error","name":"RuleEngine_RulesManagementModule_RuleAlreadyExists"},{"inputs":[],"type":"error","name":"RuleEngine_RulesManagementModule_RuleDoNotMatch"},{"inputs":[],"type":"error","name":"TokenBinding_InvalidTokenAddress"},{"inputs":[],"type":"error","name":"TokenBinding_TokenAlreadyBound"},{"inputs":[],"type":"error","name":"TokenBinding_TokenNotBound"},{"inputs":[],"type":"error","name":"TokenBinding_UnauthorizedCaller"},{"inputs":[{"internalType":"contract IRule","name":"rule","type":"address","indexed":true}],"type":"event","name":"AddRule","anonymous":false},{"inputs":[],"type":"event","name":"ClearRules","anonymous":false},{"inputs":[{"internalType":"address","name":"previousOwner","type":"address","indexed":true},{"internalType":"address","name":"newOwner","type":"address","indexed":true}],"type":"event","name":"OwnershipTransferStarted","anonymous":false},{"inputs":[{"internalType":"address","name":"previousOwner","type":"address","indexed":true},{"internalType":"address","name":"newOwner","type":"address","indexed":true}],"type":"event","name":"OwnershipTransferred","anonymous":false},{"inputs":[{"internalType":"contract IRule","name":"rule","type":"address","indexed":true}],"type":"event","name":"RemoveRule","anonymous":false},{"inputs":[{"internalType":"uint256","name":"maxRules","type":"uint256","indexed":false}],"type":"event","name":"SetMaxRules","anonymous":false},{"inputs":[{"internalType":"address","name":"token","type":"address","indexed":false}],"type":"event","name":"TokenBound","anonymous":false},{"inputs":[{"internalType":"address[]","name":"tokens","type":"address[]","indexed":false},{"internalType":"bool","name":"approved","type":"bool","indexed":false}],"type":"event","name":"TokenSelfBindingApprovalBatchSet","anonymous":false},{"inputs":[{"internalType":"address","name":"token","type":"address","indexed":true},{"internalType":"bool","name":"approved","type":"bool","indexed":false}],"type":"event","name":"TokenSelfBindingApprovalSet","anonymous":false},{"inputs":[{"internalType":"address","name":"token","type":"address","indexed":false}],"type":"event","name":"TokenUnbound","anonymous":false},{"inputs":[],"stateMutability":"view","type":"function","name":"DEFAULT_MAX_RULES","outputs":[{"internalType":"uint256","name":"","type":"uint256"}]},{"inputs":[],"stateMutability":"nonpayable","type":"function","name":"acceptOwnership"},{"inputs":[{"internalType":"contract IRule","name":"rule_","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"addRule"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"bindToken"},{"inputs":[{"internalType":"address[]","name":"tokens","type":"address[]"}],"stateMutability":"nonpayable","type":"function","name":"bindTokens"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"view","type":"function","name":"canTransfer","outputs":[{"internalType":"bool","name":"","type":"bool"}]},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"view","type":"function","name":"canTransferFrom","outputs":[{"internalType":"bool","name":"","type":"bool"}]},{"inputs":[],"stateMutability":"nonpayable","type":"function","name":"clearRules"},{"inputs":[{"internalType":"contract IRule","name":"rule_","type":"address"}],"stateMutability":"view","type":"function","name":"containsRule","outputs":[{"internalType":"bool","name":"","type":"bool"}]},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"nonpayable","type":"function","name":"created"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"nonpayable","type":"function","name":"destroyed"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"view","type":"function","name":"detectTransferRestriction","outputs":[{"internalType":"uint8","name":"","type":"uint8"}]},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"view","type":"function","name":"detectTransferRestrictionFrom","outputs":[{"internalType":"uint8","name":"","type":"uint8"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"getTokenBound","outputs":[{"internalType":"address","name":"","type":"address"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"getTokenBounds","outputs":[{"internalType":"address[]","name":"","type":"address[]"}]},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"stateMutability":"view","type":"function","name":"isTokenBound","outputs":[{"internalType":"bool","name":"","type":"bool"}]},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"stateMutability":"view","type":"function","name":"isTokenSelfBindingApproved","outputs":[{"internalType":"bool","name":"","type":"bool"}]},{"inputs":[{"internalType":"address","name":"forwarder","type":"address"}],"stateMutability":"view","type":"function","name":"isTrustedForwarder","outputs":[{"internalType":"bool","name":"","type":"bool"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"maxRules","outputs":[{"internalType":"uint256","name":"","type":"uint256"}]},{"inputs":[{"internalType":"uint8","name":"restrictionCode","type":"uint8"}],"stateMutability":"view","type":"function","name":"messageForTransferRestriction","outputs":[{"internalType":"string","name":"","type":"string"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"pendingOwner","outputs":[{"internalType":"address","name":"","type":"address"}]},{"inputs":[{"internalType":"contract IRule","name":"rule_","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"removeRule"},{"inputs":[],"stateMutability":"nonpayable","type":"function","name":"renounceOwnership"},{"inputs":[{"internalType":"uint256","name":"ruleId","type":"uint256"}],"stateMutability":"view","type":"function","name":"rule","outputs":[{"internalType":"address","name":"","type":"address"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"rules","outputs":[{"internalType":"address[]","name":"","type":"address[]"}]},{"inputs":[],"stateMutability":"view","type":"function","name":"rulesCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}]},{"inputs":[{"internalType":"uint256","name":"maxRules_","type":"uint256"}],"stateMutability":"nonpayable","type":"function","name":"setMaxRules"},{"inputs":[{"internalType":"contract IRule[]","name":"rules_","type":"address[]"}],"stateMutability":"nonpayable","type":"function","name":"setRules"},{"inputs":[{"internalType":"address","name":"token","type":"address"},{"internalType":"bool","name":"approved","type":"bool"}],"stateMutability":"nonpayable","type":"function","name":"setTokenSelfBindingApproval"},{"inputs":[{"internalType":"address[]","name":"tokens","type":"address[]"},{"internalType":"bool","name":"approved","type":"bool"}],"stateMutability":"nonpayable","type":"function","name":"setTokenSelfBindingApprovalBatch"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"stateMutability":"view","type":"function","name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}]},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"transferOwnership"},{"inputs":[{"internalType":"address","name":"spender","type":"address"},{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"nonpayable","type":"function","name":"transferred"},{"inputs":[{"internalType":"address","name":"from","type":"address"},{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"value","type":"uint256"}],"stateMutability":"nonpayable","type":"function","name":"transferred"},{"inputs":[],"stateMutability":"view","type":"function","name":"trustedForwarder","outputs":[{"internalType":"address","name":"","type":"address"}]},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"stateMutability":"nonpayable","type":"function","name":"unbindToken"},{"inputs":[{"internalType":"address[]","name":"tokens","type":"address[]"}],"stateMutability":"nonpayable","type":"function","name":"unbindTokens"},{"inputs":[],"stateMutability":"view","type":"function","name":"version","outputs":[{"internalType":"string","name":"version_","type":"string"}]}],"devdoc":{"kind":"dev","methods":{"acceptOwnership()":{"details":"Repeats the rule-account check of {transferOwnership}: an address nominated while it was not a rule, then added as a rule, cannot accept until it is removed from the rule set."},"addRule(address)":{"details":"Reverts when the configured maximum number of rules is already reached. Security convention: do not grant {RULES_MANAGEMENT_ROLE} to rule contracts.","params":{"rule_":"The IRule contract to add."}},"bindToken(address)":{"custom:security-note":"\"Multi-tenant\" means one instance is shared by multiple token contracts. Downstream state (for the RuleEngine: the per-address accounting held by stateful rules) is shared across all bound tokens, so binding tokens from different issuers silently cross-contaminates it. Only bind tokens that are equally trusted and governed together.","details":"Authorized by {_authorizeTokenBindingChange}.","params":{"token":"The address of the token to bind."}},"bindTokens(address[])":{"custom:security-note":"See {bindToken} for multi-tenant state risks. All tokens bound in this batch share the same downstream state. Only bind tokens that are equally trusted and governed together.","details":"Must be restricted by implementation-specific access control. Atomic: reverts if any token is invalid or already bound (or listed twice), and then binds none of them. This deliberately departs from the usual batch convention of skipping elements already in the target state: a binding change is security-relevant, and a token that is already bound in the list is most likely an operator mistake that should stop the whole operation. An empty array is a no-op.","params":{"tokens":"The token addresses to bind."}},"canTransfer(address,address,uint256)":{"details":"Don't check the balance and the user's right (access control)","params":{"from":"The address sending tokens.","to":"The address receiving tokens.","value":"The amount of tokens to transfer."},"returns":{"_0":"True if the transfer is valid, false otherwise."}},"canTransferFrom(address,address,address,uint256)":{"details":"Does not check balances or access rights (Access Control).","params":{"from":"The source address.","spender":"The address performing the transfer.","to":"The destination address.","value":"The number of tokens to transfer."},"returns":{"_0":"isCompliant True if the transfer complies with policy."}},"clearRules()":{"details":"After calling this function, no rules will remain set. Cost is O(n) in the number of configured rules. With the default cap of 10 this is negligible, but a high {maxRules} setting re-exposes unbounded cost here even though per-transfer cost remains bounded."},"constructor":{"params":{"forwarderIrrevocable":"Address of the trusted ERC-2771 forwarder, immutable after construction.","owner_":"Address of the initial contract owner (ERC-173).","tokenContract":"Token to bind at deployment, or the zero address to bind none."}},"containsRule(address)":{"details":"Complexity: O(1).","params":{"rule_":"The IRule contract to check for membership."},"returns":{"_0":"True if the rule is present, false otherwise."}},"created(address,uint256)":{"details":"Called by the token contract when new tokens are issued to an account. Reverts if the minting does not comply with the rules.","params":{"to":"The address receiving the minted tokens.","value":"The number of tokens created."}},"destroyed(address,uint256)":{"details":"Called by the token contract when tokens are redeemed or burned. Reverts if the burning does not comply with the rules.","params":{"from":"The address whose tokens are being destroyed.","value":"The number of tokens destroyed."}},"detectTransferRestriction(address,address,uint256)":{"params":{"from":"the origin address","to":"the destination address","value":"to transfer"},"returns":{"_0":"The restriction code or REJECTED_CODE_BASE.TRANSFER_OK (0) if the transfer is valid"}},"detectTransferRestrictionFrom(address,address,address,uint256)":{"details":" See {ERC-1404} Add an additionnal argument `spender` This function is where an issuer enforces the restriction logic of their token transfers. Some examples of this might include: - checking if the token recipient is whitelisted, - checking if a sender's tokens are frozen in a lock-up period, etc.","params":{"from":"The address sending tokens.","spender":"The address initiating the delegated transfer.","to":"The address receiving tokens.","value":"amount of tokens to transfer"},"returns":{"_0":"uint8 restricted code, 0 means the transfer is authorized"}},"getTokenBound()":{"details":"If multiple tokens are supported, consider using getTokenBounds().","returns":{"_0":"The address of the currently bound token."}},"getTokenBounds()":{"details":"This operation copies the entire storage set to memory and is mainly intended for off-chain reads.","returns":{"_0":"An array of bound token addresses."}},"isTokenBound(address)":{"details":"Complexity: O(1).","params":{"token":"The token address to verify."},"returns":{"_0":"True if the token is bound, false otherwise."}},"isTokenSelfBindingApproved(address)":{"params":{"token":"The token address to query."},"returns":{"_0":"True if self-binding is approved for `token`, false otherwise."}},"isTrustedForwarder(address)":{"details":"Indicates whether any particular address is the trusted forwarder."},"maxRules()":{"returns":{"_0":"The maximum number of rules that can be configured."}},"messageForTransferRestriction(uint8)":{"details":"See {ERC-1404} This function is effectively an accessor for the \"message\", a human-readable explanation as to why a transaction is restricted.","params":{"restrictionCode":"The restriction code to translate into a message."},"returns":{"_0":"The human-readable message corresponding to `restrictionCode`."}},"owner()":{"details":"Returns the address of the current owner."},"pendingOwner()":{"details":"Returns the address of the pending owner."},"removeRule(address)":{"details":"Reverts if the provided rule is not found or does not match the stored rule at its index. Complexity: O(1).","params":{"rule_":"The IRule contract to remove."}},"renounceOwnership()":{"details":"Leaves the contract without owner. It will not be possible to call `onlyOwner` functions. Can only be called by the current owner. NOTE: Renouncing ownership will leave the contract without an owner, thereby disabling any functionality that is only available to the owner."},"rule(uint256)":{"details":"Reverts if `ruleId` is out of bounds. Complexity: O(1). Note that there are no guarantees on the ordering of values inside the array, and it may change when more values are added or removed.","params":{"ruleId":"The index of the desired rule in the array."},"returns":{"_0":"The address of the corresponding IRule contract, return the `zero address` is out of bounds."}},"rules()":{"details":"This is a view-only function that does not modify state. This operation will copy the entire storage to memory, which can be quite expensive. This is designed to mostly be used by view accessors that are queried without any gas fees.","returns":{"_0":"An array of all active rule contract addresses."}},"rulesCount()":{"details":"Equivalent to the length of the internal rules array. Complexity: O(1)","returns":{"_0":"The number of active rules."}},"setMaxRules(uint256)":{"details":"Access control is implementation specific (admin/owner). Setting a very high cap re-exposes unbounded gas cost for administrative operations such as {clearRules} even though normal per-transfer cost remains bounded.","params":{"maxRules_":"New maximum number of rules."}},"setRules(address[])":{"details":"Replaces the entire rule set atomically. Reverts if `rules_` is empty. Use {clearRules} to remove all rules explicitly. To transition from one non-empty set to another without an enforcement gap, call this function directly with the new set. Emits {ClearRules} when the existing rule set is non-empty, then emits {AddRule} for each new rule. Off-chain indexers must handle both events to reconstruct state. Security convention: rule contracts should be treated as trusted business logic, but should not also be granted {RULES_MANAGEMENT_ROLE}.","params":{"rules_":"The array of addresses representing the new rules to be set."}},"setTokenSelfBindingApproval(address,bool)":{"details":"Must be restricted by implementation-specific access control. An approval stays in force until it is revoked here or until the binding manager unbinds the token ({unbindToken} or {unbindTokens}), which revokes it and emits {TokenSelfBindingApprovalSet} with `false`. A token that unbinds itself keeps its approval, so it can bind itself again later.","params":{"approved":"Whether self-binding is approved for `token`.","token":"The token address to configure."}},"setTokenSelfBindingApprovalBatch(address[],bool)":{"details":"Must be restricted by implementation-specific access control. Reverts if any token in `tokens` is the zero address. Emits a single {TokenSelfBindingApprovalBatchSet} with the input array, not one {TokenSelfBindingApprovalSet} per token.","params":{"approved":"Whether self-binding is approved for all provided tokens.","tokens":"The token addresses to configure."}},"supportsInterface(bytes4)":{"params":{"interfaceId":"The interface identifier to check."},"returns":{"_0":"True if the interface is supported, false otherwise."}},"transferOwnership(address)":{"details":"Reverts when `newOwner` is already configured as a rule.","params":{"newOwner":"The address of the new owner."}},"transferred(address,address,address,uint256)":{"details":"Must revert if the transfer is invalid Same name as ERC-3643 but with one supplementary argument `spender` This function can be used to update state variables of the RuleEngine contract This function can be called ONLY by the token contract bound to the RuleEngine Which overload the token calls (since CMTAT v3.3.0): - this 4-argument overload for `transferFrom` (`spender` = approved spender) and for every operation initiated by an operator, with the operator as `spender`: mint (`from == address(0)`), burn (`to == address(0)`), including `burnFrom`, self-burn and cross-chain mint/burn, and the minter `batchTransfer`; - the 3-argument ERC-3643 overload `transferred(from, to, value)`, inherited from {IERC3643IComplianceContract}, only for a direct `transfer`. Up to CMTAT v3.2.0, mint, burn and the minter transfer used the 3-argument overload. WARNING - zero-value calls are permissionless. ERC-20 requires transfers of `0` to be treated as normal transfers, and OpenZeppelin's `_spendAllowance` consumes no allowance when `value == 0`. Any address can therefore call `transferFrom(victim, anyone, 0)` on the token and reach this callback for an arbitrary `from`, with itself as `spender`, without ever having been approved. The token deliberately does not suppress the notification, because doing so would make its compliance notifications inconsistent with its own ERC-20 transfer semantics. Implementations MUST therefore treat `value == 0` as carrying no economic meaning: any stateful rule (cooldown, holding period, quota, tax bucket, counter, holder tracking, ...) MUST be a no-op for a zero value, otherwise an attacker can desynchronize policy state from balances, or keep a holder permanently restricted, at no cost. The same applies to the 3-argument ERC-3643 overload, which a zero-value `transfer(to, 0)` reaches the same way.","params":{"from":"token holder address","spender":"spender address (sender)","to":"receiver address","value":"value of tokens involved in the transfer; MAY be `0` — see the warning above"}},"transferred(address,address,uint256)":{"details":" This function can be used to update state variables of the compliance contract This function can be called ONLY by the token contract bound to the compliance","params":{"from":"The address of the sender","to":"The address of the receiver","value":"value of tokens involved in the transfer"}},"trustedForwarder()":{"details":"Returns the address of the trusted forwarder."},"unbindToken(address)":{"details":"Authorized by {_authorizeTokenBindingChange}. Operator warning: unbinding is an administrative operation and does not erase any state already stored downstream in a previously shared (\"multi-tenant\") setup.","params":{"token":"The address of the token to unbind."}},"unbindTokens(address[])":{"details":"Must be restricted by implementation-specific access control. Atomic: reverts if any token is not currently bound, and then unbinds none of them. Deliberately not the skip-if-already-done batch convention, for the same reason as {bindTokens}. An empty array is a no-op. Like a manager's {unbindToken}, revokes each token's self-binding approval (see {setTokenSelfBindingApproval}).","params":{"tokens":"The token addresses to unbind."}},"version()":{"details":"This value is useful to know which smart contract version has been used","returns":{"version_":"A string representing the version of the token implementation (e.g., \"1.0.0\")."}}},"version":1},"userdoc":{"kind":"user","methods":{"DEFAULT_MAX_RULES()":{"notice":"Default upper bound on the number of rules a RuleEngine may hold."},"acceptOwnership()":{"notice":"Completes the ownership transfer; callable by the pending owner only."},"addRule(address)":{"notice":"Adds a new rule to the current rule set."},"bindToken(address)":{"notice":"Binds a token contract, allowing it to call the bound-token entry points."},"bindTokens(address[])":{"notice":"Binds several token contracts in a single call."},"canTransfer(address,address,uint256)":{"notice":"Returns true if the transfer is valid, and false otherwise."},"canTransferFrom(address,address,address,uint256)":{"notice":"Checks if `spender` can transfer `value` tokens from `from` to `to` under compliance rules."},"clearRules()":{"notice":"Removes all configured rules."},"constructor":{"notice":"Deploys a RuleEngine with ERC-173 Ownable2Step access control and a trusted forwarder."},"containsRule(address)":{"notice":"Checks whether a specific rule is currently configured."},"created(address,uint256)":{"notice":"Updates the compliance contract state when tokens are created (minted)."},"destroyed(address,uint256)":{"notice":"Updates the compliance contract state when tokens are destroyed (burned)."},"detectTransferRestriction(address,address,uint256)":{"notice":"Queries every rule, in order, and returns the first restriction code that is not zero"},"detectTransferRestrictionFrom(address,address,address,uint256)":{"notice":"Returns a uint8 code to indicate if a transfer is restricted or not"},"getTokenBound()":{"notice":"Returns the single token currently bound to this compliance contract."},"getTokenBounds()":{"notice":"Returns all tokens currently bound."},"isTokenBound(address)":{"notice":"Checks whether a token is currently bound."},"isTokenSelfBindingApproved(address)":{"notice":"Returns whether a token is approved to bind and unbind itself."},"maxRules()":{"notice":"Returns the maximum number of rules allowed in the engine."},"removeRule(address)":{"notice":"Removes a specific rule from the current rule set."},"rule(uint256)":{"notice":"Retrieves the rule address at a specific index."},"rules()":{"notice":"Returns the full list of currently configured rules."},"rulesCount()":{"notice":"Returns the total number of currently configured rules."},"setMaxRules(uint256)":{"notice":"Updates the maximum number of rules allowed in the engine."},"setRules(address[])":{"notice":"Defines the rules for the rule engine."},"setTokenSelfBindingApproval(address,bool)":{"notice":"Sets whether a token is allowed to bind and unbind itself."},"setTokenSelfBindingApprovalBatch(address[],bool)":{"notice":"Sets self-binding approval for multiple tokens in one transaction."},"supportsInterface(bytes4)":{"notice":"ERC-165 interface detection."},"transferOwnership(address)":{"notice":"Starts ownership transfer to `newOwner`."},"transferred(address,address,address,uint256)":{"notice":"Function called whenever tokens are transferred from one wallet to another, minted or burned, when the token knows the account that initiated the operation (`spender`)."},"transferred(address,address,uint256)":{"notice":"Function called whenever tokens are transferred from one wallet to another"},"unbindToken(address)":{"notice":"Unbinds a token contract, revoking its access to the bound-token entry points."},"unbindTokens(address[])":{"notice":"Unbinds several token contracts in a single call."},"version()":{"notice":"Returns the current version of the token contract."}},"version":1}},"settings":{"remappings":["@chainlink/contracts-ccip/=lib/Rules/lib/chainlink-ace/node_modules/@chainlink/contracts-ccip/chains/evm/contracts/","@chainlink/contracts/=lib/Rules/lib/chainlink-ace/node_modules/@chainlink/contracts/","@chainlink/contracts@1.4.0/=lib/Rules/lib/chainlink-doc/node_modules/@chainlink/contracts-1.4.0/","@chainlink/cross-chain-identity/=lib/Rules/lib/chainlink-ace/packages/cross-chain-identity/src/","@chainlink/local/=lib/Rules/lib/chainlink-doc/node_modules/@chainlink/local/","@chainlink/policy-management/=lib/Rules/lib/chainlink-ace/packages/policy-management/src/","@openzeppelin/contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/contracts/","@openzeppelin/contracts/=lib/openzeppelin-contracts/contracts/","@openzeppelin/contracts@4.7.3/=lib/Rules/lib/chainlink-doc/node_modules/@openzeppelin/contracts-4.7.3/","@openzeppelin/contracts@4.8.3/=lib/Rules/lib/chainlink-ace/node_modules/@openzeppelin/contracts-4.8.3/","@openzeppelin/contracts@4.9.6/=lib/Rules/lib/chainlink-doc/node_modules/@openzeppelin/contracts-4.9.6/","@openzeppelin/contracts@5.0.2/=lib/Rules/lib/chainlink-ace/node_modules/@openzeppelin/contracts/","@openzeppelin/contracts@5.1.0/=lib/Rules/lib/chainlink-doc/node_modules/@openzeppelin/contracts-5.1.0/","@openzeppelin/contracts@5.3.0/=lib/Rules/lib/chainlink-ace/node_modules/@openzeppelin/contracts-5.3.0/","CMTAT/=lib/CMTAT/contracts/","CMTATv3.0.0/=lib/CMTATv3.0.0/contracts/","ERC-3643/=lib/ERC-3643/contracts/","ERC3643/=lib/Rules/lib/ERC-3643/contracts/","RuleEngine/=lib/Rules/lib/RuleEngine/","Rules/=lib/Rules/","chainlink-ace/=lib/Rules/lib/chainlink-ace/","chainlink-doc/=lib/Rules/lib/","erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/","forge-std/=lib/forge-std/src/","halmos-cheatcodes/=lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/","openzeppelin-contracts-upgradeable/=lib/openzeppelin-contracts-upgradeable/","openzeppelin-contracts/=lib/openzeppelin-contracts/"],"optimizer":{"enabled":true,"runs":200},"metadata":{"bytecodeHash":"ipfs"},"compilationTarget":{"src/deployment/ownable/RuleEngineOwnable2Step2771.sol":"RuleEngineOwnable2Step2771"},"evmVersion":"osaka","libraries":{}},"sources":{"lib/CMTAT/contracts/interfaces/engine/IRuleEngine.sol":{"keccak256":"0xeda899e2e46a9b9c3516acb61a7f7e92ed098928379010655c330da721aaffa7","urls":["bzz-raw://60f8555330fc531dff7d0d71a862696fb286a0ba3290e41efbbbf4dd25947a3c","dweb:/ipfs/QmWvbsBGWPtNMNN2EEedwdzzvQG7NtSj9VD2fmNgqVtCXN"],"license":"MPL-2.0"},"lib/CMTAT/contracts/interfaces/technical/IERC5679.sol":{"keccak256":"0x5bee30750c9a65438469a6c5bd8465e1603eec3aeeb94c07bd64ba3e9ee766e1","urls":["bzz-raw://ef7a5c5f0d47135c97ab5d7456d31e513a71c849ae7f2f5395f860be125c4fbc","dweb:/ipfs/Qmezem3qqSjij6ggyB34wC2S15KrY9fu42oymyS9epAYCQ"],"license":"MPL-2.0"},"lib/CMTAT/contracts/interfaces/tokenization/IERC3643Partial.sol":{"keccak256":"0x5c84c2e2442824e98625c471482fb3c9502f43f4c345e7c0fb07fa549be02e26","urls":["bzz-raw://19071f2d12fb580d37eeee07885461f193568df34f3f69d2c5d65ce655d84435","dweb:/ipfs/QmRqHwC7LksE3YPohMtxFieiPerhWdoDNUUMMLbB4XYvhK"],"license":"MPL-2.0"},"lib/CMTAT/contracts/interfaces/tokenization/draft-IERC1404.sol":{"keccak256":"0xc27cdac182d930a94391d589bdafa15364b6f8d9bf211175781dba661f1c0336","urls":["bzz-raw://b509fa7f3cfd785632569f6ae3bec846aa0beefd73c1d5bde233440cae919f0f","dweb:/ipfs/QmPCAdiEun8gaMqS8KhwPpRZV2zXAPfURRaF4C2KjX5Kby"],"license":"MPL-2.0"},"lib/CMTAT/contracts/interfaces/tokenization/draft-IERC7551.sol":{"keccak256":"0x84b73eb77ec82d6d7b313eff2d87f58d3b795840d004aaa10c611b360b827e30","urls":["bzz-raw://a5b8c99fb3600369065a422d3821ba441dc06fc64f50ce0f33950a76ad82b51b","dweb:/ipfs/QmbviJsZPY3xuLU3cHUWJx11aJCPAuN4WKnCufN4kVLm2U"],"license":"MPL-2.0"},"lib/CMTAT/contracts/interfaces/tokenization/draft-IERC7943.sol":{"keccak256":"0xc69588a72da81057ee278e961e8e3bb61a28d64c3c6cebe494ce00809c1cef15","urls":["bzz-raw://148f117d9c463de441f81e6c0a67e95f1f14a61db209492dd0a1767b5572f21a","dweb:/ipfs/QmUjT5uyJfNSYgUWn5Dxhf6Sx9Y1z8CNf3PuTEaGoAx3za"],"license":"MPL-2.0"},"lib/CMTAT/contracts/library/ERC1404ExtendInterfaceId.sol":{"keccak256":"0xf8268f4eb3a6b2e26c32cf76c5c76b6c17df3385c150f05953538a2472149247","urls":["bzz-raw://05108de7a7ba2a0a67978bdfe8e500360674db6d894f42970bb1016b36639056","dweb:/ipfs/QmRux9Qj1GomATseS6Tyq9uiPPNNipuxg2HjdjnPjgSQds"],"license":"MPL-2.0"},"lib/CMTAT/contracts/library/RuleEngineInterfaceId.sol":{"keccak256":"0x1152a49cba4232d943e295d259eb8a1b216d815067367410a5729a256dae4051","urls":["bzz-raw://470f4435a5e62b0ba0ad70f8657b2db0e4cc3b7f2561772adb944ce010551ee6","dweb:/ipfs/QmXECahRr8rK9XJPZwBCnemLDVPdFvPEBusezhaBqbLBqp"],"license":"MPL-2.0"},"lib/openzeppelin-contracts/contracts/access/Ownable.sol":{"keccak256":"0xff6d0bb2e285473e5311d9d3caacb525ae3538a80758c10649a4d61029b017bb","urls":["bzz-raw://8ed324d3920bb545059d66ab97d43e43ee85fd3bd52e03e401f020afb0b120f6","dweb:/ipfs/QmfEckWLmZkDDcoWrkEvMWhms66xwTLff9DDhegYpvHo1a"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/access/Ownable2Step.sol":{"keccak256":"0xdcad8898fda432696597752e8ec361b87d85c82cb258115427af006dacf7128c","urls":["bzz-raw://e2c9d517f0c136d54bd00cd57959d25681d4d6273f5bbbc263afe228303772f0","dweb:/ipfs/QmReNFjXBiufByiAAzfSQ2SM5r3qeUErn46BmN3yVRvrek"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/interfaces/IERC165.sol":{"keccak256":"0x0afcb7e740d1537b252cb2676f600465ce6938398569f09ba1b9ca240dde2dfc","urls":["bzz-raw://1c299900ac4ec268d4570ecef0d697a3013cd11a6eb74e295ee3fbc945056037","dweb:/ipfs/Qmab9owJoxcA7vJT5XNayCMaUR1qxqj1NDzzisduwaJMcZ"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/metatx/ERC2771Context.sol":{"keccak256":"0x9695d220b99dcf62910533bdf5d40d4cf6a4e04d5b106b6803a80586486dc7f7","urls":["bzz-raw://83b7aecd65882d8953643dce144efe91367082cc01830c9c4ed3c8a4837fb558","dweb:/ipfs/QmQ5HxGavcCKjuhd8buv177qjG6A4kvxx4pZviceKdspdM"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/Arrays.sol":{"keccak256":"0x772f0c778626a7bdcbcbabca74b825ae9b9dc89d2a47a98b402b1187fbaa63a4","urls":["bzz-raw://eba1d46e58e8880b45c6d51245dc94585b81d6d7290ca77ef50037a6193ed301","dweb:/ipfs/Qme3CWun5qQACjGEerT2MCvhs6brKGFfJirGnzV1ypKTXA"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/Comparators.sol":{"keccak256":"0x302eecd8cf323b4690e3494a7d960b3cbce077032ab8ef655b323cdd136cec58","urls":["bzz-raw://49ba706f1bc476d68fe6c1fad75517acea4e9e275be0989b548e292eb3a3eacd","dweb:/ipfs/QmeBpvcdGWzWMKTQESUCEhHgnEQYYATVwPxLMxa6vMT7jC"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/Context.sol":{"keccak256":"0x493033a8d1b176a037b2cc6a04dad01a5c157722049bbecf632ca876224dd4b2","urls":["bzz-raw://6a708e8a5bdb1011c2c381c9a5cfd8a9a956d7d0a9dc1bd8bcdaf52f76ef2f12","dweb:/ipfs/Qmax9WHBnVsZP46ZxEMNRQpLQnrdE4dK8LehML1Py8FowF"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/Panic.sol":{"keccak256":"0xf7fe324703a64fc51702311dc51562d5cb1497734f074e4f483bfb6717572d7a","urls":["bzz-raw://c6a5ff4f9fd8649b7ee20800b7fa387d3465bd77cf20c2d1068cd5c98e1ed57a","dweb:/ipfs/QmVSaVJf9FXFhdYEYeCEfjMVHrxDh5qL4CGkxdMWpQCrqG"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/SlotDerivation.sol":{"keccak256":"0x94045fd4f268edf2b2d01ef119268548c320366d6f5294ad30c1b8f9d4f5225f","urls":["bzz-raw://edfda81f426f8948b3834115c21e83c48180e6db0d2a8cd2debb2185ed349337","dweb:/ipfs/QmdYZneFyDAux1BuWQxLAdqtABrGS2k9WYCa7C9dvpKkWv"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/StorageSlot.sol":{"keccak256":"0xcf74f855663ce2ae00ed8352666b7935f6cddea2932fdf2c3ecd30a9b1cd0e97","urls":["bzz-raw://9f660b1f351b757dfe01438e59888f31f33ded3afcf5cb5b0d9bf9aa6f320a8b","dweb:/ipfs/QmarDJ5hZEgBtCmmrVzEZWjub9769eD686jmzb2XpSU1cM"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165.sol":{"keccak256":"0x2d9dc2fe26180f74c11c13663647d38e259e45f95eb88f57b61d2160b0109d3e","urls":["bzz-raw://81233d1f98060113d9922180bb0f14f8335856fe9f339134b09335e9f678c377","dweb:/ipfs/QmWh6R35SarhAn4z2wH8SU456jJSYL2FgucfTFgbHJJN4E"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/introspection/ERC165Checker.sol":{"keccak256":"0x7c7ad70641a7f8cd44def0857ec97b0e40bfd073b2d6037a5f57ce9527ee9bc5","urls":["bzz-raw://e05c6572dfe769f7aea6f3a8002951cc12d143d980dad29f6c5feedf9408bc14","dweb:/ipfs/QmXM7C8YEptxisZiEefXUrwdXt3zMaCobmkCchxTtDg1oK"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/introspection/IERC165.sol":{"keccak256":"0x8891738ffe910f0cf2da09566928589bf5d63f4524dd734fd9cedbac3274dd5c","urls":["bzz-raw://971f954442df5c2ef5b5ebf1eb245d7105d9fbacc7386ee5c796df1d45b21617","dweb:/ipfs/QmadRjHbkicwqwwh61raUEapaVEtaLMcYbQZWs9gUkgj3u"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/math/Math.sol":{"keccak256":"0x59973a93b1f983f94e10529f46ca46544a9fec2b5f56fb1390bbe9e0dc79f857","urls":["bzz-raw://c55ef8f0b9719790c2ae6f81d80a59ffb89f2f0abe6bc065585bd79edce058c5","dweb:/ipfs/QmNNmCbX9NjPXKqHJN8R1WC2rNeZSQrPZLd6FF6AKLyH5Y"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/math/SafeCast.sol":{"keccak256":"0xc8cae21c9ae4a46e5162ff9bf5b351d6fa6a6eba72d515f3bc1bdfeda7fdf083","urls":["bzz-raw://ce830ebcf28e31643caba318996db3763c36d52cd0f23798ba83c135355d45e9","dweb:/ipfs/QmdGPcvptHN7UBCbUYBbRX3hiRVRFLRwno8b4uga6uFNif"],"license":"MIT"},"lib/openzeppelin-contracts/contracts/utils/structs/EnumerableSet.sol":{"keccak256":"0xd553ff8b7d55679f0711f1598600ac292dbd8cfdf4b2419b9cabe4c931172895","urls":["bzz-raw://7905ccb27e2308fd0d90dc1212161003ab6964e1c176593db1ccedef705bcc09","dweb:/ipfs/QmW37vm2PcrWLKnN74sKkvAzqSwntCEfCp4EoSEvbBHWkj"],"license":"MIT"},"src/RuleEngineBase.sol":{"keccak256":"0xb3d832fa55b615574d80b0e0ad76620ad236aa046523617ed5daa46ae07bf853","urls":["bzz-raw://7be31bf5dbd3fa1be025cdc4b7674b76bf40e1c14ce89ec78f792cb3d7ed804e","dweb:/ipfs/QmPq4xBiB3XwXerWtuonZLGiWHMqvz5tKvjhTh9AiWkbww"],"license":"MPL-2.0"},"src/RuleEngineOwnableShared.sol":{"keccak256":"0xa78493398d8b0554e72def7f14d7439109bd4dbd5e07f1466b40acea2bb7dc02","urls":["bzz-raw://ebd87d69b4f6eb193c5d03476381ac132f9587248422d3306dda95b79fd4e470","dweb:/ipfs/QmWYDLvPWjRcfxdR2KhXAij8U9TrFjeM77fsJRX25jWQmY"],"license":"MPL-2.0"},"src/deployment/ownable/RuleEngineOwnable2Step.sol":{"keccak256":"0xf8d7f52cf7857f0d89adeb7dfa42444dbaf371dd6cca712c797181baf7a3fe97","urls":["bzz-raw://f3307f7a2800dfc1b23c89cf6eebcbf21fd283eeb19343a374bc5bc771b7a4ef","dweb:/ipfs/QmbFjoQ97zF74QCWwbswVwKL7wB1Gx4pfRdu7jp2vE36DB"],"license":"MPL-2.0"},"src/deployment/ownable/RuleEngineOwnable2Step2771.sol":{"keccak256":"0x1980b872a8d8fac8e37bf8d032ef7a6b01d205abb8723b8b0b18ba64ed566e94","urls":["bzz-raw://031a2672f52384fc76b123bcec8a6b86d5c70607920ea3d347326275652cf482","dweb:/ipfs/QmXLwxAmpXJmjcwMrLuJKnnPkZMHrqg9bPcLJ1jupsKF2x"],"license":"MPL-2.0"},"src/interfaces/IERC3643Compliance.sol":{"keccak256":"0xd0edd6697d67135853576ac6a40cadaffd787cedea98071708bbfb189c7ee5bc","urls":["bzz-raw://4ed3cd3af64fccff17a1f33989cdfbdacbc0e4f32a56de11a072cf9e2277a1f6","dweb:/ipfs/QmenRqRw1Yy39yDv1pJgBmnHtwuZhDdHE4omchL41CjXjb"],"license":"MPL-2.0"},"src/interfaces/IERC3643ComplianceExtended.sol":{"keccak256":"0x4a43bf330c7a904cba110acf52f519718d8409514c377912d5bd063c9d963729","urls":["bzz-raw://c671879c591760ecbc2691e2f24adfb215a658c9fe6eb0c05dd1ca980054e585","dweb:/ipfs/QmdbA19PFpJgHraF46YrcMNzUgswbTRA92atL2Lha63JLY"],"license":"MPL-2.0"},"src/interfaces/IRule.sol":{"keccak256":"0x81580b67f7be09049aa64d93cc1d8d691a87c639adc1cf169dc6073e1e543a5c","urls":["bzz-raw://6f1808c3ed18ef1acbccdd9b30011b6e7220d388cfd66cba40b1ef0b485306a1","dweb:/ipfs/QmcUCQ5MYcf7KTtoeqMKsTutPPSJhNTaK1ntHV21ioS9Fm"],"license":"MPL-2.0"},"src/interfaces/IRulesManagementModule.sol":{"keccak256":"0x082dd58070e83b02f275584afa872c4583ac4ca8ad12eb329fc11301470147f9","urls":["bzz-raw://e2d0ad78dc323881864f406acd44976f5de39cdc97a6c99a724d8458b993e2e2","dweb:/ipfs/QmRFfMbXbdiAYV3vQyNppXG7tHTji6mV1Y5Cu3ZzEQm5ng"],"license":"MPL-2.0"},"src/interfaces/ITokenBinding.sol":{"keccak256":"0x34dfea4e118c966adf867c0899844515566251819b4e4510fd8ee424555493fd","urls":["bzz-raw://1d054ed49874816688a6e71f76d611bbdefd492d122ae386cb804c6f5af677a7","dweb:/ipfs/QmRaYX4aJWYSNWNa1D4Nich3k7hkGM9rTfc9s2XaVqyRjy"],"license":"MPL-2.0"},"src/interfaces/ITokenBindingExtended.sol":{"keccak256":"0x01f3ab56dffce860d03e72d10e9f2d13b6bfc9004cf058c63a0b23e3b226da99","urls":["bzz-raw://521e0c9651632b70d61c4c3bd0b14c6f05d818166fe65dbed8e3253158b7637e","dweb:/ipfs/QmY2xEVvfV1dgtFYw6coHX3Z7Fm7yRhzPaGyt6cYBMVf76"],"license":"MPL-2.0"},"src/modules/ERC2771ModuleStandalone.sol":{"keccak256":"0x2135408cd37646f3a27b4a2cdb6f1b9b622541fed4f4b6311a06f986f6eb75d1","urls":["bzz-raw://82229782c9664a8c039fd5a3ecedca8a827fcec190be6c527c1236c864c0418f","dweb:/ipfs/QmXQmX1BFFupTPB27uJweT1tSc6nce3JXDSDa9Ztpf6cKk"],"license":"MPL-2.0"},"src/modules/ERC3643ComplianceExtendedModule.sol":{"keccak256":"0x6f808b068517e9e15f09fc6a9d4190001ec8c2314a10e27a85a2d43e44c84fb1","urls":["bzz-raw://c62c0b77fdd8b6e7bf7aa5bf8134a78ff024d6489a23f746874a99df38a8a265","dweb:/ipfs/QmV7PG3ZUUzwDs9tpooC3hmBu5e39buJnJ4TRditojJ3hu"],"license":"MPL-2.0"},"src/modules/ERC3643ComplianceModule.sol":{"keccak256":"0x7cda81af8687328ac2089f9d1d78352e0e75d0f70a4ba8e2b3ac82896f22863f","urls":["bzz-raw://50711cb94d69ea63d787a8bb19c38c0b99539029ec8fb957a8eff00880fc11fc","dweb:/ipfs/QmSapDWh5mpvWn1q6JteZisJfVGPrCz47WP2BBrJCccEjV"],"license":"MPL-2.0"},"src/modules/RulesManagementModule.sol":{"keccak256":"0xe4d9425613284e71a5e3d590d5433167a9751d9496f57efa914baa81f493e66d","urls":["bzz-raw://d07a16e6869df86c526ef89e7e359e34a9553dc4288b262abd2979359ecf720e","dweb:/ipfs/QmRy2JEsyhkv1mxv7eFaSbEWN4A3gtpPSUnnV48W2KiV4u"],"license":"MPL-2.0"},"src/modules/TokenBindingExtendedModule.sol":{"keccak256":"0x4e1ca7b2ec78608c3a7960bec7102a1780bdf3ec7ff544b612bafaf738b34d05","urls":["bzz-raw://657bcdd303fd5a7fbe733b283f69d8e8aa73efeeeaf95c0ae7479769ac573693","dweb:/ipfs/QmXiWPrv8pEqvBQck8jxC7NwB1MUdGQfLjihK6etYcZ54j"],"license":"MPL-2.0"},"src/modules/TokenBindingModule.sol":{"keccak256":"0xf65f46311d0078f60c30e3359dca988e39cba45b9eee53a09d618bfa70e6ef9b","urls":["bzz-raw://e8c458ecfd41df5fb4a391e7ef837fd5ed5c999e61ccc0e6b4bd23023a739832","dweb:/ipfs/Qmdsr765aw9fPFN2M9cSCP69o1o41FNCqhrXjHgEXNwbXV"],"license":"MPL-2.0"},"src/modules/VersionModule.sol":{"keccak256":"0x35daf007be8b9bb1cb9196ae2decb3e5ad4b574f6390f8fc010b78796ac42f73","urls":["bzz-raw://b1b29d75e1c5023a0c6cb8c56638a17d855a3fdc051a60b9d2f304b99f7876d2","dweb:/ipfs/QmXSCVjLuViC8916LwNpKtw8hqyH78Ptag3xH1n7F1fY4g"],"license":"MPL-2.0"},"src/modules/library/ComplianceInterfaceId.sol":{"keccak256":"0xd54bed5328e732f753d2886aeaa2761b2d66536d5247d4548e0ac1c83c7a0dac","urls":["bzz-raw://ad695339fdfe72446a69d2dfbe39373affe2f37299ad921e57016069a7bc3592","dweb:/ipfs/QmWathGt3E85hLfy5rrAYdb291W8VoTa4gpGPoxtWGvNNA"],"license":"MPL-2.0"},"src/modules/library/ERC1404InterfaceId.sol":{"keccak256":"0x07dc6905e137096cd0ae88be29b112d0e54a83ddf8ca527a281718010f6abcce","urls":["bzz-raw://9249dce67cb59432bdbc9e49978c6cac0346cda3d3fca97c5a310e0f424e1600","dweb:/ipfs/QmRi5awH3hjwvd3k3td48y5Cf64n1wvX9wCWy6fQLayuKs"],"license":"MPL-2.0"},"src/modules/library/Ownable2StepInterfaceId.sol":{"keccak256":"0xe4c5bd8569553d93b7283118318993fea44410a608e7bda490ff27bc3e848f89","urls":["bzz-raw://8145a588e30eb836199f489e16464123082cd2af9989c9aeca1038c69ac3da6f","dweb:/ipfs/QmNrQJ2mQQjqx3UY86mKB2M1vCgLQakumumKxVhvqX6AhF"],"license":"MPL-2.0"},"src/modules/library/OwnableInterfaceId.sol":{"keccak256":"0xdbe06b3203e21e41d1fd2a3ef373a80727193443dfd981de6821422158015d4f","urls":["bzz-raw://ebe8699ae8af81c5cd82f25a1609d9396d72ae957647c33aaa745aadcdac8d18","dweb:/ipfs/QmV73gwDJPFthn8VspdYE6GsoAcQMAR7TachUK8YrPonuT"],"license":"MPL-2.0"},"src/modules/library/RuleEngineInvariantStorage.sol":{"keccak256":"0x50a212f09f1695662965e5fba643b42a1978bec2a8368abbf43983489c983096","urls":["bzz-raw://6137f01df7630527c985d85d2f7446359c678fcb933b66c55b51f583757b5c4a","dweb:/ipfs/QmeHo47WQm1V99xZHS4soMk68UdtXtZhtWhV3dQC5BtA7u"],"license":"MPL-2.0"},"src/modules/library/RuleInterfaceId.sol":{"keccak256":"0x0d86820eee4c92b21d6704bea8ce7bd2cc1b35f6e4a1ceabbcf2a10f1c6b02ec","urls":["bzz-raw://cfb560cb8588983b8c79a973d03c214a149bf1ac034fa9130ce93f0031a404d7","dweb:/ipfs/Qmc6qt4E4BHdDyLUegCsgxqhf7ZFUiX4ahj8FjM54V7wpY"],"license":"MPL-2.0"},"src/modules/library/RulesManagementModuleInvariantStorage.sol":{"keccak256":"0xb81ea3a54c6e8d47b87d6c3d9fb5aae80c3430021b8cd66d9adeef7f5fc95893","urls":["bzz-raw://cfcbadc2011f60de7189273c278dda1df2218aeeb153bee3b8a93447ec95df21","dweb:/ipfs/Qmem5FqCLEfBJQdJzS7Xzd3zSfyL8Muf9Wv5WvCiBVsqfh"],"license":"MPL-2.0"},"src/modules/library/TokenBindingModuleInvariantStorage.sol":{"keccak256":"0x9bab8e5b265068da356fd46e343a7c6c73776f3964fdeaeff056e8ce104d40a5","urls":["bzz-raw://e2e75d2d52b1e4f5cbb832d194266de9a1b3a8cc2101e875dce43a2664c31a05","dweb:/ipfs/QmUsd5cTPsE89WKm3kTUWsobR9JsBDUY8NdxDU5RPYpvP6"],"license":"MPL-2.0"}},"version":1},"ast":{"absolutePath":"src/deployment/ownable/RuleEngineOwnable2Step2771.sol","id":10284,"exportedSymbols":{"Context":[3248],"ERC2771Context":[1565],"ERC2771ModuleStandalone":[13340],"RuleEngineOwnable2Step":[10208],"RuleEngineOwnable2Step2771":[10283]},"nodeType":"SourceUnit","src":"37:2657:35","nodes":[{"id":10210,"nodeType":"PragmaDirective","src":"37:24:35","nodes":[],"literals":["solidity","^","0.8",".27"]},{"id":10212,"nodeType":"ImportDirective","src":"91:66:35","nodes":[],"absolutePath":"lib/openzeppelin-contracts/contracts/utils/Context.sol","file":"@openzeppelin/contracts/utils/Context.sol","nameLocation":"-1:-1:-1","scope":10284,"sourceUnit":3249,"symbolAliases":[{"foreign":{"id":10211,"name":"Context","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":3248,"src":"99:7:35","typeDescriptions":{}},"nameLocation":"-1:-1:-1"}],"unitAlias":""},{"id":10215,"nodeType":"ImportDirective","src":"181:98:35","nodes":[],"absolutePath":"src/modules/ERC2771ModuleStandalone.sol","file":"../../modules/ERC2771ModuleStandalone.sol","nameLocation":"-1:-1:-1","scope":10284,"sourceUnit":13341,"symbolAliases":[{"foreign":{"id":10213,"name":"ERC2771ModuleStandalone","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":13340,"src":"189:23:35","typeDescriptions":{}},"nameLocation":"-1:-1:-1"},{"foreign":{"id":10214,"name":"ERC2771Context","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":1565,"src":"214:14:35","typeDescriptions":{}},"nameLocation":"-1:-1:-1"}],"unitAlias":""},{"id":10217,"nodeType":"ImportDirective","src":"309:68:35","nodes":[],"absolutePath":"src/deployment/ownable/RuleEngineOwnable2Step.sol","file":"./RuleEngineOwnable2Step.sol","nameLocation":"-1:-1:-1","scope":10284,"sourceUnit":10209,"symbolAliases":[{"foreign":{"id":10216,"name":"RuleEngineOwnable2Step","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":10208,"src":"317:22:35","typeDescriptions":{}},"nameLocation":"-1:-1:-1"}],"unitAlias":""},{"id":10283,"nodeType":"ContractDefinition","src":"788:1905:35","nodes":[{"id":10240,"nodeType":"FunctionDefinition","src":"1268:195:35","nodes":[],"body":{"id":10239,"nodeType":"Block","src":"1461:2:35","nodes":[],"statements":[]},"documentation":{"id":10223,"nodeType":"StructuredDocumentation","src":"881:382:35","text":" @notice Deploys a RuleEngine with ERC-173 Ownable2Step access control and a trusted forwarder.\n @param owner_ Address of the initial contract owner (ERC-173).\n @param forwarderIrrevocable Address of the trusted ERC-2771 forwarder, immutable after construction.\n @param tokenContract Token to bind at deployment, or the zero address to bind none."},"implemented":true,"kind":"constructor","modifiers":[{"arguments":[{"id":10232,"name":"forwarderIrrevocable","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":10227,"src":"1381:20:35","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"id":10233,"kind":"baseConstructorSpecifier","modifierName":{"id":10231,"name":"ERC2771ModuleStandalone","nameLocations":["1357:23:35"],"nodeType":"IdentifierPath","referencedDeclaration":13340,"src":"1357:23:35"},"nodeType":"ModifierInvocation","src":"1357:45:35"},{"arguments":[{"id":10235,"name":"owner_","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":10225,"src":"1434:6:35","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},{"id":10236,"name":"tokenContract","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":10229,"src":"1442:13:35","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}}],"id":10237,"kind":"baseConstructorSpecifier","modifierName":{"id":10234,"name":"RuleEngineOwnable2Step","nameLocations":["1411:22:35"],"nodeType":"IdentifierPath","referencedDeclaration":10208,"src":"1411:22:35"},"nodeType":"ModifierInvocation","src":"1411:45:35"}],"name":"","nameLocation":"-1:-1:-1","parameters":{"id":10230,"nodeType":"ParameterList","parameters":[{"constant":false,"id":10225,"mutability":"mutable","name":"owner_","nameLocation":"1288:6:35","nodeType":"VariableDeclaration","scope":10240,"src":"1280:14:35","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":10224,"name":"address","nodeType":"ElementaryTypeName","src":"1280:7:35","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"},{"constant":false,"id":10227,"mutability":"mutable","name":"forwarderIrrevocable","nameLocation":"1304:20:35","nodeType":"VariableDeclaration","scope":10240,"src":"1296:28:35","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":10226,"name":"address","nodeType":"ElementaryTypeName","src":"1296:7:35","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"},{"constant":false,"id":10229,"mutability":"mutable","name":"tokenContract","nameLocation":"1334:13:35","nodeType":"VariableDeclaration","scope":10240,"src":"1326:21:35","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":10228,"name":"address","nodeType":"ElementaryTypeName","src":"1326:7:35","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"src":"1279:69:35"},"returnParameters":{"id":10238,"nodeType":"ParameterList","parameters":[],"src":"1461:0:35"},"scope":10283,"stateMutability":"nonpayable","virtual":false,"visibility":"public"},{"id":10254,"nodeType":"FunctionDefinition","src":"1854:154:35","nodes":[],"body":{"id":10253,"nodeType":"Block","src":"1957:51:35","nodes":[],"statements":[{"expression":{"arguments":[],"expression":{"argumentTypes":[],"expression":{"id":10249,"name":"ERC2771Context","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":1565,"src":"1974:14:35","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_ERC2771Context_$1565_$","typeString":"type(contract ERC2771Context)"}},"id":10250,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberLocation":"1989:10:35","memberName":"_msgSender","nodeType":"MemberAccess","referencedDeclaration":1512,"src":"1974:25:35","typeDescriptions":{"typeIdentifier":"t_function_internal_view$__$returns$_t_address_$","typeString":"function () view returns (address)"}},"id":10251,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"nameLocations":[],"names":[],"nodeType":"FunctionCall","src":"1974:27:35","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"functionReturnParameters":10248,"id":10252,"nodeType":"Return","src":"1967:34:35"}]},"baseFunctions":[1512,3230],"documentation":{"id":10241,"nodeType":"StructuredDocumentation","src":"1643:206:35","text":" @dev Resolves the sender through ERC-2771 when the call comes from the trusted forwarder.\n @return sender The transaction sender, unwrapped from the forwarder calldata when relayed."},"implemented":true,"kind":"function","modifiers":[],"name":"_msgSender","nameLocation":"1863:10:35","overrides":{"id":10245,"nodeType":"OverrideSpecifier","overrides":[{"id":10243,"name":"ERC2771Context","nameLocations":["1907:14:35"],"nodeType":"IdentifierPath","referencedDeclaration":1565,"src":"1907:14:35"},{"id":10244,"name":"Context","nameLocations":["1923:7:35"],"nodeType":"IdentifierPath","referencedDeclaration":3248,"src":"1923:7:35"}],"src":"1898:33:35"},"parameters":{"id":10242,"nodeType":"ParameterList","parameters":[],"src":"1873:2:35"},"returnParameters":{"id":10248,"nodeType":"ParameterList","parameters":[{"constant":false,"id":10247,"mutability":"mutable","name":"sender","nameLocation":"1949:6:35","nodeType":"VariableDeclaration","scope":10254,"src":"1941:14:35","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"},"typeName":{"id":10246,"name":"address","nodeType":"ElementaryTypeName","src":"1941:7:35","stateMutability":"nonpayable","typeDescriptions":{"typeIdentifier":"t_address","typeString":"address"}},"visibility":"internal"}],"src":"1940:16:35"},"scope":10283,"stateMutability":"view","virtual":true,"visibility":"internal"},{"id":10268,"nodeType":"FunctionDefinition","src":"2218:150:35","nodes":[],"body":{"id":10267,"nodeType":"Block","src":"2319:49:35","nodes":[],"statements":[{"expression":{"arguments":[],"expression":{"argumentTypes":[],"expression":{"id":10263,"name":"ERC2771Context","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":1565,"src":"2336:14:35","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_ERC2771Context_$1565_$","typeString":"type(contract ERC2771Context)"}},"id":10264,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberLocation":"2351:8:35","memberName":"_msgData","nodeType":"MemberAccess","referencedDeclaration":1554,"src":"2336:23:35","typeDescriptions":{"typeIdentifier":"t_function_internal_view$__$returns$_t_bytes_calldata_ptr_$","typeString":"function () view returns (bytes calldata)"}},"id":10265,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"nameLocations":[],"names":[],"nodeType":"FunctionCall","src":"2336:25:35","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_bytes_calldata_ptr","typeString":"bytes calldata"}},"functionReturnParameters":10262,"id":10266,"nodeType":"Return","src":"2329:32:35"}]},"baseFunctions":[1554,3239],"documentation":{"id":10255,"nodeType":"StructuredDocumentation","src":"2014:199:35","text":" @dev Resolves the calldata through ERC-2771 when the call comes from the trusted forwarder.\n @return The transaction calldata, with the appended sender stripped when relayed."},"implemented":true,"kind":"function","modifiers":[],"name":"_msgData","nameLocation":"2227:8:35","overrides":{"id":10259,"nodeType":"OverrideSpecifier","overrides":[{"id":10257,"name":"ERC2771Context","nameLocations":["2269:14:35"],"nodeType":"IdentifierPath","referencedDeclaration":1565,"src":"2269:14:35"},{"id":10258,"name":"Context","nameLocations":["2285:7:35"],"nodeType":"IdentifierPath","referencedDeclaration":3248,"src":"2285:7:35"}],"src":"2260:33:35"},"parameters":{"id":10256,"nodeType":"ParameterList","parameters":[],"src":"2235:2:35"},"returnParameters":{"id":10262,"nodeType":"ParameterList","parameters":[{"constant":false,"id":10261,"mutability":"mutable","name":"","nameLocation":"-1:-1:-1","nodeType":"VariableDeclaration","scope":10268,"src":"2303:14:35","stateVariable":false,"storageLocation":"calldata","typeDescriptions":{"typeIdentifier":"t_bytes_calldata_ptr","typeString":"bytes"},"typeName":{"id":10260,"name":"bytes","nodeType":"ElementaryTypeName","src":"2303:5:35","typeDescriptions":{"typeIdentifier":"t_bytes_storage_ptr","typeString":"bytes"}},"visibility":"internal"}],"src":"2302:16:35"},"scope":10283,"stateMutability":"view","virtual":true,"visibility":"internal"},{"id":10282,"nodeType":"FunctionDefinition","src":"2524:167:35","nodes":[],"body":{"id":10281,"nodeType":"Block","src":"2630:61:35","nodes":[],"statements":[{"expression":{"arguments":[],"expression":{"argumentTypes":[],"expression":{"id":10277,"name":"ERC2771Context","nodeType":"Identifier","overloadedDeclarations":[],"referencedDeclaration":1565,"src":"2647:14:35","typeDescriptions":{"typeIdentifier":"t_type$_t_contract$_ERC2771Context_$1565_$","typeString":"type(contract ERC2771Context)"}},"id":10278,"isConstant":false,"isLValue":false,"isPure":false,"lValueRequested":false,"memberLocation":"2662:20:35","memberName":"_contextSuffixLength","nodeType":"MemberAccess","referencedDeclaration":1564,"src":"2647:35:35","typeDescriptions":{"typeIdentifier":"t_function_internal_view$__$returns$_t_uint256_$","typeString":"function () view returns (uint256)"}},"id":10279,"isConstant":false,"isLValue":false,"isPure":false,"kind":"functionCall","lValueRequested":false,"nameLocations":[],"names":[],"nodeType":"FunctionCall","src":"2647:37:35","tryCall":false,"typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"functionReturnParameters":10276,"id":10280,"nodeType":"Return","src":"2640:44:35"}]},"baseFunctions":[1564,3247],"documentation":{"id":10269,"nodeType":"StructuredDocumentation","src":"2374:145:35","text":" @dev Length of the sender suffix appended by the trusted forwarder.\n @return The length of the ERC-2771 calldata suffix."},"implemented":true,"kind":"function","modifiers":[],"name":"_contextSuffixLength","nameLocation":"2533:20:35","overrides":{"id":10273,"nodeType":"OverrideSpecifier","overrides":[{"id":10271,"name":"ERC2771Context","nameLocations":["2587:14:35"],"nodeType":"IdentifierPath","referencedDeclaration":1565,"src":"2587:14:35"},{"id":10272,"name":"Context","nameLocations":["2603:7:35"],"nodeType":"IdentifierPath","referencedDeclaration":3248,"src":"2603:7:35"}],"src":"2578:33:35"},"parameters":{"id":10270,"nodeType":"ParameterList","parameters":[],"src":"2553:2:35"},"returnParameters":{"id":10276,"nodeType":"ParameterList","parameters":[{"constant":false,"id":10275,"mutability":"mutable","name":"","nameLocation":"-1:-1:-1","nodeType":"VariableDeclaration","scope":10282,"src":"2621:7:35","stateVariable":false,"storageLocation":"default","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"},"typeName":{"id":10274,"name":"uint256","nodeType":"ElementaryTypeName","src":"2621:7:35","typeDescriptions":{"typeIdentifier":"t_uint256","typeString":"uint256"}},"visibility":"internal"}],"src":"2620:9:35"},"scope":10283,"stateMutability":"view","virtual":true,"visibility":"internal"}],"abstract":false,"baseContracts":[{"baseName":{"id":10219,"name":"ERC2771ModuleStandalone","nameLocations":["827:23:35"],"nodeType":"IdentifierPath","referencedDeclaration":13340,"src":"827:23:35"},"id":10220,"nodeType":"InheritanceSpecifier","src":"827:23:35"},{"baseName":{"id":10221,"name":"RuleEngineOwnable2Step","nameLocations":["852:22:35"],"nodeType":"IdentifierPath","referencedDeclaration":10208,"src":"852:22:35"},"id":10222,"nodeType":"InheritanceSpecifier","src":"852:22:35"}],"canonicalName":"RuleEngineOwnable2Step2771","contractDependencies":[],"contractKind":"contract","documentation":{"id":10218,"nodeType":"StructuredDocumentation","src":"379:408:35","text":" @title Implementation of a ruleEngine with ERC-173 Ownable2Step access control and ERC-2771\n @dev {RuleEngineOwnable2Step} plus an immutable trusted forwarder: administrative calls (owner-only functions) may be\n relayed by the forwarder (gasless transactions). Token identity is never resolved through the\n forwarder: the bound-token gate and token self-binding compare the raw `msg.sender`."},"fullyImplemented":true,"linearizedBaseContracts":[10283,10208,1230,1144,9689,3578,9604,34,28,3800,14477,13390,10332,13447,14176,10545,10320,14356,14606,10476,262,464,251,311,285,13340,1565,3248,13913,10442,14580,14379,123],"name":"RuleEngineOwnable2Step2771","nameLocation":"797:26:35","scope":10284,"usedErrors":[1010,1015,14474,14476,14545,14547,14549,14551,14555,14557,14559,14596,14599,14602,14605],"usedEvents":[1021,1159,10450,10455,10490,10498,14565,14571,14574,14579]}],"license":"MPL-2.0"},"id":35} \ No newline at end of file diff --git a/doc/compilation/v3.0.0-rc7/hardhat/RuleEngine.sol/RuleEngine.dbg.json b/doc/compilation/v3.0.0-rc7/hardhat/RuleEngine.sol/RuleEngine.dbg.json new file mode 100644 index 00000000..c25ba54e --- /dev/null +++ b/doc/compilation/v3.0.0-rc7/hardhat/RuleEngine.sol/RuleEngine.dbg.json @@ -0,0 +1,4 @@ +{ + "_format": "hh-sol-dbg-1", + "buildInfo": "../../../../build-info/315e205e547361276a4bba3ad0401f98.json" +} diff --git a/doc/compilation/v3.0.0-rc7/hardhat/RuleEngine.sol/RuleEngine.json b/doc/compilation/v3.0.0-rc7/hardhat/RuleEngine.sol/RuleEngine.json new file mode 100644 index 00000000..e82474d3 --- /dev/null +++ b/doc/compilation/v3.0.0-rc7/hardhat/RuleEngine.sol/RuleEngine.json @@ -0,0 +1,1066 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "RuleEngine", + "sourceName": "src/deployment/accessControl/RuleEngine.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenContract", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "AccessControlBadConfirmation", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "neededRole", + "type": "bytes32" + } + ], + "name": "AccessControlUnauthorizedAccount", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_AdminWithAddressZeroNotAllowed", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_RuleInvalidInterface", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_RulesManagementModule_ArrayIsEmpty", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "maxRules", + "type": "uint256" + } + ], + "name": "RuleEngine_RulesManagementModule_MaxRulesExceeded", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_RulesManagementModule_MaxRulesZeroNotAllowed", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_RulesManagementModule_RuleAccountCannotReceivePrivileges", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_RulesManagementModule_RuleAddressZeroNotAllowed", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_RulesManagementModule_RuleAlreadyExists", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_RulesManagementModule_RuleDoNotMatch", + "type": "error" + }, + { + "inputs": [], + "name": "TokenBinding_InvalidTokenAddress", + "type": "error" + }, + { + "inputs": [], + "name": "TokenBinding_TokenAlreadyBound", + "type": "error" + }, + { + "inputs": [], + "name": "TokenBinding_TokenNotBound", + "type": "error" + }, + { + "inputs": [], + "name": "TokenBinding_UnauthorizedCaller", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract IRule", + "name": "rule", + "type": "address" + } + ], + "name": "AddRule", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "ClearRules", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract IRule", + "name": "rule", + "type": "address" + } + ], + "name": "RemoveRule", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "previousAdminRole", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "newAdminRole", + "type": "bytes32" + } + ], + "name": "RoleAdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "maxRules", + "type": "uint256" + } + ], + "name": "SetMaxRules", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "TokenBound", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address[]", + "name": "tokens", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "TokenSelfBindingApprovalBatchSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "TokenSelfBindingApprovalSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "TokenUnbound", + "type": "event" + }, + { + "inputs": [], + "name": "COMPLIANCE_MANAGER_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "DEFAULT_ADMIN_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "DEFAULT_MAX_RULES", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "RULES_MANAGEMENT_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IRule", + "name": "rule_", + "type": "address" + } + ], + "name": "addRule", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "bindToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "tokens", + "type": "address[]" + } + ], + "name": "bindTokens", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "canTransfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "canTransferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "clearRules", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IRule", + "name": "rule_", + "type": "address" + } + ], + "name": "containsRule", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "created", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "destroyed", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "detectTransferRestriction", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "detectTransferRestrictionFrom", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleAdmin", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "getRoleMember", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleMemberCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleMembers", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getTokenBound", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getTokenBounds", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRole", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "isTokenBound", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "isTokenSelfBindingApproved", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maxRules", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "restrictionCode", + "type": "uint8" + } + ], + "name": "messageForTransferRestriction", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IRule", + "name": "rule_", + "type": "address" + } + ], + "name": "removeRule", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "callerConfirmation", + "type": "address" + } + ], + "name": "renounceRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "ruleId", + "type": "uint256" + } + ], + "name": "rule", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "rules", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "rulesCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "maxRules_", + "type": "uint256" + } + ], + "name": "setMaxRules", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IRule[]", + "name": "rules_", + "type": "address[]" + } + ], + "name": "setRules", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setTokenSelfBindingApproval", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "tokens", + "type": "address[]" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setTokenSelfBindingApprovalBatch", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transferred", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transferred", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "unbindToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "tokens", + "type": "address[]" + } + ], + "name": "unbindTokens", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "version_", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x6080604052600a600255348015610014575f5ffd5b506040516122ef3803806122ef83398101604081905261003391610374565b6001600160a01b03821661005a57604051630872273360e21b815260040160405180910390fd5b6001600160a01b03811615610072576100728161008e565b61007c5f83610126565b50610087600a61015c565b50506103a5565b6001600160a01b0381166100b55760405163135217db60e21b815260040160405180910390fd5b6100be816101b1565b6100c96003826101dc565b6100e6576040516371b3c56560e11b815260040160405180910390fd5b6040516001600160a01b03821681527f2de35142b19ed5a07796cf30791959c592018f70b1d2d7c460eef8ffe713692b906020015b60405180910390a150565b5f8061013284846101f0565b90508015610153575f84815260076020526040902061015190846101dc565b505b90505b92915050565b805f0361017c57604051631e69e71760e21b815260040160405180910390fd5b60028190556040518181527f2292ad4720fff63e2bd104c6b1c0d72c2c729a6001c8ab4bb947cbcc511098639060200161011b565b6101bb5f82610281565b156101d9576040516302925f7360e11b815260040160405180910390fd5b50565b5f610153836001600160a01b0384166102a2565b5f6101fb83836102e7565b61027a575f8381526006602090815260408083206001600160a01b03861684529091529020805460ff191660011790556102323390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4506001610156565b505f610156565b6001600160a01b0381165f9081526001830160205260408120541515610153565b5f81815260018301602052604081205461027a57508154600181810184555f848152602080822090930184905584548482528286019093526040902091909155610156565b6001600160a01b0381165f9081527f54cdd369e4e8a8515e52ca72ec816c2101831ad1f18bf44102ed171459c9b4f8602052604081205460ff161561032e57506001610156565b505f8281526006602090815260408083206001600160a01b038516845290915290205460ff16610156565b80516001600160a01b038116811461036f575f5ffd5b919050565b5f5f60408385031215610385575f5ffd5b61038e83610359565b915061039c60208401610359565b90509250929050565b611f3d806103b25f395ff3fe608060405234801561000f575f5ffd5b5060043610610260575f3560e01c80639010d07c1161014b578063ca15c873116100bf578063db75d01711610084578063db75d0171461058e578063df21950f146105b9578063e3c4602c146105cc578063e46638e6146105df578063e54621d2146105f2578063f76bf550146105fa575f5ffd5b8063ca15c8731461051d578063d32c7bb514610530578063d4ce141514610555578063d547741f14610568578063db18af6c1461057b575f5ffd5b8063a3246ad311610110578063a3246ad3146104c1578063b043572e146104d4578063b27aef3a146104dc578063bb4b6121146104ef578063bc13eacc14610502578063c7c24b181461050a575f5ffd5b80639010d07c1461045a57806391d148541461046d578063993e8b95146104805780639b11c11514610493578063a217fddf146104ba575f5ffd5b806340db3b50116101e25780636a3edf28116101a75780636a3edf28146103e65780636ae728c6146104065780637157797f1461040e5780637f4ab1dd146104215780638baf29b4146104345780638d2ea77214610447575f5ffd5b806340db3b501461036a57806352f6747a1461037d57806354e4b9451461039257806354fd4d50146103a55780635f8dead3146103d3575f5ffd5b80633284a9a5116102285780633284a9a51461030b57806336568abe1461031e5780633a56d6d5146103315780633e5af4ca146103445780633ff5aa0214610357575f5ffd5b806301ffc9a71461026457806303c26bcd1461028c5780631455d0e7146102c1578063248a9ca3146102d65780632f2ff15d146102f8575b5f5ffd5b610277610272366004611a3e565b610602565b60405190151581526020015b60405180910390f35b6102b37fe5c50d0927e06141e032cb9a67e1d7092dc85c0b0825191f7e1cede60002856881565b604051908152602001610283565b6102d46102cf366004611aad565b610621565b005b6102b36102e4366004611aec565b5f9081526006602052604090206001015490565b6102d4610306366004611b17565b61066f565b6102d4610319366004611b52565b6106a5565b6102d461032c366004611b17565b6106de565b6102d461033f366004611aec565b610711565b6102d4610352366004611b7e565b610725565b6102d4610365366004611bcc565b61073f565b6102d4610378366004611bcc565b610751565b610385610763565b6040516102839190611be7565b6102776103a0366004611bcc565b610773565b604080518082019091526009815268332e302e302d72633760b81b60208201525b6040516102839190611c32565b6102d46103e1366004611c67565b61077e565b6103ee610791565b6040516001600160a01b039091168152602001610283565b6002546102b3565b61027761041c366004611b7e565b6107b3565b6103c661042f366004611c9f565b6107d0565b6102d4610442366004611cba565b6107db565b6102d4610455366004611c67565b6107ee565b6103ee610468366004611cf8565b610801565b61027761047b366004611b17565b61081f565b61027761048e366004611bcc565b610891565b6102b37fea5f4eb72290e50c32abd6c23e45de3d8300b3286e1cbc2e293114b92e034e5e81565b6102b35f81565b6103856104cf366004611aec565b61089d565b6102d46108b6565b6102d46104ea366004611aad565b6108c8565b6102d46104fd366004611d18565b61097b565b6102b3610a49565b6102d4610518366004611aad565b610a53565b6102b361052b366004611aec565b610a9c565b61054361053e366004611b7e565b610ab2565b60405160ff9091168152602001610283565b610543610563366004611cba565b610ac8565b6102d4610576366004611b17565b610ad4565b6103ee610589366004611aec565b610af8565b61027761059c366004611bcc565b6001600160a01b03165f9081526005602052604090205460ff1690565b6102d46105c7366004611bcc565b610b1a565b6102d46105da366004611bcc565b610b2b565b6102776105ed366004611cba565b610b6d565b610385610b86565b6102b3600a81565b5f61060c82610b92565b8061061b575061061b82610c33565b92915050565b610629610c57565b5f5b8181101561066a5761066283838381811061064857610648611d6b565b905060200201602081019061065d9190611bcc565b610c5f565b60010161062b565b505050565b6106795f82610c68565b15610697576040516302925f7360e11b815260040160405180910390fd5b6106a18282610c89565b5050565b6106ad610c57565b6001600160a01b0382166106d45760405163135217db60e21b815260040160405180910390fd5b6106a18282610cad565b6001600160a01b03811633146107075760405163334bd91960e11b815260040160405180910390fd5b61066a8282610d0b565b610719610d3e565b61072281610d48565b50565b61072d610da4565b61073984848484610dcc565b50505050565b61074881610e6e565b61072281610e77565b61075a81610e6e565b61072281610c5f565b606061076e5f610f08565b905090565b5f61061b8183610c68565b610786610da4565b6106a15f8383610f14565b5f5f61079d6003610fad565b11156107ae5761076e60035f610fb6565b505f90565b5f806107c186868686610ab2565b60ff161490505b949350505050565b606061061b82610fc1565b6107e3610da4565b61066a838383610f14565b6107f6610da4565b6106a1825f83610f14565b5f8281526007602052604081206108189083610fb6565b9392505050565b6001600160a01b0381165f9081527f54cdd369e4e8a8515e52ca72ec816c2101831ad1f18bf44102ed171459c9b4f8602052604081205460ff16156108665750600161061b565b505f8281526006602090815260408083206001600160a01b038516845290915290205460ff1661061b565b5f61061b600383610c68565b5f81815260076020526040902060609061061b90610f08565b6108be611136565b6108c6611160565b565b6108d0611136565b5f8190036108f1576040516359203cb960e01b815260040160405180910390fd5b6002548082111561092157604051630befc49d60e01b815260040161091891815260200190565b60405180910390fd5b505f61092c5f610fad565b111561093a5761093a611160565b5f5b8181101561066a5761097383838381811061095957610959611d6b565b905060200201602081019061096e9190611bcc565b611191565b60010161093c565b610983610c57565b5f5b82811015610a08575f8484838181106109a0576109a0611d6b565b90506020020160208101906109b59190611bcc565b90506001600160a01b0381166109de5760405163135217db60e21b815260040160405180910390fd5b6001600160a01b03165f908152600560205260409020805460ff1916831515179055600101610985565b507f430881f04f203566ee9b32d6444cf02e1b2a0f17ab6b4263a1ee2074d3d0f483838383604051610a3c93929190611d7f565b60405180910390a1505050565b5f61076e5f610fad565b610a5b610c57565b5f5b8181101561066a57610a94838383818110610a7a57610a7a611d6b565b9050602002016020810190610a8f9190611bcc565b610e77565b600101610a5d565b5f81815260076020526040812061061b90610fad565b5f610abf858585856111f7565b95945050505050565b5f6107c88484846112c4565b5f82815260066020526040902060010154610aee81611388565b6107398383610d0b565b5f610b025f610fad565b821015610b135761061b5f83610fb6565b505f919050565b610b22611136565b61072281611392565b610b33611136565b60025480610b405f610fad565b108190610b6357604051630befc49d60e01b815260040161091891815260200190565b506106a182611191565b5f80610b7a858585610ac8565b60ff1614949350505050565b606061076e6003610f08565b5f6001600160e01b031982166320c49ce760e01b1480610bc257506001600160e01b0319821663157094b960e31b145b80610bdd57506001600160e01b031982166378a8de7d60e01b145b80610bf857506001600160e01b03198216630c51264760e21b145b80610c1357506001600160e01b03198216633235d15f60e11b145b8061061b57506001600160e01b03198216637157797f60e01b1492915050565b5f6001600160e01b03198216635a05180f60e01b148061061b575061061b826113ef565b6108c6611423565b6107228161144d565b6001600160a01b0381165f9081526001830160205260408120541515610818565b5f82815260066020526040902060010154610ca381611388565b6107398383611495565b6001600160a01b0382165f81815260056020908152604091829020805460ff191685151590811790915591519182527f407b412a9b6db334d48445ec9bcad46fb50bc4b2e97f73e963e397101957a729910160405180910390a25050565b5f5f610d1784846114c0565b90508015610818575f848152600760205260409020610d369084611532565b509392505050565b5f61072281611388565b805f03610d6857604051631e69e71760e21b815260040160405180910390fd5b60028190556040518181527f2292ad4720fff63e2bd104c6b1c0d72c2c729a6001c8ab4bb947cbcc51109863906020015b60405180910390a150565b610daf600333610c68565b6108c657604051630599c0e960e01b815260040160405180910390fd5b5f610dd65f610fad565b90505f5b81811015610e6657610dec5f82610fb6565b604051631f2d7a6560e11b81526001600160a01b03888116600483015287811660248301528681166044830152606482018690529190911690633e5af4ca906084015f604051808303815f87803b158015610e45575f5ffd5b505af1158015610e57573d5f5f3e3d5ffd5b50505050806001019050610dda565b505050505050565b61072281611546565b6001600160a01b038116610e9e5760405163135217db60e21b815260040160405180910390fd5b610ea781611585565b610eb26003826115ad565b610ecf576040516371b3c56560e11b815260040160405180910390fd5b6040516001600160a01b03821681527f2de35142b19ed5a07796cf30791959c592018f70b1d2d7c460eef8ffe713692b90602001610d99565b60605f610818836115c1565b5f610f1e5f610fad565b90505f5b81811015610fa657610f345f82610fb6565b6040516322ebca6d60e21b81526001600160a01b0387811660048301528681166024830152604482018690529190911690638baf29b4906064015f604051808303815f87803b158015610f85575f5ffd5b505af1158015610f97573d5f5f3e3d5ffd5b50505050806001019050610f22565b5050505050565b5f61061b825490565b5f610818838361161a565b606060ff8216610ff457505060408051808201909152600d81526c2737a932b9ba3934b1ba34b7b760991b602082015290565b5f610ffe5f610fad565b90505f5b818110156110fa575f6110158183610fb6565b604051633e822efb60e11b815260ff871660048201529091506001600160a01b03821690637d045df690602401602060405180830381865afa15801561105d573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110819190611dd7565b156110f157604051637f4ab1dd60e01b815260ff861660048201526001600160a01b03821690637f4ab1dd906024015f60405180830381865afa1580156110ca573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610abf9190810190611e06565b50600101611002565b505060408051808201909152601881527f556e6b6e6f776e207265737472696374696f6e20636f64650000000000000000602082015292915050565b7fea5f4eb72290e50c32abd6c23e45de3d8300b3286e1cbc2e293114b92e034e5e61072281611388565b6040517fdbf61473843cd9be1c9791ce51ef66d0da6c9026d62ba80c1ca433b13fb729b2905f90a16108c65f611640565b61119a81611649565b6111a45f826115ad565b6111c15760405163cc790a4b60e01b815260040160405180910390fd5b6040516001600160a01b038216907f60305ce6c9104acd0969d358f926bf391174340660aaf5e6215261fd6847bf46905f90a250565b5f5f6112025f610fad565b90505f5b818110156112b8575f6112198183610fb6565b60405163d32c7bb560e01b81526001600160a01b038a811660048301528981166024830152888116604483015260648201889052919091169063d32c7bb590608401602060405180830381865afa158015611276573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061129a9190611eb9565b905060ff8116156112af5792506107c8915050565b50600101611206565b505f9695505050505050565b5f5f6112cf5f610fad565b90505f5b8181101561137d575f6112e68183610fb6565b60405163d4ce141560e01b81526001600160a01b038981166004830152888116602483015260448201889052919091169063d4ce141590606401602060405180830381865afa15801561133b573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061135f9190611eb9565b905060ff811615611374579250610818915050565b506001016112d3565b505f95945050505050565b61072281336116a1565b61139c5f82611532565b6113b957604051632cdc3a4160e21b815260040160405180910390fd5b6040516001600160a01b038216907f6d83315c9718799346b67584ec64301b1457e989c8e35a8e2982a7776c04bfc4905f90a250565b5f6001600160e01b03198216637965db0b60e01b148061061b57506301ffc9a760e01b6001600160e01b031983161461061b565b7fe5c50d0927e06141e032cb9a67e1d7092dc85c0b0825191f7e1cede60002856861072281611388565b611456816116da565b336001600160a01b0382161480159061148657506001600160a01b0381165f9081526005602052604090205460ff165b1561072257610722815f610cad565b5f5f6114a1848461173b565b90508015610818575f848152600760205260409020610d3690846115ad565b5f6114cb838361081f565b1561152b575f8381526006602090815260408083206001600160a01b0386168085529252808320805460ff1916905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a450600161061b565b505f61061b565b5f610818836001600160a01b0384166117c5565b336001600160a01b03821614801561157557506001600160a01b0381165f9081526005602052604090205460ff165b1561157d5750565b610722610c57565b61158f5f82610c68565b15610722576040516302925f7360e11b815260040160405180910390fd5b5f610818836001600160a01b0384166118a8565b6060815f0180548060200260200160405190810160405280929190818152602001828054801561160e57602002820191905f5260205f20905b8154815260200190600101908083116115fa575b50505050509050919050565b5f825f01828154811061162f5761162f611d6b565b905f5260205f200154905092915050565b610722816118ed565b61165281611946565b61165d600382610c68565b1561167b576040516302925f7360e11b815260040160405180910390fd5b6116848161196d565b61072257604051639952e34360e01b815260040160405180910390fd5b6116ab828261081f565b6106a15760405163e2517d3f60e01b81526001600160a01b038216600482015260248101839052604401610918565b6116e5600382611532565b61170257604051633477dd1760e01b815260040160405180910390fd5b6040516001600160a01b03821681527f28a4ca7134a3b3f9aff286e79ad3daadb4a06d1b43d037a3a98bdc074edd9b7a90602001610d99565b5f611746838361081f565b61152b575f8381526006602090815260408083206001600160a01b03861684529091529020805460ff1916600117905561177d3390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a450600161061b565b5f818152600183016020526040812054801561189f575f6117e7600183611ed4565b85549091505f906117fa90600190611ed4565b9050808214611859575f865f01828154811061181857611818611d6b565b905f5260205f200154905080875f01848154811061183857611838611d6b565b5f918252602080832090910192909255918252600188019052604090208390555b855486908061186a5761186a611ef3565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f90556001935050505061061b565b5f91505061061b565b5f81815260018301602052604081205461152b57508154600181810184555f84815260208082209093018490558454848252828601909352604090209190915561061b565b5f6118f6825490565b90505f5b8181101561193f57826001015f845f01838154811061191b5761191b611d6b565b905f5260205f20015481526020019081526020015f205f90558060010190506118fa565b50505f9055565b6001600160a01b0381166107225760405163f9d152fb60e01b815260040160405180910390fd5b5f611977826119aa565b61198257505f919050565b611993826358d34ba960e11b6119e9565b8061061b575061061b82632497d6cb60e01b6119e9565b5f6119bc826301ffc9a760e01b6119e9565b15610b13575f806119d5846001600160e01b0319611a0a565b915091508180156107c85750159392505050565b5f5f5f6119f68585611a0a565b91509150818015610abf5750949350505050565b6301ffc9a760e01b5f818152600483905290819060208260248188617530fa92505f511515601f3d11169150509250929050565b5f60208284031215611a4e575f5ffd5b81356001600160e01b031981168114610818575f5ffd5b5f5f83601f840112611a75575f5ffd5b50813567ffffffffffffffff811115611a8c575f5ffd5b6020830191508360208260051b8501011115611aa6575f5ffd5b9250929050565b5f5f60208385031215611abe575f5ffd5b823567ffffffffffffffff811115611ad4575f5ffd5b611ae085828601611a65565b90969095509350505050565b5f60208284031215611afc575f5ffd5b5035919050565b6001600160a01b0381168114610722575f5ffd5b5f5f60408385031215611b28575f5ffd5b823591506020830135611b3a81611b03565b809150509250929050565b8015158114610722575f5ffd5b5f5f60408385031215611b63575f5ffd5b8235611b6e81611b03565b91506020830135611b3a81611b45565b5f5f5f5f60808587031215611b91575f5ffd5b8435611b9c81611b03565b93506020850135611bac81611b03565b92506040850135611bbc81611b03565b9396929550929360600135925050565b5f60208284031215611bdc575f5ffd5b813561081881611b03565b602080825282518282018190525f918401906040840190835b81811015611c275783516001600160a01b0316835260209384019390920191600101611c00565b509095945050505050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b5f5f60408385031215611c78575f5ffd5b8235611c8381611b03565b946020939093013593505050565b60ff81168114610722575f5ffd5b5f60208284031215611caf575f5ffd5b813561081881611c91565b5f5f5f60608486031215611ccc575f5ffd5b8335611cd781611b03565b92506020840135611ce781611b03565b929592945050506040919091013590565b5f5f60408385031215611d09575f5ffd5b50508035926020909101359150565b5f5f5f60408486031215611d2a575f5ffd5b833567ffffffffffffffff811115611d40575f5ffd5b611d4c86828701611a65565b9094509250506020840135611d6081611b45565b809150509250925092565b634e487b7160e01b5f52603260045260245ffd5b604080825281018390525f8460608301825b86811015611dc1578235611da481611b03565b6001600160a01b0316825260209283019290910190600101611d91565b5080925050508215156020830152949350505050565b5f60208284031215611de7575f5ffd5b815161081881611b45565b634e487b7160e01b5f52604160045260245ffd5b5f60208284031215611e16575f5ffd5b815167ffffffffffffffff811115611e2c575f5ffd5b8201601f81018413611e3c575f5ffd5b805167ffffffffffffffff811115611e5657611e56611df2565b604051601f8201601f19908116603f0116810167ffffffffffffffff81118282101715611e8557611e85611df2565b604052818152828201602001861015611e9c575f5ffd5b8160208401602083015e5f91810160200191909152949350505050565b5f60208284031215611ec9575f5ffd5b815161081881611c91565b8181038181111561061b57634e487b7160e01b5f52601160045260245ffd5b634e487b7160e01b5f52603160045260245ffdfea2646970667358221220dcec0f9e82ca5150b252126dddf0c7407725c5e4b420725018654eee648dc3e064736f6c63430008250033", + "deployedBytecode": "0x608060405234801561000f575f5ffd5b5060043610610260575f3560e01c80639010d07c1161014b578063ca15c873116100bf578063db75d01711610084578063db75d0171461058e578063df21950f146105b9578063e3c4602c146105cc578063e46638e6146105df578063e54621d2146105f2578063f76bf550146105fa575f5ffd5b8063ca15c8731461051d578063d32c7bb514610530578063d4ce141514610555578063d547741f14610568578063db18af6c1461057b575f5ffd5b8063a3246ad311610110578063a3246ad3146104c1578063b043572e146104d4578063b27aef3a146104dc578063bb4b6121146104ef578063bc13eacc14610502578063c7c24b181461050a575f5ffd5b80639010d07c1461045a57806391d148541461046d578063993e8b95146104805780639b11c11514610493578063a217fddf146104ba575f5ffd5b806340db3b50116101e25780636a3edf28116101a75780636a3edf28146103e65780636ae728c6146104065780637157797f1461040e5780637f4ab1dd146104215780638baf29b4146104345780638d2ea77214610447575f5ffd5b806340db3b501461036a57806352f6747a1461037d57806354e4b9451461039257806354fd4d50146103a55780635f8dead3146103d3575f5ffd5b80633284a9a5116102285780633284a9a51461030b57806336568abe1461031e5780633a56d6d5146103315780633e5af4ca146103445780633ff5aa0214610357575f5ffd5b806301ffc9a71461026457806303c26bcd1461028c5780631455d0e7146102c1578063248a9ca3146102d65780632f2ff15d146102f8575b5f5ffd5b610277610272366004611a3e565b610602565b60405190151581526020015b60405180910390f35b6102b37fe5c50d0927e06141e032cb9a67e1d7092dc85c0b0825191f7e1cede60002856881565b604051908152602001610283565b6102d46102cf366004611aad565b610621565b005b6102b36102e4366004611aec565b5f9081526006602052604090206001015490565b6102d4610306366004611b17565b61066f565b6102d4610319366004611b52565b6106a5565b6102d461032c366004611b17565b6106de565b6102d461033f366004611aec565b610711565b6102d4610352366004611b7e565b610725565b6102d4610365366004611bcc565b61073f565b6102d4610378366004611bcc565b610751565b610385610763565b6040516102839190611be7565b6102776103a0366004611bcc565b610773565b604080518082019091526009815268332e302e302d72633760b81b60208201525b6040516102839190611c32565b6102d46103e1366004611c67565b61077e565b6103ee610791565b6040516001600160a01b039091168152602001610283565b6002546102b3565b61027761041c366004611b7e565b6107b3565b6103c661042f366004611c9f565b6107d0565b6102d4610442366004611cba565b6107db565b6102d4610455366004611c67565b6107ee565b6103ee610468366004611cf8565b610801565b61027761047b366004611b17565b61081f565b61027761048e366004611bcc565b610891565b6102b37fea5f4eb72290e50c32abd6c23e45de3d8300b3286e1cbc2e293114b92e034e5e81565b6102b35f81565b6103856104cf366004611aec565b61089d565b6102d46108b6565b6102d46104ea366004611aad565b6108c8565b6102d46104fd366004611d18565b61097b565b6102b3610a49565b6102d4610518366004611aad565b610a53565b6102b361052b366004611aec565b610a9c565b61054361053e366004611b7e565b610ab2565b60405160ff9091168152602001610283565b610543610563366004611cba565b610ac8565b6102d4610576366004611b17565b610ad4565b6103ee610589366004611aec565b610af8565b61027761059c366004611bcc565b6001600160a01b03165f9081526005602052604090205460ff1690565b6102d46105c7366004611bcc565b610b1a565b6102d46105da366004611bcc565b610b2b565b6102776105ed366004611cba565b610b6d565b610385610b86565b6102b3600a81565b5f61060c82610b92565b8061061b575061061b82610c33565b92915050565b610629610c57565b5f5b8181101561066a5761066283838381811061064857610648611d6b565b905060200201602081019061065d9190611bcc565b610c5f565b60010161062b565b505050565b6106795f82610c68565b15610697576040516302925f7360e11b815260040160405180910390fd5b6106a18282610c89565b5050565b6106ad610c57565b6001600160a01b0382166106d45760405163135217db60e21b815260040160405180910390fd5b6106a18282610cad565b6001600160a01b03811633146107075760405163334bd91960e11b815260040160405180910390fd5b61066a8282610d0b565b610719610d3e565b61072281610d48565b50565b61072d610da4565b61073984848484610dcc565b50505050565b61074881610e6e565b61072281610e77565b61075a81610e6e565b61072281610c5f565b606061076e5f610f08565b905090565b5f61061b8183610c68565b610786610da4565b6106a15f8383610f14565b5f5f61079d6003610fad565b11156107ae5761076e60035f610fb6565b505f90565b5f806107c186868686610ab2565b60ff161490505b949350505050565b606061061b82610fc1565b6107e3610da4565b61066a838383610f14565b6107f6610da4565b6106a1825f83610f14565b5f8281526007602052604081206108189083610fb6565b9392505050565b6001600160a01b0381165f9081527f54cdd369e4e8a8515e52ca72ec816c2101831ad1f18bf44102ed171459c9b4f8602052604081205460ff16156108665750600161061b565b505f8281526006602090815260408083206001600160a01b038516845290915290205460ff1661061b565b5f61061b600383610c68565b5f81815260076020526040902060609061061b90610f08565b6108be611136565b6108c6611160565b565b6108d0611136565b5f8190036108f1576040516359203cb960e01b815260040160405180910390fd5b6002548082111561092157604051630befc49d60e01b815260040161091891815260200190565b60405180910390fd5b505f61092c5f610fad565b111561093a5761093a611160565b5f5b8181101561066a5761097383838381811061095957610959611d6b565b905060200201602081019061096e9190611bcc565b611191565b60010161093c565b610983610c57565b5f5b82811015610a08575f8484838181106109a0576109a0611d6b565b90506020020160208101906109b59190611bcc565b90506001600160a01b0381166109de5760405163135217db60e21b815260040160405180910390fd5b6001600160a01b03165f908152600560205260409020805460ff1916831515179055600101610985565b507f430881f04f203566ee9b32d6444cf02e1b2a0f17ab6b4263a1ee2074d3d0f483838383604051610a3c93929190611d7f565b60405180910390a1505050565b5f61076e5f610fad565b610a5b610c57565b5f5b8181101561066a57610a94838383818110610a7a57610a7a611d6b565b9050602002016020810190610a8f9190611bcc565b610e77565b600101610a5d565b5f81815260076020526040812061061b90610fad565b5f610abf858585856111f7565b95945050505050565b5f6107c88484846112c4565b5f82815260066020526040902060010154610aee81611388565b6107398383610d0b565b5f610b025f610fad565b821015610b135761061b5f83610fb6565b505f919050565b610b22611136565b61072281611392565b610b33611136565b60025480610b405f610fad565b108190610b6357604051630befc49d60e01b815260040161091891815260200190565b506106a182611191565b5f80610b7a858585610ac8565b60ff1614949350505050565b606061076e6003610f08565b5f6001600160e01b031982166320c49ce760e01b1480610bc257506001600160e01b0319821663157094b960e31b145b80610bdd57506001600160e01b031982166378a8de7d60e01b145b80610bf857506001600160e01b03198216630c51264760e21b145b80610c1357506001600160e01b03198216633235d15f60e11b145b8061061b57506001600160e01b03198216637157797f60e01b1492915050565b5f6001600160e01b03198216635a05180f60e01b148061061b575061061b826113ef565b6108c6611423565b6107228161144d565b6001600160a01b0381165f9081526001830160205260408120541515610818565b5f82815260066020526040902060010154610ca381611388565b6107398383611495565b6001600160a01b0382165f81815260056020908152604091829020805460ff191685151590811790915591519182527f407b412a9b6db334d48445ec9bcad46fb50bc4b2e97f73e963e397101957a729910160405180910390a25050565b5f5f610d1784846114c0565b90508015610818575f848152600760205260409020610d369084611532565b509392505050565b5f61072281611388565b805f03610d6857604051631e69e71760e21b815260040160405180910390fd5b60028190556040518181527f2292ad4720fff63e2bd104c6b1c0d72c2c729a6001c8ab4bb947cbcc51109863906020015b60405180910390a150565b610daf600333610c68565b6108c657604051630599c0e960e01b815260040160405180910390fd5b5f610dd65f610fad565b90505f5b81811015610e6657610dec5f82610fb6565b604051631f2d7a6560e11b81526001600160a01b03888116600483015287811660248301528681166044830152606482018690529190911690633e5af4ca906084015f604051808303815f87803b158015610e45575f5ffd5b505af1158015610e57573d5f5f3e3d5ffd5b50505050806001019050610dda565b505050505050565b61072281611546565b6001600160a01b038116610e9e5760405163135217db60e21b815260040160405180910390fd5b610ea781611585565b610eb26003826115ad565b610ecf576040516371b3c56560e11b815260040160405180910390fd5b6040516001600160a01b03821681527f2de35142b19ed5a07796cf30791959c592018f70b1d2d7c460eef8ffe713692b90602001610d99565b60605f610818836115c1565b5f610f1e5f610fad565b90505f5b81811015610fa657610f345f82610fb6565b6040516322ebca6d60e21b81526001600160a01b0387811660048301528681166024830152604482018690529190911690638baf29b4906064015f604051808303815f87803b158015610f85575f5ffd5b505af1158015610f97573d5f5f3e3d5ffd5b50505050806001019050610f22565b5050505050565b5f61061b825490565b5f610818838361161a565b606060ff8216610ff457505060408051808201909152600d81526c2737a932b9ba3934b1ba34b7b760991b602082015290565b5f610ffe5f610fad565b90505f5b818110156110fa575f6110158183610fb6565b604051633e822efb60e11b815260ff871660048201529091506001600160a01b03821690637d045df690602401602060405180830381865afa15801561105d573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110819190611dd7565b156110f157604051637f4ab1dd60e01b815260ff861660048201526001600160a01b03821690637f4ab1dd906024015f60405180830381865afa1580156110ca573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610abf9190810190611e06565b50600101611002565b505060408051808201909152601881527f556e6b6e6f776e207265737472696374696f6e20636f64650000000000000000602082015292915050565b7fea5f4eb72290e50c32abd6c23e45de3d8300b3286e1cbc2e293114b92e034e5e61072281611388565b6040517fdbf61473843cd9be1c9791ce51ef66d0da6c9026d62ba80c1ca433b13fb729b2905f90a16108c65f611640565b61119a81611649565b6111a45f826115ad565b6111c15760405163cc790a4b60e01b815260040160405180910390fd5b6040516001600160a01b038216907f60305ce6c9104acd0969d358f926bf391174340660aaf5e6215261fd6847bf46905f90a250565b5f5f6112025f610fad565b90505f5b818110156112b8575f6112198183610fb6565b60405163d32c7bb560e01b81526001600160a01b038a811660048301528981166024830152888116604483015260648201889052919091169063d32c7bb590608401602060405180830381865afa158015611276573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061129a9190611eb9565b905060ff8116156112af5792506107c8915050565b50600101611206565b505f9695505050505050565b5f5f6112cf5f610fad565b90505f5b8181101561137d575f6112e68183610fb6565b60405163d4ce141560e01b81526001600160a01b038981166004830152888116602483015260448201889052919091169063d4ce141590606401602060405180830381865afa15801561133b573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061135f9190611eb9565b905060ff811615611374579250610818915050565b506001016112d3565b505f95945050505050565b61072281336116a1565b61139c5f82611532565b6113b957604051632cdc3a4160e21b815260040160405180910390fd5b6040516001600160a01b038216907f6d83315c9718799346b67584ec64301b1457e989c8e35a8e2982a7776c04bfc4905f90a250565b5f6001600160e01b03198216637965db0b60e01b148061061b57506301ffc9a760e01b6001600160e01b031983161461061b565b7fe5c50d0927e06141e032cb9a67e1d7092dc85c0b0825191f7e1cede60002856861072281611388565b611456816116da565b336001600160a01b0382161480159061148657506001600160a01b0381165f9081526005602052604090205460ff165b1561072257610722815f610cad565b5f5f6114a1848461173b565b90508015610818575f848152600760205260409020610d3690846115ad565b5f6114cb838361081f565b1561152b575f8381526006602090815260408083206001600160a01b0386168085529252808320805460ff1916905551339286917ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9190a450600161061b565b505f61061b565b5f610818836001600160a01b0384166117c5565b336001600160a01b03821614801561157557506001600160a01b0381165f9081526005602052604090205460ff165b1561157d5750565b610722610c57565b61158f5f82610c68565b15610722576040516302925f7360e11b815260040160405180910390fd5b5f610818836001600160a01b0384166118a8565b6060815f0180548060200260200160405190810160405280929190818152602001828054801561160e57602002820191905f5260205f20905b8154815260200190600101908083116115fa575b50505050509050919050565b5f825f01828154811061162f5761162f611d6b565b905f5260205f200154905092915050565b610722816118ed565b61165281611946565b61165d600382610c68565b1561167b576040516302925f7360e11b815260040160405180910390fd5b6116848161196d565b61072257604051639952e34360e01b815260040160405180910390fd5b6116ab828261081f565b6106a15760405163e2517d3f60e01b81526001600160a01b038216600482015260248101839052604401610918565b6116e5600382611532565b61170257604051633477dd1760e01b815260040160405180910390fd5b6040516001600160a01b03821681527f28a4ca7134a3b3f9aff286e79ad3daadb4a06d1b43d037a3a98bdc074edd9b7a90602001610d99565b5f611746838361081f565b61152b575f8381526006602090815260408083206001600160a01b03861684529091529020805460ff1916600117905561177d3390565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a450600161061b565b5f818152600183016020526040812054801561189f575f6117e7600183611ed4565b85549091505f906117fa90600190611ed4565b9050808214611859575f865f01828154811061181857611818611d6b565b905f5260205f200154905080875f01848154811061183857611838611d6b565b5f918252602080832090910192909255918252600188019052604090208390555b855486908061186a5761186a611ef3565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f90556001935050505061061b565b5f91505061061b565b5f81815260018301602052604081205461152b57508154600181810184555f84815260208082209093018490558454848252828601909352604090209190915561061b565b5f6118f6825490565b90505f5b8181101561193f57826001015f845f01838154811061191b5761191b611d6b565b905f5260205f20015481526020019081526020015f205f90558060010190506118fa565b50505f9055565b6001600160a01b0381166107225760405163f9d152fb60e01b815260040160405180910390fd5b5f611977826119aa565b61198257505f919050565b611993826358d34ba960e11b6119e9565b8061061b575061061b82632497d6cb60e01b6119e9565b5f6119bc826301ffc9a760e01b6119e9565b15610b13575f806119d5846001600160e01b0319611a0a565b915091508180156107c85750159392505050565b5f5f5f6119f68585611a0a565b91509150818015610abf5750949350505050565b6301ffc9a760e01b5f818152600483905290819060208260248188617530fa92505f511515601f3d11169150509250929050565b5f60208284031215611a4e575f5ffd5b81356001600160e01b031981168114610818575f5ffd5b5f5f83601f840112611a75575f5ffd5b50813567ffffffffffffffff811115611a8c575f5ffd5b6020830191508360208260051b8501011115611aa6575f5ffd5b9250929050565b5f5f60208385031215611abe575f5ffd5b823567ffffffffffffffff811115611ad4575f5ffd5b611ae085828601611a65565b90969095509350505050565b5f60208284031215611afc575f5ffd5b5035919050565b6001600160a01b0381168114610722575f5ffd5b5f5f60408385031215611b28575f5ffd5b823591506020830135611b3a81611b03565b809150509250929050565b8015158114610722575f5ffd5b5f5f60408385031215611b63575f5ffd5b8235611b6e81611b03565b91506020830135611b3a81611b45565b5f5f5f5f60808587031215611b91575f5ffd5b8435611b9c81611b03565b93506020850135611bac81611b03565b92506040850135611bbc81611b03565b9396929550929360600135925050565b5f60208284031215611bdc575f5ffd5b813561081881611b03565b602080825282518282018190525f918401906040840190835b81811015611c275783516001600160a01b0316835260209384019390920191600101611c00565b509095945050505050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b5f5f60408385031215611c78575f5ffd5b8235611c8381611b03565b946020939093013593505050565b60ff81168114610722575f5ffd5b5f60208284031215611caf575f5ffd5b813561081881611c91565b5f5f5f60608486031215611ccc575f5ffd5b8335611cd781611b03565b92506020840135611ce781611b03565b929592945050506040919091013590565b5f5f60408385031215611d09575f5ffd5b50508035926020909101359150565b5f5f5f60408486031215611d2a575f5ffd5b833567ffffffffffffffff811115611d40575f5ffd5b611d4c86828701611a65565b9094509250506020840135611d6081611b45565b809150509250925092565b634e487b7160e01b5f52603260045260245ffd5b604080825281018390525f8460608301825b86811015611dc1578235611da481611b03565b6001600160a01b0316825260209283019290910190600101611d91565b5080925050508215156020830152949350505050565b5f60208284031215611de7575f5ffd5b815161081881611b45565b634e487b7160e01b5f52604160045260245ffd5b5f60208284031215611e16575f5ffd5b815167ffffffffffffffff811115611e2c575f5ffd5b8201601f81018413611e3c575f5ffd5b805167ffffffffffffffff811115611e5657611e56611df2565b604051601f8201601f19908116603f0116810167ffffffffffffffff81118282101715611e8557611e85611df2565b604052818152828201602001861015611e9c575f5ffd5b8160208401602083015e5f91810160200191909152949350505050565b5f60208284031215611ec9575f5ffd5b815161081881611c91565b8181038181111561061b57634e487b7160e01b5f52601160045260245ffd5b634e487b7160e01b5f52603160045260245ffdfea2646970667358221220dcec0f9e82ca5150b252126dddf0c7407725c5e4b420725018654eee648dc3e064736f6c63430008250033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/doc/compilation/v3.0.0-rc7/hardhat/RuleEngine2771.sol/RuleEngine2771.dbg.json b/doc/compilation/v3.0.0-rc7/hardhat/RuleEngine2771.sol/RuleEngine2771.dbg.json new file mode 100644 index 00000000..c25ba54e --- /dev/null +++ b/doc/compilation/v3.0.0-rc7/hardhat/RuleEngine2771.sol/RuleEngine2771.dbg.json @@ -0,0 +1,4 @@ +{ + "_format": "hh-sol-dbg-1", + "buildInfo": "../../../../build-info/315e205e547361276a4bba3ad0401f98.json" +} diff --git a/doc/compilation/v3.0.0-rc7/hardhat/RuleEngine2771.sol/RuleEngine2771.json b/doc/compilation/v3.0.0-rc7/hardhat/RuleEngine2771.sol/RuleEngine2771.json new file mode 100644 index 00000000..3fefb663 --- /dev/null +++ b/doc/compilation/v3.0.0-rc7/hardhat/RuleEngine2771.sol/RuleEngine2771.json @@ -0,0 +1,1103 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "RuleEngine2771", + "sourceName": "src/deployment/accessControl/RuleEngine2771.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "admin", + "type": "address" + }, + { + "internalType": "address", + "name": "forwarderIrrevocable", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenContract", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [], + "name": "AccessControlBadConfirmation", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "internalType": "bytes32", + "name": "neededRole", + "type": "bytes32" + } + ], + "name": "AccessControlUnauthorizedAccount", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_AdminWithAddressZeroNotAllowed", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_RuleInvalidInterface", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_RulesManagementModule_ArrayIsEmpty", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "maxRules", + "type": "uint256" + } + ], + "name": "RuleEngine_RulesManagementModule_MaxRulesExceeded", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_RulesManagementModule_MaxRulesZeroNotAllowed", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_RulesManagementModule_RuleAccountCannotReceivePrivileges", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_RulesManagementModule_RuleAddressZeroNotAllowed", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_RulesManagementModule_RuleAlreadyExists", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_RulesManagementModule_RuleDoNotMatch", + "type": "error" + }, + { + "inputs": [], + "name": "TokenBinding_InvalidTokenAddress", + "type": "error" + }, + { + "inputs": [], + "name": "TokenBinding_TokenAlreadyBound", + "type": "error" + }, + { + "inputs": [], + "name": "TokenBinding_TokenNotBound", + "type": "error" + }, + { + "inputs": [], + "name": "TokenBinding_UnauthorizedCaller", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract IRule", + "name": "rule", + "type": "address" + } + ], + "name": "AddRule", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "ClearRules", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract IRule", + "name": "rule", + "type": "address" + } + ], + "name": "RemoveRule", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "previousAdminRole", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "bytes32", + "name": "newAdminRole", + "type": "bytes32" + } + ], + "name": "RoleAdminChanged", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleGranted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "indexed": true, + "internalType": "address", + "name": "account", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "sender", + "type": "address" + } + ], + "name": "RoleRevoked", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "maxRules", + "type": "uint256" + } + ], + "name": "SetMaxRules", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "TokenBound", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address[]", + "name": "tokens", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "TokenSelfBindingApprovalBatchSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "TokenSelfBindingApprovalSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "TokenUnbound", + "type": "event" + }, + { + "inputs": [], + "name": "COMPLIANCE_MANAGER_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "DEFAULT_ADMIN_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "DEFAULT_MAX_RULES", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "RULES_MANAGEMENT_ROLE", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IRule", + "name": "rule_", + "type": "address" + } + ], + "name": "addRule", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "bindToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "tokens", + "type": "address[]" + } + ], + "name": "bindTokens", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "canTransfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "canTransferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "clearRules", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IRule", + "name": "rule_", + "type": "address" + } + ], + "name": "containsRule", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "created", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "destroyed", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "detectTransferRestriction", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "detectTransferRestrictionFrom", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleAdmin", + "outputs": [ + { + "internalType": "bytes32", + "name": "", + "type": "bytes32" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "uint256", + "name": "index", + "type": "uint256" + } + ], + "name": "getRoleMember", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleMemberCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + } + ], + "name": "getRoleMembers", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getTokenBound", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getTokenBounds", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "grantRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "hasRole", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "isTokenBound", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "isTokenSelfBindingApproved", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "forwarder", + "type": "address" + } + ], + "name": "isTrustedForwarder", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maxRules", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "restrictionCode", + "type": "uint8" + } + ], + "name": "messageForTransferRestriction", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IRule", + "name": "rule_", + "type": "address" + } + ], + "name": "removeRule", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "callerConfirmation", + "type": "address" + } + ], + "name": "renounceRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes32", + "name": "role", + "type": "bytes32" + }, + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "revokeRole", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "ruleId", + "type": "uint256" + } + ], + "name": "rule", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "rules", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "rulesCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "maxRules_", + "type": "uint256" + } + ], + "name": "setMaxRules", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IRule[]", + "name": "rules_", + "type": "address[]" + } + ], + "name": "setRules", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setTokenSelfBindingApproval", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "tokens", + "type": "address[]" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setTokenSelfBindingApprovalBatch", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transferred", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transferred", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "trustedForwarder", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "unbindToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "tokens", + "type": "address[]" + } + ], + "name": "unbindTokens", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "version_", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x60a0604052600a600255348015610014575f5ffd5b50604051612590380380612590833981016040819052610033916103fb565b6001600160a01b0380831660805283908290821661006457604051630872273360e21b815260040160405180910390fd5b6001600160a01b0381161561007c5761007c8161009b565b6100865f83610133565b50610091600a610169565b505050505061049a565b6001600160a01b0381166100c25760405163135217db60e21b815260040160405180910390fd5b6100cb816101be565b6100d66003826101e9565b6100f3576040516371b3c56560e11b815260040160405180910390fd5b6040516001600160a01b03821681527f2de35142b19ed5a07796cf30791959c592018f70b1d2d7c460eef8ffe713692b906020015b60405180910390a150565b5f8061013f84846101fd565b90508015610160575f84815260076020526040902061015e90846101e9565b505b90505b92915050565b805f0361018957604051631e69e71760e21b815260040160405180910390fd5b60028190556040518181527f2292ad4720fff63e2bd104c6b1c0d72c2c729a6001c8ab4bb947cbcc5110986390602001610128565b6101c85f8261028f565b156101e6576040516302925f7360e11b815260040160405180910390fd5b50565b5f610160836001600160a01b0384166102b0565b5f61020883836102f5565b610288575f8381526006602090815260408083206001600160a01b03861684529091529020805460ff19166001179055610240610367565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4506001610163565b505f610163565b6001600160a01b0381165f9081526001830160205260408120541515610160565b5f81815260018301602052604081205461028857508154600181810184555f848152602080822090930184905584548482528286019093526040902091909155610163565b6001600160a01b0381165f9081527f54cdd369e4e8a8515e52ca72ec816c2101831ad1f18bf44102ed171459c9b4f8602052604081205460ff161561033c57506001610163565b505f8281526006602090815260408083206001600160a01b038516845290915290205460ff16610163565b5f610370610375565b905090565b5f36601480821080159061038d575061038d336103bb565b156103b3576103a036828403815f61043b565b6103a991610462565b60601c9250505090565b339250505090565b5f6103c560805190565b6001600160a01b0316826001600160a01b0316149050919050565b80516001600160a01b03811681146103f6575f5ffd5b919050565b5f5f5f6060848603121561040d575f5ffd5b610416846103e0565b9250610424602085016103e0565b9150610432604085016103e0565b90509250925092565b5f5f85851115610449575f5ffd5b83861115610455575f5ffd5b5050820193919092039150565b80356001600160601b03198116906014841015610493576001600160601b0319601485900360031b81901b82161691505b5092915050565b6080516120d06104c05f395f81816103f901528181610479015261156d01526120d05ff3fe608060405234801561000f575f5ffd5b5060043610610276575f3560e01c80638d2ea77211610156578063c7c24b18116100ca578063db75d01711610084578063db75d0171461060a578063df21950f14610635578063e3c4602c14610648578063e46638e61461065b578063e54621d21461066e578063f76bf55014610676575f5ffd5b8063c7c24b1814610586578063ca15c87314610599578063d32c7bb5146105ac578063d4ce1415146105d1578063d547741f146105e4578063db18af6c146105f7575f5ffd5b8063a217fddf1161011b578063a217fddf14610536578063a3246ad31461053d578063b043572e14610550578063b27aef3a14610558578063bb4b61211461056b578063bc13eacc1461057e575f5ffd5b80638d2ea772146104c35780639010d07c146104d657806391d14854146104e9578063993e8b95146104fc5780639b11c1151461050f575f5ffd5b806352f6747a116101ed5780636a3edf28116101b25780636a3edf281461043c5780636ae728c61461045c5780637157797f146104645780637da0a877146104775780637f4ab1dd1461049d5780638baf29b4146104b0575f5ffd5b806352f6747a1461039357806354e4b945146103a857806354fd4d50146103bb578063572b6c05146103e95780635f8dead314610429575f5ffd5b80633284a9a51161023e5780633284a9a51461032157806336568abe146103345780633a56d6d5146103475780633e5af4ca1461035a5780633ff5aa021461036d57806340db3b5014610380575f5ffd5b806301ffc9a71461027a57806303c26bcd146102a25780631455d0e7146102d7578063248a9ca3146102ec5780632f2ff15d1461030e575b5f5ffd5b61028d610288366004611b6a565b61067e565b60405190151581526020015b60405180910390f35b6102c97fe5c50d0927e06141e032cb9a67e1d7092dc85c0b0825191f7e1cede60002856881565b604051908152602001610299565b6102ea6102e5366004611bd9565b61069d565b005b6102c96102fa366004611c18565b5f9081526006602052604090206001015490565b6102ea61031c366004611c43565b6106eb565b6102ea61032f366004611c7e565b610721565b6102ea610342366004611c43565b61075a565b6102ea610355366004611c18565b61079d565b6102ea610368366004611caa565b6107b1565b6102ea61037b366004611cf8565b6107cb565b6102ea61038e366004611cf8565b6107dd565b61039b6107ef565b6040516102999190611d13565b61028d6103b6366004611cf8565b6107ff565b604080518082019091526009815268332e302e302d72633760b81b60208201525b6040516102999190611d5e565b61028d6103f7366004611cf8565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0390811691161490565b6102ea610437366004611d93565b61080a565b61044461081d565b6040516001600160a01b039091168152602001610299565b6002546102c9565b61028d610472366004611caa565b61083f565b7f0000000000000000000000000000000000000000000000000000000000000000610444565b6103dc6104ab366004611dcb565b61085c565b6102ea6104be366004611de6565b610867565b6102ea6104d1366004611d93565b61087a565b6104446104e4366004611e24565b61088d565b61028d6104f7366004611c43565b6108ab565b61028d61050a366004611cf8565b61091d565b6102c97fea5f4eb72290e50c32abd6c23e45de3d8300b3286e1cbc2e293114b92e034e5e81565b6102c95f81565b61039b61054b366004611c18565b610929565b6102ea610942565b6102ea610566366004611bd9565b610954565b6102ea610579366004611e44565b610a07565b6102c9610ad5565b6102ea610594366004611bd9565b610adf565b6102c96105a7366004611c18565b610b28565b6105bf6105ba366004611caa565b610b3e565b60405160ff9091168152602001610299565b6105bf6105df366004611de6565b610b54565b6102ea6105f2366004611c43565b610b60565b610444610605366004611c18565b610b84565b61028d610618366004611cf8565b6001600160a01b03165f9081526005602052604090205460ff1690565b6102ea610643366004611cf8565b610ba6565b6102ea610656366004611cf8565b610bb7565b61028d610669366004611de6565b610bf9565b61039b610c12565b6102c9600a81565b5f61068882610c1e565b80610697575061069782610cbf565b92915050565b6106a5610ce3565b5f5b818110156106e6576106de8383838181106106c4576106c4611e97565b90506020020160208101906106d99190611cf8565b610ceb565b6001016106a7565b505050565b6106f55f82610cf4565b15610713576040516302925f7360e11b815260040160405180910390fd5b61071d8282610d15565b5050565b610729610ce3565b6001600160a01b0382166107505760405163135217db60e21b815260040160405180910390fd5b61071d8282610d39565b610762610d97565b6001600160a01b0316816001600160a01b0316146107935760405163334bd91960e11b815260040160405180910390fd5b6106e68282610da0565b6107a5610dd3565b6107ae81610ddd565b50565b6107b9610e39565b6107c584848484610e61565b50505050565b6107d481610f03565b6107ae81610f0c565b6107e681610f03565b6107ae81610ceb565b60606107fa5f610f9d565b905090565b5f6106978183610cf4565b610812610e39565b61071d5f8383610fa9565b5f5f6108296003611042565b111561083a576107fa60035f61104b565b505f90565b5f8061084d86868686610b3e565b60ff161490505b949350505050565b606061069782611056565b61086f610e39565b6106e6838383610fa9565b610882610e39565b61071d825f83610fa9565b5f8281526007602052604081206108a4908361104b565b9392505050565b6001600160a01b0381165f9081527f54cdd369e4e8a8515e52ca72ec816c2101831ad1f18bf44102ed171459c9b4f8602052604081205460ff16156108f257506001610697565b505f8281526006602090815260408083206001600160a01b038516845290915290205460ff16610697565b5f610697600383610cf4565b5f81815260076020526040902060609061069790610f9d565b61094a6111cb565b6109526111f5565b565b61095c6111cb565b5f81900361097d576040516359203cb960e01b815260040160405180910390fd5b600254808211156109ad57604051630befc49d60e01b81526004016109a491815260200190565b60405180910390fd5b505f6109b85f611042565b11156109c6576109c66111f5565b5f5b818110156106e6576109ff8383838181106109e5576109e5611e97565b90506020020160208101906109fa9190611cf8565b611226565b6001016109c8565b610a0f610ce3565b5f5b82811015610a94575f848483818110610a2c57610a2c611e97565b9050602002016020810190610a419190611cf8565b90506001600160a01b038116610a6a5760405163135217db60e21b815260040160405180910390fd5b6001600160a01b03165f908152600560205260409020805460ff1916831515179055600101610a11565b507f430881f04f203566ee9b32d6444cf02e1b2a0f17ab6b4263a1ee2074d3d0f483838383604051610ac893929190611eab565b60405180910390a1505050565b5f6107fa5f611042565b610ae7610ce3565b5f5b818110156106e657610b20838383818110610b0657610b06611e97565b9050602002016020810190610b1b9190611cf8565b610f0c565b600101610ae9565b5f81815260076020526040812061069790611042565b5f610b4b8585858561128c565b95945050505050565b5f610854848484611359565b5f82815260066020526040902060010154610b7a8161141d565b6107c58383610da0565b5f610b8e5f611042565b821015610b9f576106975f8361104b565b505f919050565b610bae6111cb565b6107ae8161142e565b610bbf6111cb565b60025480610bcc5f611042565b108190610bef57604051630befc49d60e01b81526004016109a491815260200190565b5061071d82611226565b5f80610c06858585610b54565b60ff1614949350505050565b60606107fa6003610f9d565b5f6001600160e01b031982166320c49ce760e01b1480610c4e57506001600160e01b0319821663157094b960e31b145b80610c6957506001600160e01b031982166378a8de7d60e01b145b80610c8457506001600160e01b03198216630c51264760e21b145b80610c9f57506001600160e01b03198216633235d15f60e11b145b8061069757506001600160e01b03198216637157797f60e01b1492915050565b5f6001600160e01b03198216635a05180f60e01b148061069757506106978261148b565b6109526114bf565b6107ae816114e9565b6001600160a01b0381165f90815260018301602052604081205415156108a4565b5f82815260066020526040902060010154610d2f8161141d565b6107c58383611531565b6001600160a01b0382165f81815260056020908152604091829020805460ff191685151590811790915591519182527f407b412a9b6db334d48445ec9bcad46fb50bc4b2e97f73e963e397101957a729910160405180910390a25050565b5f6107fa61155c565b5f5f610dac84846115c6565b905080156108a4575f848152600760205260409020610dcb9084611656565b509392505050565b5f6107ae8161141d565b805f03610dfd57604051631e69e71760e21b815260040160405180910390fd5b60028190556040518181527f2292ad4720fff63e2bd104c6b1c0d72c2c729a6001c8ab4bb947cbcc51109863906020015b60405180910390a150565b610e44600333610cf4565b61095257604051630599c0e960e01b815260040160405180910390fd5b5f610e6b5f611042565b90505f5b81811015610efb57610e815f8261104b565b604051631f2d7a6560e11b81526001600160a01b03888116600483015287811660248301528681166044830152606482018690529190911690633e5af4ca906084015f604051808303815f87803b158015610eda575f5ffd5b505af1158015610eec573d5f5f3e3d5ffd5b50505050806001019050610e6f565b505050505050565b6107ae8161166a565b6001600160a01b038116610f335760405163135217db60e21b815260040160405180910390fd5b610f3c816116a9565b610f476003826116d1565b610f64576040516371b3c56560e11b815260040160405180910390fd5b6040516001600160a01b03821681527f2de35142b19ed5a07796cf30791959c592018f70b1d2d7c460eef8ffe713692b90602001610e2e565b60605f6108a4836116e5565b5f610fb35f611042565b90505f5b8181101561103b57610fc95f8261104b565b6040516322ebca6d60e21b81526001600160a01b0387811660048301528681166024830152604482018690529190911690638baf29b4906064015f604051808303815f87803b15801561101a575f5ffd5b505af115801561102c573d5f5f3e3d5ffd5b50505050806001019050610fb7565b5050505050565b5f610697825490565b5f6108a4838361173e565b606060ff821661108957505060408051808201909152600d81526c2737a932b9ba3934b1ba34b7b760991b602082015290565b5f6110935f611042565b90505f5b8181101561118f575f6110aa818361104b565b604051633e822efb60e11b815260ff871660048201529091506001600160a01b03821690637d045df690602401602060405180830381865afa1580156110f2573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111169190611f03565b1561118657604051637f4ab1dd60e01b815260ff861660048201526001600160a01b03821690637f4ab1dd906024015f60405180830381865afa15801561115f573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610b4b9190810190611f32565b50600101611097565b505060408051808201909152601881527f556e6b6e6f776e207265737472696374696f6e20636f64650000000000000000602082015292915050565b7fea5f4eb72290e50c32abd6c23e45de3d8300b3286e1cbc2e293114b92e034e5e6107ae8161141d565b6040517fdbf61473843cd9be1c9791ce51ef66d0da6c9026d62ba80c1ca433b13fb729b2905f90a16109525f611764565b61122f8161176d565b6112395f826116d1565b6112565760405163cc790a4b60e01b815260040160405180910390fd5b6040516001600160a01b038216907f60305ce6c9104acd0969d358f926bf391174340660aaf5e6215261fd6847bf46905f90a250565b5f5f6112975f611042565b90505f5b8181101561134d575f6112ae818361104b565b60405163d32c7bb560e01b81526001600160a01b038a811660048301528981166024830152888116604483015260648201889052919091169063d32c7bb590608401602060405180830381865afa15801561130b573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061132f9190611fe5565b905060ff811615611344579250610854915050565b5060010161129b565b505f9695505050505050565b5f5f6113645f611042565b90505f5b81811015611412575f61137b818361104b565b60405163d4ce141560e01b81526001600160a01b038981166004830152888116602483015260448201889052919091169063d4ce141590606401602060405180830381865afa1580156113d0573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906113f49190611fe5565b905060ff8116156114095792506108a4915050565b50600101611368565b505f95945050505050565b6107ae81611429610d97565b6117c5565b6114385f82611656565b61145557604051632cdc3a4160e21b815260040160405180910390fd5b6040516001600160a01b038216907f6d83315c9718799346b67584ec64301b1457e989c8e35a8e2982a7776c04bfc4905f90a250565b5f6001600160e01b03198216637965db0b60e01b148061069757506301ffc9a760e01b6001600160e01b0319831614610697565b7fe5c50d0927e06141e032cb9a67e1d7092dc85c0b0825191f7e1cede6000285686107ae8161141d565b6114f2816117fe565b336001600160a01b0382161480159061152257506001600160a01b0381165f9081526005602052604090205460ff165b156107ae576107ae815f610d39565b5f5f61153d848461185f565b905080156108a4575f848152600760205260409020610dcb90846116d1565b5f36601480821080159061159857507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031633145b156115be576115ab36828403815f612000565b6115b491612027565b60601c9250505090565b339250505090565b5f6115d183836108ab565b1561164f575f8381526006602090815260408083206001600160a01b03861684529091529020805460ff19169055611607610d97565b6001600160a01b0316826001600160a01b0316847ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a4506001610697565b505f610697565b5f6108a4836001600160a01b0384166118ea565b336001600160a01b03821614801561169957506001600160a01b0381165f9081526005602052604090205460ff165b156116a15750565b6107ae610ce3565b6116b35f82610cf4565b156107ae576040516302925f7360e11b815260040160405180910390fd5b5f6108a4836001600160a01b0384166119d4565b6060815f0180548060200260200160405190810160405280929190818152602001828054801561173257602002820191905f5260205f20905b81548152602001906001019080831161171e575b50505050509050919050565b5f825f01828154811061175357611753611e97565b905f5260205f200154905092915050565b6107ae81611a19565b61177681611a72565b611781600382610cf4565b1561179f576040516302925f7360e11b815260040160405180910390fd5b6117a881611a99565b6107ae57604051639952e34360e01b815260040160405180910390fd5b6117cf82826108ab565b61071d5760405163e2517d3f60e01b81526001600160a01b0382166004820152602481018390526044016109a4565b611809600382611656565b61182657604051633477dd1760e01b815260040160405180910390fd5b6040516001600160a01b03821681527f28a4ca7134a3b3f9aff286e79ad3daadb4a06d1b43d037a3a98bdc074edd9b7a90602001610e2e565b5f61186a83836108ab565b61164f575f8381526006602090815260408083206001600160a01b03861684529091529020805460ff191660011790556118a2610d97565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4506001610697565b5f81815260018301602052604081205480156119c4575f61190c600183612067565b85549091505f9061191f90600190612067565b905080821461197e575f865f01828154811061193d5761193d611e97565b905f5260205f200154905080875f01848154811061195d5761195d611e97565b5f918252602080832090910192909255918252600188019052604090208390555b855486908061198f5761198f612086565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f905560019350505050610697565b5f915050610697565b5092915050565b5f81815260018301602052604081205461164f57508154600181810184555f848152602080822090930184905584548482528286019093526040902091909155610697565b5f611a22825490565b90505f5b81811015611a6b57826001015f845f018381548110611a4757611a47611e97565b905f5260205f20015481526020019081526020015f205f9055806001019050611a26565b50505f9055565b6001600160a01b0381166107ae5760405163f9d152fb60e01b815260040160405180910390fd5b5f611aa382611ad6565b611aae57505f919050565b611abf826358d34ba960e11b611b15565b80610697575061069782632497d6cb60e01b611b15565b5f611ae8826301ffc9a760e01b611b15565b15610b9f575f80611b01846001600160e01b0319611b36565b915091508180156108545750159392505050565b5f5f5f611b228585611b36565b91509150818015610b4b5750949350505050565b6301ffc9a760e01b5f818152600483905290819060208260248188617530fa92505f511515601f3d11169150509250929050565b5f60208284031215611b7a575f5ffd5b81356001600160e01b0319811681146108a4575f5ffd5b5f5f83601f840112611ba1575f5ffd5b50813567ffffffffffffffff811115611bb8575f5ffd5b6020830191508360208260051b8501011115611bd2575f5ffd5b9250929050565b5f5f60208385031215611bea575f5ffd5b823567ffffffffffffffff811115611c00575f5ffd5b611c0c85828601611b91565b90969095509350505050565b5f60208284031215611c28575f5ffd5b5035919050565b6001600160a01b03811681146107ae575f5ffd5b5f5f60408385031215611c54575f5ffd5b823591506020830135611c6681611c2f565b809150509250929050565b80151581146107ae575f5ffd5b5f5f60408385031215611c8f575f5ffd5b8235611c9a81611c2f565b91506020830135611c6681611c71565b5f5f5f5f60808587031215611cbd575f5ffd5b8435611cc881611c2f565b93506020850135611cd881611c2f565b92506040850135611ce881611c2f565b9396929550929360600135925050565b5f60208284031215611d08575f5ffd5b81356108a481611c2f565b602080825282518282018190525f918401906040840190835b81811015611d535783516001600160a01b0316835260209384019390920191600101611d2c565b509095945050505050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b5f5f60408385031215611da4575f5ffd5b8235611daf81611c2f565b946020939093013593505050565b60ff811681146107ae575f5ffd5b5f60208284031215611ddb575f5ffd5b81356108a481611dbd565b5f5f5f60608486031215611df8575f5ffd5b8335611e0381611c2f565b92506020840135611e1381611c2f565b929592945050506040919091013590565b5f5f60408385031215611e35575f5ffd5b50508035926020909101359150565b5f5f5f60408486031215611e56575f5ffd5b833567ffffffffffffffff811115611e6c575f5ffd5b611e7886828701611b91565b9094509250506020840135611e8c81611c71565b809150509250925092565b634e487b7160e01b5f52603260045260245ffd5b604080825281018390525f8460608301825b86811015611eed578235611ed081611c2f565b6001600160a01b0316825260209283019290910190600101611ebd565b5080925050508215156020830152949350505050565b5f60208284031215611f13575f5ffd5b81516108a481611c71565b634e487b7160e01b5f52604160045260245ffd5b5f60208284031215611f42575f5ffd5b815167ffffffffffffffff811115611f58575f5ffd5b8201601f81018413611f68575f5ffd5b805167ffffffffffffffff811115611f8257611f82611f1e565b604051601f8201601f19908116603f0116810167ffffffffffffffff81118282101715611fb157611fb1611f1e565b604052818152828201602001861015611fc8575f5ffd5b8160208401602083015e5f91810160200191909152949350505050565b5f60208284031215611ff5575f5ffd5b81516108a481611dbd565b5f5f8585111561200e575f5ffd5b8386111561201a575f5ffd5b5050820193919092039150565b80356bffffffffffffffffffffffff1981169060148410156119cd576bffffffffffffffffffffffff1960149490940360031b84901b1690921692915050565b8181038181111561069757634e487b7160e01b5f52601160045260245ffd5b634e487b7160e01b5f52603160045260245ffdfea26469706673582212204cc6d4f8ac0adf6c88fe67343897a0d2c4402c1bafcf0801c24ebf9dc6a2b48064736f6c63430008250033", + "deployedBytecode": "0x608060405234801561000f575f5ffd5b5060043610610276575f3560e01c80638d2ea77211610156578063c7c24b18116100ca578063db75d01711610084578063db75d0171461060a578063df21950f14610635578063e3c4602c14610648578063e46638e61461065b578063e54621d21461066e578063f76bf55014610676575f5ffd5b8063c7c24b1814610586578063ca15c87314610599578063d32c7bb5146105ac578063d4ce1415146105d1578063d547741f146105e4578063db18af6c146105f7575f5ffd5b8063a217fddf1161011b578063a217fddf14610536578063a3246ad31461053d578063b043572e14610550578063b27aef3a14610558578063bb4b61211461056b578063bc13eacc1461057e575f5ffd5b80638d2ea772146104c35780639010d07c146104d657806391d14854146104e9578063993e8b95146104fc5780639b11c1151461050f575f5ffd5b806352f6747a116101ed5780636a3edf28116101b25780636a3edf281461043c5780636ae728c61461045c5780637157797f146104645780637da0a877146104775780637f4ab1dd1461049d5780638baf29b4146104b0575f5ffd5b806352f6747a1461039357806354e4b945146103a857806354fd4d50146103bb578063572b6c05146103e95780635f8dead314610429575f5ffd5b80633284a9a51161023e5780633284a9a51461032157806336568abe146103345780633a56d6d5146103475780633e5af4ca1461035a5780633ff5aa021461036d57806340db3b5014610380575f5ffd5b806301ffc9a71461027a57806303c26bcd146102a25780631455d0e7146102d7578063248a9ca3146102ec5780632f2ff15d1461030e575b5f5ffd5b61028d610288366004611b6a565b61067e565b60405190151581526020015b60405180910390f35b6102c97fe5c50d0927e06141e032cb9a67e1d7092dc85c0b0825191f7e1cede60002856881565b604051908152602001610299565b6102ea6102e5366004611bd9565b61069d565b005b6102c96102fa366004611c18565b5f9081526006602052604090206001015490565b6102ea61031c366004611c43565b6106eb565b6102ea61032f366004611c7e565b610721565b6102ea610342366004611c43565b61075a565b6102ea610355366004611c18565b61079d565b6102ea610368366004611caa565b6107b1565b6102ea61037b366004611cf8565b6107cb565b6102ea61038e366004611cf8565b6107dd565b61039b6107ef565b6040516102999190611d13565b61028d6103b6366004611cf8565b6107ff565b604080518082019091526009815268332e302e302d72633760b81b60208201525b6040516102999190611d5e565b61028d6103f7366004611cf8565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0390811691161490565b6102ea610437366004611d93565b61080a565b61044461081d565b6040516001600160a01b039091168152602001610299565b6002546102c9565b61028d610472366004611caa565b61083f565b7f0000000000000000000000000000000000000000000000000000000000000000610444565b6103dc6104ab366004611dcb565b61085c565b6102ea6104be366004611de6565b610867565b6102ea6104d1366004611d93565b61087a565b6104446104e4366004611e24565b61088d565b61028d6104f7366004611c43565b6108ab565b61028d61050a366004611cf8565b61091d565b6102c97fea5f4eb72290e50c32abd6c23e45de3d8300b3286e1cbc2e293114b92e034e5e81565b6102c95f81565b61039b61054b366004611c18565b610929565b6102ea610942565b6102ea610566366004611bd9565b610954565b6102ea610579366004611e44565b610a07565b6102c9610ad5565b6102ea610594366004611bd9565b610adf565b6102c96105a7366004611c18565b610b28565b6105bf6105ba366004611caa565b610b3e565b60405160ff9091168152602001610299565b6105bf6105df366004611de6565b610b54565b6102ea6105f2366004611c43565b610b60565b610444610605366004611c18565b610b84565b61028d610618366004611cf8565b6001600160a01b03165f9081526005602052604090205460ff1690565b6102ea610643366004611cf8565b610ba6565b6102ea610656366004611cf8565b610bb7565b61028d610669366004611de6565b610bf9565b61039b610c12565b6102c9600a81565b5f61068882610c1e565b80610697575061069782610cbf565b92915050565b6106a5610ce3565b5f5b818110156106e6576106de8383838181106106c4576106c4611e97565b90506020020160208101906106d99190611cf8565b610ceb565b6001016106a7565b505050565b6106f55f82610cf4565b15610713576040516302925f7360e11b815260040160405180910390fd5b61071d8282610d15565b5050565b610729610ce3565b6001600160a01b0382166107505760405163135217db60e21b815260040160405180910390fd5b61071d8282610d39565b610762610d97565b6001600160a01b0316816001600160a01b0316146107935760405163334bd91960e11b815260040160405180910390fd5b6106e68282610da0565b6107a5610dd3565b6107ae81610ddd565b50565b6107b9610e39565b6107c584848484610e61565b50505050565b6107d481610f03565b6107ae81610f0c565b6107e681610f03565b6107ae81610ceb565b60606107fa5f610f9d565b905090565b5f6106978183610cf4565b610812610e39565b61071d5f8383610fa9565b5f5f6108296003611042565b111561083a576107fa60035f61104b565b505f90565b5f8061084d86868686610b3e565b60ff161490505b949350505050565b606061069782611056565b61086f610e39565b6106e6838383610fa9565b610882610e39565b61071d825f83610fa9565b5f8281526007602052604081206108a4908361104b565b9392505050565b6001600160a01b0381165f9081527f54cdd369e4e8a8515e52ca72ec816c2101831ad1f18bf44102ed171459c9b4f8602052604081205460ff16156108f257506001610697565b505f8281526006602090815260408083206001600160a01b038516845290915290205460ff16610697565b5f610697600383610cf4565b5f81815260076020526040902060609061069790610f9d565b61094a6111cb565b6109526111f5565b565b61095c6111cb565b5f81900361097d576040516359203cb960e01b815260040160405180910390fd5b600254808211156109ad57604051630befc49d60e01b81526004016109a491815260200190565b60405180910390fd5b505f6109b85f611042565b11156109c6576109c66111f5565b5f5b818110156106e6576109ff8383838181106109e5576109e5611e97565b90506020020160208101906109fa9190611cf8565b611226565b6001016109c8565b610a0f610ce3565b5f5b82811015610a94575f848483818110610a2c57610a2c611e97565b9050602002016020810190610a419190611cf8565b90506001600160a01b038116610a6a5760405163135217db60e21b815260040160405180910390fd5b6001600160a01b03165f908152600560205260409020805460ff1916831515179055600101610a11565b507f430881f04f203566ee9b32d6444cf02e1b2a0f17ab6b4263a1ee2074d3d0f483838383604051610ac893929190611eab565b60405180910390a1505050565b5f6107fa5f611042565b610ae7610ce3565b5f5b818110156106e657610b20838383818110610b0657610b06611e97565b9050602002016020810190610b1b9190611cf8565b610f0c565b600101610ae9565b5f81815260076020526040812061069790611042565b5f610b4b8585858561128c565b95945050505050565b5f610854848484611359565b5f82815260066020526040902060010154610b7a8161141d565b6107c58383610da0565b5f610b8e5f611042565b821015610b9f576106975f8361104b565b505f919050565b610bae6111cb565b6107ae8161142e565b610bbf6111cb565b60025480610bcc5f611042565b108190610bef57604051630befc49d60e01b81526004016109a491815260200190565b5061071d82611226565b5f80610c06858585610b54565b60ff1614949350505050565b60606107fa6003610f9d565b5f6001600160e01b031982166320c49ce760e01b1480610c4e57506001600160e01b0319821663157094b960e31b145b80610c6957506001600160e01b031982166378a8de7d60e01b145b80610c8457506001600160e01b03198216630c51264760e21b145b80610c9f57506001600160e01b03198216633235d15f60e11b145b8061069757506001600160e01b03198216637157797f60e01b1492915050565b5f6001600160e01b03198216635a05180f60e01b148061069757506106978261148b565b6109526114bf565b6107ae816114e9565b6001600160a01b0381165f90815260018301602052604081205415156108a4565b5f82815260066020526040902060010154610d2f8161141d565b6107c58383611531565b6001600160a01b0382165f81815260056020908152604091829020805460ff191685151590811790915591519182527f407b412a9b6db334d48445ec9bcad46fb50bc4b2e97f73e963e397101957a729910160405180910390a25050565b5f6107fa61155c565b5f5f610dac84846115c6565b905080156108a4575f848152600760205260409020610dcb9084611656565b509392505050565b5f6107ae8161141d565b805f03610dfd57604051631e69e71760e21b815260040160405180910390fd5b60028190556040518181527f2292ad4720fff63e2bd104c6b1c0d72c2c729a6001c8ab4bb947cbcc51109863906020015b60405180910390a150565b610e44600333610cf4565b61095257604051630599c0e960e01b815260040160405180910390fd5b5f610e6b5f611042565b90505f5b81811015610efb57610e815f8261104b565b604051631f2d7a6560e11b81526001600160a01b03888116600483015287811660248301528681166044830152606482018690529190911690633e5af4ca906084015f604051808303815f87803b158015610eda575f5ffd5b505af1158015610eec573d5f5f3e3d5ffd5b50505050806001019050610e6f565b505050505050565b6107ae8161166a565b6001600160a01b038116610f335760405163135217db60e21b815260040160405180910390fd5b610f3c816116a9565b610f476003826116d1565b610f64576040516371b3c56560e11b815260040160405180910390fd5b6040516001600160a01b03821681527f2de35142b19ed5a07796cf30791959c592018f70b1d2d7c460eef8ffe713692b90602001610e2e565b60605f6108a4836116e5565b5f610fb35f611042565b90505f5b8181101561103b57610fc95f8261104b565b6040516322ebca6d60e21b81526001600160a01b0387811660048301528681166024830152604482018690529190911690638baf29b4906064015f604051808303815f87803b15801561101a575f5ffd5b505af115801561102c573d5f5f3e3d5ffd5b50505050806001019050610fb7565b5050505050565b5f610697825490565b5f6108a4838361173e565b606060ff821661108957505060408051808201909152600d81526c2737a932b9ba3934b1ba34b7b760991b602082015290565b5f6110935f611042565b90505f5b8181101561118f575f6110aa818361104b565b604051633e822efb60e11b815260ff871660048201529091506001600160a01b03821690637d045df690602401602060405180830381865afa1580156110f2573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111169190611f03565b1561118657604051637f4ab1dd60e01b815260ff861660048201526001600160a01b03821690637f4ab1dd906024015f60405180830381865afa15801561115f573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f19168201604052610b4b9190810190611f32565b50600101611097565b505060408051808201909152601881527f556e6b6e6f776e207265737472696374696f6e20636f64650000000000000000602082015292915050565b7fea5f4eb72290e50c32abd6c23e45de3d8300b3286e1cbc2e293114b92e034e5e6107ae8161141d565b6040517fdbf61473843cd9be1c9791ce51ef66d0da6c9026d62ba80c1ca433b13fb729b2905f90a16109525f611764565b61122f8161176d565b6112395f826116d1565b6112565760405163cc790a4b60e01b815260040160405180910390fd5b6040516001600160a01b038216907f60305ce6c9104acd0969d358f926bf391174340660aaf5e6215261fd6847bf46905f90a250565b5f5f6112975f611042565b90505f5b8181101561134d575f6112ae818361104b565b60405163d32c7bb560e01b81526001600160a01b038a811660048301528981166024830152888116604483015260648201889052919091169063d32c7bb590608401602060405180830381865afa15801561130b573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061132f9190611fe5565b905060ff811615611344579250610854915050565b5060010161129b565b505f9695505050505050565b5f5f6113645f611042565b90505f5b81811015611412575f61137b818361104b565b60405163d4ce141560e01b81526001600160a01b038981166004830152888116602483015260448201889052919091169063d4ce141590606401602060405180830381865afa1580156113d0573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906113f49190611fe5565b905060ff8116156114095792506108a4915050565b50600101611368565b505f95945050505050565b6107ae81611429610d97565b6117c5565b6114385f82611656565b61145557604051632cdc3a4160e21b815260040160405180910390fd5b6040516001600160a01b038216907f6d83315c9718799346b67584ec64301b1457e989c8e35a8e2982a7776c04bfc4905f90a250565b5f6001600160e01b03198216637965db0b60e01b148061069757506301ffc9a760e01b6001600160e01b0319831614610697565b7fe5c50d0927e06141e032cb9a67e1d7092dc85c0b0825191f7e1cede6000285686107ae8161141d565b6114f2816117fe565b336001600160a01b0382161480159061152257506001600160a01b0381165f9081526005602052604090205460ff165b156107ae576107ae815f610d39565b5f5f61153d848461185f565b905080156108a4575f848152600760205260409020610dcb90846116d1565b5f36601480821080159061159857507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031633145b156115be576115ab36828403815f612000565b6115b491612027565b60601c9250505090565b339250505090565b5f6115d183836108ab565b1561164f575f8381526006602090815260408083206001600160a01b03861684529091529020805460ff19169055611607610d97565b6001600160a01b0316826001600160a01b0316847ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a4506001610697565b505f610697565b5f6108a4836001600160a01b0384166118ea565b336001600160a01b03821614801561169957506001600160a01b0381165f9081526005602052604090205460ff165b156116a15750565b6107ae610ce3565b6116b35f82610cf4565b156107ae576040516302925f7360e11b815260040160405180910390fd5b5f6108a4836001600160a01b0384166119d4565b6060815f0180548060200260200160405190810160405280929190818152602001828054801561173257602002820191905f5260205f20905b81548152602001906001019080831161171e575b50505050509050919050565b5f825f01828154811061175357611753611e97565b905f5260205f200154905092915050565b6107ae81611a19565b61177681611a72565b611781600382610cf4565b1561179f576040516302925f7360e11b815260040160405180910390fd5b6117a881611a99565b6107ae57604051639952e34360e01b815260040160405180910390fd5b6117cf82826108ab565b61071d5760405163e2517d3f60e01b81526001600160a01b0382166004820152602481018390526044016109a4565b611809600382611656565b61182657604051633477dd1760e01b815260040160405180910390fd5b6040516001600160a01b03821681527f28a4ca7134a3b3f9aff286e79ad3daadb4a06d1b43d037a3a98bdc074edd9b7a90602001610e2e565b5f61186a83836108ab565b61164f575f8381526006602090815260408083206001600160a01b03861684529091529020805460ff191660011790556118a2610d97565b6001600160a01b0316826001600160a01b0316847f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a4506001610697565b5f81815260018301602052604081205480156119c4575f61190c600183612067565b85549091505f9061191f90600190612067565b905080821461197e575f865f01828154811061193d5761193d611e97565b905f5260205f200154905080875f01848154811061195d5761195d611e97565b5f918252602080832090910192909255918252600188019052604090208390555b855486908061198f5761198f612086565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f905560019350505050610697565b5f915050610697565b5092915050565b5f81815260018301602052604081205461164f57508154600181810184555f848152602080822090930184905584548482528286019093526040902091909155610697565b5f611a22825490565b90505f5b81811015611a6b57826001015f845f018381548110611a4757611a47611e97565b905f5260205f20015481526020019081526020015f205f9055806001019050611a26565b50505f9055565b6001600160a01b0381166107ae5760405163f9d152fb60e01b815260040160405180910390fd5b5f611aa382611ad6565b611aae57505f919050565b611abf826358d34ba960e11b611b15565b80610697575061069782632497d6cb60e01b611b15565b5f611ae8826301ffc9a760e01b611b15565b15610b9f575f80611b01846001600160e01b0319611b36565b915091508180156108545750159392505050565b5f5f5f611b228585611b36565b91509150818015610b4b5750949350505050565b6301ffc9a760e01b5f818152600483905290819060208260248188617530fa92505f511515601f3d11169150509250929050565b5f60208284031215611b7a575f5ffd5b81356001600160e01b0319811681146108a4575f5ffd5b5f5f83601f840112611ba1575f5ffd5b50813567ffffffffffffffff811115611bb8575f5ffd5b6020830191508360208260051b8501011115611bd2575f5ffd5b9250929050565b5f5f60208385031215611bea575f5ffd5b823567ffffffffffffffff811115611c00575f5ffd5b611c0c85828601611b91565b90969095509350505050565b5f60208284031215611c28575f5ffd5b5035919050565b6001600160a01b03811681146107ae575f5ffd5b5f5f60408385031215611c54575f5ffd5b823591506020830135611c6681611c2f565b809150509250929050565b80151581146107ae575f5ffd5b5f5f60408385031215611c8f575f5ffd5b8235611c9a81611c2f565b91506020830135611c6681611c71565b5f5f5f5f60808587031215611cbd575f5ffd5b8435611cc881611c2f565b93506020850135611cd881611c2f565b92506040850135611ce881611c2f565b9396929550929360600135925050565b5f60208284031215611d08575f5ffd5b81356108a481611c2f565b602080825282518282018190525f918401906040840190835b81811015611d535783516001600160a01b0316835260209384019390920191600101611d2c565b509095945050505050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b5f5f60408385031215611da4575f5ffd5b8235611daf81611c2f565b946020939093013593505050565b60ff811681146107ae575f5ffd5b5f60208284031215611ddb575f5ffd5b81356108a481611dbd565b5f5f5f60608486031215611df8575f5ffd5b8335611e0381611c2f565b92506020840135611e1381611c2f565b929592945050506040919091013590565b5f5f60408385031215611e35575f5ffd5b50508035926020909101359150565b5f5f5f60408486031215611e56575f5ffd5b833567ffffffffffffffff811115611e6c575f5ffd5b611e7886828701611b91565b9094509250506020840135611e8c81611c71565b809150509250925092565b634e487b7160e01b5f52603260045260245ffd5b604080825281018390525f8460608301825b86811015611eed578235611ed081611c2f565b6001600160a01b0316825260209283019290910190600101611ebd565b5080925050508215156020830152949350505050565b5f60208284031215611f13575f5ffd5b81516108a481611c71565b634e487b7160e01b5f52604160045260245ffd5b5f60208284031215611f42575f5ffd5b815167ffffffffffffffff811115611f58575f5ffd5b8201601f81018413611f68575f5ffd5b805167ffffffffffffffff811115611f8257611f82611f1e565b604051601f8201601f19908116603f0116810167ffffffffffffffff81118282101715611fb157611fb1611f1e565b604052818152828201602001861015611fc8575f5ffd5b8160208401602083015e5f91810160200191909152949350505050565b5f60208284031215611ff5575f5ffd5b81516108a481611dbd565b5f5f8585111561200e575f5ffd5b8386111561201a575f5ffd5b5050820193919092039150565b80356bffffffffffffffffffffffff1981169060148410156119cd576bffffffffffffffffffffffff1960149490940360031b84901b1690921692915050565b8181038181111561069757634e487b7160e01b5f52601160045260245ffd5b634e487b7160e01b5f52603160045260245ffdfea26469706673582212204cc6d4f8ac0adf6c88fe67343897a0d2c4402c1bafcf0801c24ebf9dc6a2b48064736f6c63430008250033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/doc/compilation/v3.0.0-rc7/hardhat/RuleEngineOwnable.sol/RuleEngineOwnable.dbg.json b/doc/compilation/v3.0.0-rc7/hardhat/RuleEngineOwnable.sol/RuleEngineOwnable.dbg.json new file mode 100644 index 00000000..c25ba54e --- /dev/null +++ b/doc/compilation/v3.0.0-rc7/hardhat/RuleEngineOwnable.sol/RuleEngineOwnable.dbg.json @@ -0,0 +1,4 @@ +{ + "_format": "hh-sol-dbg-1", + "buildInfo": "../../../../build-info/315e205e547361276a4bba3ad0401f98.json" +} diff --git a/doc/compilation/v3.0.0-rc7/hardhat/RuleEngineOwnable.sol/RuleEngineOwnable.json b/doc/compilation/v3.0.0-rc7/hardhat/RuleEngineOwnable.sol/RuleEngineOwnable.json new file mode 100644 index 00000000..a3f68bc2 --- /dev/null +++ b/doc/compilation/v3.0.0-rc7/hardhat/RuleEngineOwnable.sol/RuleEngineOwnable.json @@ -0,0 +1,846 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "RuleEngineOwnable", + "sourceName": "src/deployment/ownable/RuleEngineOwnable.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "owner_", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenContract", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "OwnableInvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "OwnableUnauthorizedAccount", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_AdminWithAddressZeroNotAllowed", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_RuleInvalidInterface", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_RulesManagementModule_ArrayIsEmpty", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "maxRules", + "type": "uint256" + } + ], + "name": "RuleEngine_RulesManagementModule_MaxRulesExceeded", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_RulesManagementModule_MaxRulesZeroNotAllowed", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_RulesManagementModule_RuleAccountCannotReceivePrivileges", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_RulesManagementModule_RuleAddressZeroNotAllowed", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_RulesManagementModule_RuleAlreadyExists", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_RulesManagementModule_RuleDoNotMatch", + "type": "error" + }, + { + "inputs": [], + "name": "TokenBinding_InvalidTokenAddress", + "type": "error" + }, + { + "inputs": [], + "name": "TokenBinding_TokenAlreadyBound", + "type": "error" + }, + { + "inputs": [], + "name": "TokenBinding_TokenNotBound", + "type": "error" + }, + { + "inputs": [], + "name": "TokenBinding_UnauthorizedCaller", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract IRule", + "name": "rule", + "type": "address" + } + ], + "name": "AddRule", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "ClearRules", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract IRule", + "name": "rule", + "type": "address" + } + ], + "name": "RemoveRule", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "maxRules", + "type": "uint256" + } + ], + "name": "SetMaxRules", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "TokenBound", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address[]", + "name": "tokens", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "TokenSelfBindingApprovalBatchSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "TokenSelfBindingApprovalSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "TokenUnbound", + "type": "event" + }, + { + "inputs": [], + "name": "DEFAULT_MAX_RULES", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IRule", + "name": "rule_", + "type": "address" + } + ], + "name": "addRule", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "bindToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "tokens", + "type": "address[]" + } + ], + "name": "bindTokens", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "canTransfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "canTransferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "clearRules", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IRule", + "name": "rule_", + "type": "address" + } + ], + "name": "containsRule", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "created", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "destroyed", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "detectTransferRestriction", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "detectTransferRestrictionFrom", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getTokenBound", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getTokenBounds", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "isTokenBound", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "isTokenSelfBindingApproved", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maxRules", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "restrictionCode", + "type": "uint8" + } + ], + "name": "messageForTransferRestriction", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IRule", + "name": "rule_", + "type": "address" + } + ], + "name": "removeRule", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "ruleId", + "type": "uint256" + } + ], + "name": "rule", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "rules", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "rulesCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "maxRules_", + "type": "uint256" + } + ], + "name": "setMaxRules", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IRule[]", + "name": "rules_", + "type": "address[]" + } + ], + "name": "setRules", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setTokenSelfBindingApproval", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "tokens", + "type": "address[]" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setTokenSelfBindingApprovalBatch", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transferred", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transferred", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "unbindToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "tokens", + "type": "address[]" + } + ], + "name": "unbindTokens", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "version_", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x6080604052600a600255348015610014575f5ffd5b50604051611e1c380380611e1c833981016040819052610033916102a4565b81816001600160a01b0381161561004d5761004d81610096565b610057600a61012e565b506001600160a01b03811661008557604051631e4fbdf760e01b81525f600482015260240160405180910390fd5b61008e81610183565b5050506102d5565b6001600160a01b0381166100bd5760405163135217db60e21b815260040160405180910390fd5b6100c6816101d4565b6100d16003826101ff565b6100ee576040516371b3c56560e11b815260040160405180910390fd5b6040516001600160a01b03821681527f2de35142b19ed5a07796cf30791959c592018f70b1d2d7c460eef8ffe713692b906020015b60405180910390a150565b805f0361014e57604051631e69e71760e21b815260040160405180910390fd5b60028190556040518181527f2292ad4720fff63e2bd104c6b1c0d72c2c729a6001c8ab4bb947cbcc5110986390602001610123565b600680546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b6101de5f8261021c565b156101fc576040516302925f7360e11b815260040160405180910390fd5b50565b5f610213836001600160a01b03841661023d565b90505b92915050565b6001600160a01b0381165f9081526001830160205260408120541515610213565b5f81815260018301602052604081205461028257508154600181810184555f848152602080822090930184905584548482528286019093526040902091909155610216565b505f610216565b80516001600160a01b038116811461029f575f5ffd5b919050565b5f5f604083850312156102b5575f5ffd5b6102be83610289565b91506102cc60208401610289565b90509250929050565b611b3a806102e25f395ff3fe608060405234801561000f575f5ffd5b5060043610610208575f3560e01c80638d2ea7721161011f578063d4ce1415116100a9578063e3c4602c11610079578063e3c4602c1461048d578063e46638e6146104a0578063e54621d2146104b3578063f2fde38b146104bb578063f76bf550146104ce575f5ffd5b8063d4ce141514610429578063db18af6c1461043c578063db75d0171461044f578063df21950f1461047a575f5ffd5b8063b27aef3a116100ef578063b27aef3a146103c3578063bb4b6121146103d6578063bc13eacc146103e9578063c7c24b18146103f1578063d32c7bb514610404575f5ffd5b80638d2ea772146103845780638da5cb5b14610397578063993e8b95146103a8578063b043572e146103bb575f5ffd5b806354e4b945116101a05780636ae728c6116101705780636ae728c614610331578063715018a6146103435780637157797f1461034b5780637f4ab1dd1461035e5780638baf29b414610371575f5ffd5b806354e4b945146102bd57806354fd4d50146102d05780635f8dead3146102fe5780636a3edf2814610311575f5ffd5b80633e5af4ca116101db5780633e5af4ca1461026f5780633ff5aa021461028257806340db3b501461029557806352f6747a146102a8575f5ffd5b806301ffc9a71461020c5780631455d0e7146102345780633284a9a5146102495780633a56d6d51461025c575b5f5ffd5b61021f61021a36600461167e565b6104d6565b60405190151581526020015b60405180910390f35b6102476102423660046116ed565b61051c565b005b61024761025736600461174d565b61056a565b61024761026a366004611784565b6105a7565b61024761027d36600461179b565b6105bb565b6102476102903660046117e9565b6105d5565b6102476102a33660046117e9565b6105e7565b6102b06105f9565b60405161022b9190611804565b61021f6102cb3660046117e9565b610609565b604080518082019091526009815268332e302e302d72633760b81b60208201525b60405161022b919061184f565b61024761030c366004611884565b610614565b610319610627565b6040516001600160a01b03909116815260200161022b565b6002545b60405190815260200161022b565b610247610649565b61021f61035936600461179b565b61065c565b6102f161036c3660046118bc565b610679565b61024761037f3660046118d7565b610684565b610247610392366004611884565b610697565b6006546001600160a01b0316610319565b61021f6103b63660046117e9565b6106aa565b6102476106b6565b6102476103d13660046116ed565b6106c6565b6102476103e4366004611915565b610779565b610335610847565b6102476103ff3660046116ed565b610851565b61041761041236600461179b565b61089a565b60405160ff909116815260200161022b565b6104176104373660046118d7565b6108b0565b61031961044a366004611784565b6108c6565b61021f61045d3660046117e9565b6001600160a01b03165f9081526005602052604090205460ff1690565b6102476104883660046117e9565b6108e8565b61024761049b3660046117e9565b6108f9565b61021f6104ae3660046118d7565b61093b565b6102b0610954565b6102476104c93660046117e9565b610960565b610335600a81565b5f6104e08261097a565b806104fb57506001600160e01b031982166307f5828d60e41b145b8061051657506301ffc9a760e01b6001600160e01b03198316145b92915050565b610524610a1b565b5f5b818110156105655761055d83838381811061054357610543611968565b905060200201602081019061055891906117e9565b610a23565b600101610526565b505050565b610572610a1b565b6001600160a01b0382166105995760405163135217db60e21b815260040160405180910390fd5b6105a38282610a2c565b5050565b6105af610a8a565b6105b881610a92565b50565b6105c3610aee565b6105cf84848484610b16565b50505050565b6105de81610bb8565b6105b881610bc1565b6105f081610bb8565b6105b881610a23565b60606106045f610c52565b905090565b5f6105168183610c5e565b61061c610aee565b6105a35f8383610c7e565b5f5f6106336003610d17565b11156106445761060460035f610d20565b505f90565b610651610d2b565b61065a5f610d58565b565b5f8061066a8686868661089a565b60ff161490505b949350505050565b606061051682610da9565b61068c610aee565b610565838383610c7e565b61069f610aee565b6105a3825f83610c7e565b5f610516600383610c5e565b6106be610a8a565b61065a610f1e565b6106ce610a8a565b5f8190036106ef576040516359203cb960e01b815260040160405180910390fd5b6002548082111561071f57604051630befc49d60e01b815260040161071691815260200190565b60405180910390fd5b505f61072a5f610d17565b111561073857610738610f1e565b5f5b818110156105655761077183838381811061075757610757611968565b905060200201602081019061076c91906117e9565b610f4f565b60010161073a565b610781610a1b565b5f5b82811015610806575f84848381811061079e5761079e611968565b90506020020160208101906107b391906117e9565b90506001600160a01b0381166107dc5760405163135217db60e21b815260040160405180910390fd5b6001600160a01b03165f908152600560205260409020805460ff1916831515179055600101610783565b507f430881f04f203566ee9b32d6444cf02e1b2a0f17ab6b4263a1ee2074d3d0f48383838360405161083a9392919061197c565b60405180910390a1505050565b5f6106045f610d17565b610859610a1b565b5f5b818110156105655761089283838381811061087857610878611968565b905060200201602081019061088d91906117e9565b610bc1565b60010161085b565b5f6108a785858585610fb5565b95945050505050565b5f6108bc848484611082565b90505b9392505050565b5f6108d05f610d17565b8210156108e1576105165f83610d20565b505f919050565b6108f0610a8a565b6105b881611146565b610901610a8a565b6002548061090e5f610d17565b10819061093157604051630befc49d60e01b815260040161071691815260200190565b506105a382610f4f565b5f806109488585856108b0565b60ff1614949350505050565b60606106046003610c52565b610968610d2b565b610971816111a3565b6105b8816111ca565b5f6001600160e01b031982166320c49ce760e01b14806109aa57506001600160e01b0319821663157094b960e31b145b806109c557506001600160e01b031982166378a8de7d60e01b145b806109e057506001600160e01b03198216630c51264760e21b145b806109fb57506001600160e01b03198216633235d15f60e11b145b8061051657506001600160e01b03198216637157797f60e01b1492915050565b61065a610a8a565b6105b881611204565b6001600160a01b0382165f81815260056020908152604091829020805460ff191685151590811790915591519182527f407b412a9b6db334d48445ec9bcad46fb50bc4b2e97f73e963e397101957a729910160405180910390a25050565b61065a610d2b565b805f03610ab257604051631e69e71760e21b815260040160405180910390fd5b60028190556040518181527f2292ad4720fff63e2bd104c6b1c0d72c2c729a6001c8ab4bb947cbcc51109863906020015b60405180910390a150565b610af9600333610c5e565b61065a57604051630599c0e960e01b815260040160405180910390fd5b5f610b205f610d17565b90505f5b81811015610bb057610b365f82610d20565b604051631f2d7a6560e11b81526001600160a01b03888116600483015287811660248301528681166044830152606482018690529190911690633e5af4ca906084015f604051808303815f87803b158015610b8f575f5ffd5b505af1158015610ba1573d5f5f3e3d5ffd5b50505050806001019050610b24565b505050505050565b6105b88161124c565b6001600160a01b038116610be85760405163135217db60e21b815260040160405180910390fd5b610bf18161128b565b610bfc600382611295565b610c19576040516371b3c56560e11b815260040160405180910390fd5b6040516001600160a01b03821681527f2de35142b19ed5a07796cf30791959c592018f70b1d2d7c460eef8ffe713692b90602001610ae3565b60605f6108bf836112a9565b6001600160a01b03165f9081526001919091016020526040902054151590565b5f610c885f610d17565b90505f5b81811015610d1057610c9e5f82610d20565b6040516322ebca6d60e21b81526001600160a01b0387811660048301528681166024830152604482018690529190911690638baf29b4906064015f604051808303815f87803b158015610cef575f5ffd5b505af1158015610d01573d5f5f3e3d5ffd5b50505050806001019050610c8c565b5050505050565b5f610516825490565b5f6108bf8383611302565b6006546001600160a01b0316331461065a5760405163118cdaa760e01b8152336004820152602401610716565b600680546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b606060ff8216610ddc57505060408051808201909152600d81526c2737a932b9ba3934b1ba34b7b760991b602082015290565b5f610de65f610d17565b90505f5b81811015610ee2575f610dfd8183610d20565b604051633e822efb60e11b815260ff871660048201529091506001600160a01b03821690637d045df690602401602060405180830381865afa158015610e45573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e6991906119d4565b15610ed957604051637f4ab1dd60e01b815260ff861660048201526001600160a01b03821690637f4ab1dd906024015f60405180830381865afa158015610eb2573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526108a79190810190611a03565b50600101610dea565b505060408051808201909152601881527f556e6b6e6f776e207265737472696374696f6e20636f64650000000000000000602082015292915050565b6040517fdbf61473843cd9be1c9791ce51ef66d0da6c9026d62ba80c1ca433b13fb729b2905f90a161065a5f611328565b610f5881611331565b610f625f82611295565b610f7f5760405163cc790a4b60e01b815260040160405180910390fd5b6040516001600160a01b038216907f60305ce6c9104acd0969d358f926bf391174340660aaf5e6215261fd6847bf46905f90a250565b5f5f610fc05f610d17565b90505f5b81811015611076575f610fd78183610d20565b60405163d32c7bb560e01b81526001600160a01b038a811660048301528981166024830152888116604483015260648201889052919091169063d32c7bb590608401602060405180830381865afa158015611034573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110589190611ab6565b905060ff81161561106d579250610671915050565b50600101610fc4565b505f9695505050505050565b5f5f61108d5f610d17565b90505f5b8181101561113b575f6110a48183610d20565b60405163d4ce141560e01b81526001600160a01b038981166004830152888116602483015260448201889052919091169063d4ce141590606401602060405180830381865afa1580156110f9573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061111d9190611ab6565b905060ff8116156111325792506108bf915050565b50600101611091565b505f95945050505050565b6111505f82611389565b61116d57604051632cdc3a4160e21b815260040160405180910390fd5b6040516001600160a01b038216907f6d83315c9718799346b67584ec64301b1457e989c8e35a8e2982a7776c04bfc4905f90a250565b6111ac81610609565b156105b8576040516302925f7360e11b815260040160405180910390fd5b6111d2610d2b565b6001600160a01b0381166111fb57604051631e4fbdf760e01b81525f6004820152602401610716565b6105b881610d58565b61120d8161139d565b336001600160a01b0382161480159061123d57506001600160a01b0381165f9081526005602052604090205460ff165b156105b8576105b8815f610a2c565b336001600160a01b03821614801561127b57506001600160a01b0381165f9081526005602052604090205460ff165b156112835750565b6105b8610a1b565b6111ac5f82610c5e565b5f6108bf836001600160a01b0384166113fe565b6060815f018054806020026020016040519081016040528092919081815260200182805480156112f657602002820191905f5260205f20905b8154815260200190600101908083116112e2575b50505050509050919050565b5f825f01828154811061131757611317611968565b905f5260205f200154905092915050565b6105b88161144a565b61133a816114a3565b611345600382610c5e565b15611363576040516302925f7360e11b815260040160405180910390fd5b61136c816114ca565b6105b857604051639952e34360e01b815260040160405180910390fd5b5f6108bf836001600160a01b038416611507565b6113a8600382611389565b6113c557604051633477dd1760e01b815260040160405180910390fd5b6040516001600160a01b03821681527f28a4ca7134a3b3f9aff286e79ad3daadb4a06d1b43d037a3a98bdc074edd9b7a90602001610ae3565b5f81815260018301602052604081205461144357508154600181810184555f848152602080822090930184905584548482528286019093526040902091909155610516565b505f610516565b5f611453825490565b90505f5b8181101561149c57826001015f845f01838154811061147857611478611968565b905f5260205f20015481526020019081526020015f205f9055806001019050611457565b50505f9055565b6001600160a01b0381166105b85760405163f9d152fb60e01b815260040160405180910390fd5b5f6114d4826115ea565b6114df57505f919050565b6114f0826358d34ba960e11b611629565b80610516575061051682632497d6cb60e01b611629565b5f81815260018301602052604081205480156115e1575f611529600183611ad1565b85549091505f9061153c90600190611ad1565b905080821461159b575f865f01828154811061155a5761155a611968565b905f5260205f200154905080875f01848154811061157a5761157a611968565b5f918252602080832090910192909255918252600188019052604090208390555b85548690806115ac576115ac611af0565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f905560019350505050610516565b5f915050610516565b5f6115fc826301ffc9a760e01b611629565b156108e1575f80611615846001600160e01b031961164a565b915091508180156106715750159392505050565b5f5f5f611636858561164a565b915091508180156108a75750949350505050565b6301ffc9a760e01b5f818152600483905290819060208260248188617530fa92505f511515601f3d11169150509250929050565b5f6020828403121561168e575f5ffd5b81356001600160e01b0319811681146108bf575f5ffd5b5f5f83601f8401126116b5575f5ffd5b50813567ffffffffffffffff8111156116cc575f5ffd5b6020830191508360208260051b85010111156116e6575f5ffd5b9250929050565b5f5f602083850312156116fe575f5ffd5b823567ffffffffffffffff811115611714575f5ffd5b611720858286016116a5565b90969095509350505050565b6001600160a01b03811681146105b8575f5ffd5b80151581146105b8575f5ffd5b5f5f6040838503121561175e575f5ffd5b82356117698161172c565b9150602083013561177981611740565b809150509250929050565b5f60208284031215611794575f5ffd5b5035919050565b5f5f5f5f608085870312156117ae575f5ffd5b84356117b98161172c565b935060208501356117c98161172c565b925060408501356117d98161172c565b9396929550929360600135925050565b5f602082840312156117f9575f5ffd5b81356108bf8161172c565b602080825282518282018190525f918401906040840190835b818110156118445783516001600160a01b031683526020938401939092019160010161181d565b509095945050505050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b5f5f60408385031215611895575f5ffd5b82356118a08161172c565b946020939093013593505050565b60ff811681146105b8575f5ffd5b5f602082840312156118cc575f5ffd5b81356108bf816118ae565b5f5f5f606084860312156118e9575f5ffd5b83356118f48161172c565b925060208401356119048161172c565b929592945050506040919091013590565b5f5f5f60408486031215611927575f5ffd5b833567ffffffffffffffff81111561193d575f5ffd5b611949868287016116a5565b909450925050602084013561195d81611740565b809150509250925092565b634e487b7160e01b5f52603260045260245ffd5b604080825281018390525f8460608301825b868110156119be5782356119a18161172c565b6001600160a01b031682526020928301929091019060010161198e565b5080925050508215156020830152949350505050565b5f602082840312156119e4575f5ffd5b81516108bf81611740565b634e487b7160e01b5f52604160045260245ffd5b5f60208284031215611a13575f5ffd5b815167ffffffffffffffff811115611a29575f5ffd5b8201601f81018413611a39575f5ffd5b805167ffffffffffffffff811115611a5357611a536119ef565b604051601f8201601f19908116603f0116810167ffffffffffffffff81118282101715611a8257611a826119ef565b604052818152828201602001861015611a99575f5ffd5b8160208401602083015e5f91810160200191909152949350505050565b5f60208284031215611ac6575f5ffd5b81516108bf816118ae565b8181038181111561051657634e487b7160e01b5f52601160045260245ffd5b634e487b7160e01b5f52603160045260245ffdfea2646970667358221220a659ba275e7418276483b0a3b605cd7437d92cb06048c0d3af9ee0b308ef258764736f6c63430008250033", + "deployedBytecode": "0x608060405234801561000f575f5ffd5b5060043610610208575f3560e01c80638d2ea7721161011f578063d4ce1415116100a9578063e3c4602c11610079578063e3c4602c1461048d578063e46638e6146104a0578063e54621d2146104b3578063f2fde38b146104bb578063f76bf550146104ce575f5ffd5b8063d4ce141514610429578063db18af6c1461043c578063db75d0171461044f578063df21950f1461047a575f5ffd5b8063b27aef3a116100ef578063b27aef3a146103c3578063bb4b6121146103d6578063bc13eacc146103e9578063c7c24b18146103f1578063d32c7bb514610404575f5ffd5b80638d2ea772146103845780638da5cb5b14610397578063993e8b95146103a8578063b043572e146103bb575f5ffd5b806354e4b945116101a05780636ae728c6116101705780636ae728c614610331578063715018a6146103435780637157797f1461034b5780637f4ab1dd1461035e5780638baf29b414610371575f5ffd5b806354e4b945146102bd57806354fd4d50146102d05780635f8dead3146102fe5780636a3edf2814610311575f5ffd5b80633e5af4ca116101db5780633e5af4ca1461026f5780633ff5aa021461028257806340db3b501461029557806352f6747a146102a8575f5ffd5b806301ffc9a71461020c5780631455d0e7146102345780633284a9a5146102495780633a56d6d51461025c575b5f5ffd5b61021f61021a36600461167e565b6104d6565b60405190151581526020015b60405180910390f35b6102476102423660046116ed565b61051c565b005b61024761025736600461174d565b61056a565b61024761026a366004611784565b6105a7565b61024761027d36600461179b565b6105bb565b6102476102903660046117e9565b6105d5565b6102476102a33660046117e9565b6105e7565b6102b06105f9565b60405161022b9190611804565b61021f6102cb3660046117e9565b610609565b604080518082019091526009815268332e302e302d72633760b81b60208201525b60405161022b919061184f565b61024761030c366004611884565b610614565b610319610627565b6040516001600160a01b03909116815260200161022b565b6002545b60405190815260200161022b565b610247610649565b61021f61035936600461179b565b61065c565b6102f161036c3660046118bc565b610679565b61024761037f3660046118d7565b610684565b610247610392366004611884565b610697565b6006546001600160a01b0316610319565b61021f6103b63660046117e9565b6106aa565b6102476106b6565b6102476103d13660046116ed565b6106c6565b6102476103e4366004611915565b610779565b610335610847565b6102476103ff3660046116ed565b610851565b61041761041236600461179b565b61089a565b60405160ff909116815260200161022b565b6104176104373660046118d7565b6108b0565b61031961044a366004611784565b6108c6565b61021f61045d3660046117e9565b6001600160a01b03165f9081526005602052604090205460ff1690565b6102476104883660046117e9565b6108e8565b61024761049b3660046117e9565b6108f9565b61021f6104ae3660046118d7565b61093b565b6102b0610954565b6102476104c93660046117e9565b610960565b610335600a81565b5f6104e08261097a565b806104fb57506001600160e01b031982166307f5828d60e41b145b8061051657506301ffc9a760e01b6001600160e01b03198316145b92915050565b610524610a1b565b5f5b818110156105655761055d83838381811061054357610543611968565b905060200201602081019061055891906117e9565b610a23565b600101610526565b505050565b610572610a1b565b6001600160a01b0382166105995760405163135217db60e21b815260040160405180910390fd5b6105a38282610a2c565b5050565b6105af610a8a565b6105b881610a92565b50565b6105c3610aee565b6105cf84848484610b16565b50505050565b6105de81610bb8565b6105b881610bc1565b6105f081610bb8565b6105b881610a23565b60606106045f610c52565b905090565b5f6105168183610c5e565b61061c610aee565b6105a35f8383610c7e565b5f5f6106336003610d17565b11156106445761060460035f610d20565b505f90565b610651610d2b565b61065a5f610d58565b565b5f8061066a8686868661089a565b60ff161490505b949350505050565b606061051682610da9565b61068c610aee565b610565838383610c7e565b61069f610aee565b6105a3825f83610c7e565b5f610516600383610c5e565b6106be610a8a565b61065a610f1e565b6106ce610a8a565b5f8190036106ef576040516359203cb960e01b815260040160405180910390fd5b6002548082111561071f57604051630befc49d60e01b815260040161071691815260200190565b60405180910390fd5b505f61072a5f610d17565b111561073857610738610f1e565b5f5b818110156105655761077183838381811061075757610757611968565b905060200201602081019061076c91906117e9565b610f4f565b60010161073a565b610781610a1b565b5f5b82811015610806575f84848381811061079e5761079e611968565b90506020020160208101906107b391906117e9565b90506001600160a01b0381166107dc5760405163135217db60e21b815260040160405180910390fd5b6001600160a01b03165f908152600560205260409020805460ff1916831515179055600101610783565b507f430881f04f203566ee9b32d6444cf02e1b2a0f17ab6b4263a1ee2074d3d0f48383838360405161083a9392919061197c565b60405180910390a1505050565b5f6106045f610d17565b610859610a1b565b5f5b818110156105655761089283838381811061087857610878611968565b905060200201602081019061088d91906117e9565b610bc1565b60010161085b565b5f6108a785858585610fb5565b95945050505050565b5f6108bc848484611082565b90505b9392505050565b5f6108d05f610d17565b8210156108e1576105165f83610d20565b505f919050565b6108f0610a8a565b6105b881611146565b610901610a8a565b6002548061090e5f610d17565b10819061093157604051630befc49d60e01b815260040161071691815260200190565b506105a382610f4f565b5f806109488585856108b0565b60ff1614949350505050565b60606106046003610c52565b610968610d2b565b610971816111a3565b6105b8816111ca565b5f6001600160e01b031982166320c49ce760e01b14806109aa57506001600160e01b0319821663157094b960e31b145b806109c557506001600160e01b031982166378a8de7d60e01b145b806109e057506001600160e01b03198216630c51264760e21b145b806109fb57506001600160e01b03198216633235d15f60e11b145b8061051657506001600160e01b03198216637157797f60e01b1492915050565b61065a610a8a565b6105b881611204565b6001600160a01b0382165f81815260056020908152604091829020805460ff191685151590811790915591519182527f407b412a9b6db334d48445ec9bcad46fb50bc4b2e97f73e963e397101957a729910160405180910390a25050565b61065a610d2b565b805f03610ab257604051631e69e71760e21b815260040160405180910390fd5b60028190556040518181527f2292ad4720fff63e2bd104c6b1c0d72c2c729a6001c8ab4bb947cbcc51109863906020015b60405180910390a150565b610af9600333610c5e565b61065a57604051630599c0e960e01b815260040160405180910390fd5b5f610b205f610d17565b90505f5b81811015610bb057610b365f82610d20565b604051631f2d7a6560e11b81526001600160a01b03888116600483015287811660248301528681166044830152606482018690529190911690633e5af4ca906084015f604051808303815f87803b158015610b8f575f5ffd5b505af1158015610ba1573d5f5f3e3d5ffd5b50505050806001019050610b24565b505050505050565b6105b88161124c565b6001600160a01b038116610be85760405163135217db60e21b815260040160405180910390fd5b610bf18161128b565b610bfc600382611295565b610c19576040516371b3c56560e11b815260040160405180910390fd5b6040516001600160a01b03821681527f2de35142b19ed5a07796cf30791959c592018f70b1d2d7c460eef8ffe713692b90602001610ae3565b60605f6108bf836112a9565b6001600160a01b03165f9081526001919091016020526040902054151590565b5f610c885f610d17565b90505f5b81811015610d1057610c9e5f82610d20565b6040516322ebca6d60e21b81526001600160a01b0387811660048301528681166024830152604482018690529190911690638baf29b4906064015f604051808303815f87803b158015610cef575f5ffd5b505af1158015610d01573d5f5f3e3d5ffd5b50505050806001019050610c8c565b5050505050565b5f610516825490565b5f6108bf8383611302565b6006546001600160a01b0316331461065a5760405163118cdaa760e01b8152336004820152602401610716565b600680546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b606060ff8216610ddc57505060408051808201909152600d81526c2737a932b9ba3934b1ba34b7b760991b602082015290565b5f610de65f610d17565b90505f5b81811015610ee2575f610dfd8183610d20565b604051633e822efb60e11b815260ff871660048201529091506001600160a01b03821690637d045df690602401602060405180830381865afa158015610e45573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e6991906119d4565b15610ed957604051637f4ab1dd60e01b815260ff861660048201526001600160a01b03821690637f4ab1dd906024015f60405180830381865afa158015610eb2573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526108a79190810190611a03565b50600101610dea565b505060408051808201909152601881527f556e6b6e6f776e207265737472696374696f6e20636f64650000000000000000602082015292915050565b6040517fdbf61473843cd9be1c9791ce51ef66d0da6c9026d62ba80c1ca433b13fb729b2905f90a161065a5f611328565b610f5881611331565b610f625f82611295565b610f7f5760405163cc790a4b60e01b815260040160405180910390fd5b6040516001600160a01b038216907f60305ce6c9104acd0969d358f926bf391174340660aaf5e6215261fd6847bf46905f90a250565b5f5f610fc05f610d17565b90505f5b81811015611076575f610fd78183610d20565b60405163d32c7bb560e01b81526001600160a01b038a811660048301528981166024830152888116604483015260648201889052919091169063d32c7bb590608401602060405180830381865afa158015611034573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906110589190611ab6565b905060ff81161561106d579250610671915050565b50600101610fc4565b505f9695505050505050565b5f5f61108d5f610d17565b90505f5b8181101561113b575f6110a48183610d20565b60405163d4ce141560e01b81526001600160a01b038981166004830152888116602483015260448201889052919091169063d4ce141590606401602060405180830381865afa1580156110f9573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061111d9190611ab6565b905060ff8116156111325792506108bf915050565b50600101611091565b505f95945050505050565b6111505f82611389565b61116d57604051632cdc3a4160e21b815260040160405180910390fd5b6040516001600160a01b038216907f6d83315c9718799346b67584ec64301b1457e989c8e35a8e2982a7776c04bfc4905f90a250565b6111ac81610609565b156105b8576040516302925f7360e11b815260040160405180910390fd5b6111d2610d2b565b6001600160a01b0381166111fb57604051631e4fbdf760e01b81525f6004820152602401610716565b6105b881610d58565b61120d8161139d565b336001600160a01b0382161480159061123d57506001600160a01b0381165f9081526005602052604090205460ff165b156105b8576105b8815f610a2c565b336001600160a01b03821614801561127b57506001600160a01b0381165f9081526005602052604090205460ff165b156112835750565b6105b8610a1b565b6111ac5f82610c5e565b5f6108bf836001600160a01b0384166113fe565b6060815f018054806020026020016040519081016040528092919081815260200182805480156112f657602002820191905f5260205f20905b8154815260200190600101908083116112e2575b50505050509050919050565b5f825f01828154811061131757611317611968565b905f5260205f200154905092915050565b6105b88161144a565b61133a816114a3565b611345600382610c5e565b15611363576040516302925f7360e11b815260040160405180910390fd5b61136c816114ca565b6105b857604051639952e34360e01b815260040160405180910390fd5b5f6108bf836001600160a01b038416611507565b6113a8600382611389565b6113c557604051633477dd1760e01b815260040160405180910390fd5b6040516001600160a01b03821681527f28a4ca7134a3b3f9aff286e79ad3daadb4a06d1b43d037a3a98bdc074edd9b7a90602001610ae3565b5f81815260018301602052604081205461144357508154600181810184555f848152602080822090930184905584548482528286019093526040902091909155610516565b505f610516565b5f611453825490565b90505f5b8181101561149c57826001015f845f01838154811061147857611478611968565b905f5260205f20015481526020019081526020015f205f9055806001019050611457565b50505f9055565b6001600160a01b0381166105b85760405163f9d152fb60e01b815260040160405180910390fd5b5f6114d4826115ea565b6114df57505f919050565b6114f0826358d34ba960e11b611629565b80610516575061051682632497d6cb60e01b611629565b5f81815260018301602052604081205480156115e1575f611529600183611ad1565b85549091505f9061153c90600190611ad1565b905080821461159b575f865f01828154811061155a5761155a611968565b905f5260205f200154905080875f01848154811061157a5761157a611968565b5f918252602080832090910192909255918252600188019052604090208390555b85548690806115ac576115ac611af0565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f905560019350505050610516565b5f915050610516565b5f6115fc826301ffc9a760e01b611629565b156108e1575f80611615846001600160e01b031961164a565b915091508180156106715750159392505050565b5f5f5f611636858561164a565b915091508180156108a75750949350505050565b6301ffc9a760e01b5f818152600483905290819060208260248188617530fa92505f511515601f3d11169150509250929050565b5f6020828403121561168e575f5ffd5b81356001600160e01b0319811681146108bf575f5ffd5b5f5f83601f8401126116b5575f5ffd5b50813567ffffffffffffffff8111156116cc575f5ffd5b6020830191508360208260051b85010111156116e6575f5ffd5b9250929050565b5f5f602083850312156116fe575f5ffd5b823567ffffffffffffffff811115611714575f5ffd5b611720858286016116a5565b90969095509350505050565b6001600160a01b03811681146105b8575f5ffd5b80151581146105b8575f5ffd5b5f5f6040838503121561175e575f5ffd5b82356117698161172c565b9150602083013561177981611740565b809150509250929050565b5f60208284031215611794575f5ffd5b5035919050565b5f5f5f5f608085870312156117ae575f5ffd5b84356117b98161172c565b935060208501356117c98161172c565b925060408501356117d98161172c565b9396929550929360600135925050565b5f602082840312156117f9575f5ffd5b81356108bf8161172c565b602080825282518282018190525f918401906040840190835b818110156118445783516001600160a01b031683526020938401939092019160010161181d565b509095945050505050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b5f5f60408385031215611895575f5ffd5b82356118a08161172c565b946020939093013593505050565b60ff811681146105b8575f5ffd5b5f602082840312156118cc575f5ffd5b81356108bf816118ae565b5f5f5f606084860312156118e9575f5ffd5b83356118f48161172c565b925060208401356119048161172c565b929592945050506040919091013590565b5f5f5f60408486031215611927575f5ffd5b833567ffffffffffffffff81111561193d575f5ffd5b611949868287016116a5565b909450925050602084013561195d81611740565b809150509250925092565b634e487b7160e01b5f52603260045260245ffd5b604080825281018390525f8460608301825b868110156119be5782356119a18161172c565b6001600160a01b031682526020928301929091019060010161198e565b5080925050508215156020830152949350505050565b5f602082840312156119e4575f5ffd5b81516108bf81611740565b634e487b7160e01b5f52604160045260245ffd5b5f60208284031215611a13575f5ffd5b815167ffffffffffffffff811115611a29575f5ffd5b8201601f81018413611a39575f5ffd5b805167ffffffffffffffff811115611a5357611a536119ef565b604051601f8201601f19908116603f0116810167ffffffffffffffff81118282101715611a8257611a826119ef565b604052818152828201602001861015611a99575f5ffd5b8160208401602083015e5f91810160200191909152949350505050565b5f60208284031215611ac6575f5ffd5b81516108bf816118ae565b8181038181111561051657634e487b7160e01b5f52601160045260245ffd5b634e487b7160e01b5f52603160045260245ffdfea2646970667358221220a659ba275e7418276483b0a3b605cd7437d92cb06048c0d3af9ee0b308ef258764736f6c63430008250033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/doc/compilation/v3.0.0-rc7/hardhat/RuleEngineOwnable2771.sol/RuleEngineOwnable2771.dbg.json b/doc/compilation/v3.0.0-rc7/hardhat/RuleEngineOwnable2771.sol/RuleEngineOwnable2771.dbg.json new file mode 100644 index 00000000..c25ba54e --- /dev/null +++ b/doc/compilation/v3.0.0-rc7/hardhat/RuleEngineOwnable2771.sol/RuleEngineOwnable2771.dbg.json @@ -0,0 +1,4 @@ +{ + "_format": "hh-sol-dbg-1", + "buildInfo": "../../../../build-info/315e205e547361276a4bba3ad0401f98.json" +} diff --git a/doc/compilation/v3.0.0-rc7/hardhat/RuleEngineOwnable2771.sol/RuleEngineOwnable2771.json b/doc/compilation/v3.0.0-rc7/hardhat/RuleEngineOwnable2771.sol/RuleEngineOwnable2771.json new file mode 100644 index 00000000..92a50baf --- /dev/null +++ b/doc/compilation/v3.0.0-rc7/hardhat/RuleEngineOwnable2771.sol/RuleEngineOwnable2771.json @@ -0,0 +1,883 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "RuleEngineOwnable2771", + "sourceName": "src/deployment/ownable/RuleEngineOwnable2771.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "owner_", + "type": "address" + }, + { + "internalType": "address", + "name": "forwarderIrrevocable", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenContract", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "OwnableInvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "OwnableUnauthorizedAccount", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_AdminWithAddressZeroNotAllowed", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_RuleInvalidInterface", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_RulesManagementModule_ArrayIsEmpty", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "maxRules", + "type": "uint256" + } + ], + "name": "RuleEngine_RulesManagementModule_MaxRulesExceeded", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_RulesManagementModule_MaxRulesZeroNotAllowed", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_RulesManagementModule_RuleAccountCannotReceivePrivileges", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_RulesManagementModule_RuleAddressZeroNotAllowed", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_RulesManagementModule_RuleAlreadyExists", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_RulesManagementModule_RuleDoNotMatch", + "type": "error" + }, + { + "inputs": [], + "name": "TokenBinding_InvalidTokenAddress", + "type": "error" + }, + { + "inputs": [], + "name": "TokenBinding_TokenAlreadyBound", + "type": "error" + }, + { + "inputs": [], + "name": "TokenBinding_TokenNotBound", + "type": "error" + }, + { + "inputs": [], + "name": "TokenBinding_UnauthorizedCaller", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract IRule", + "name": "rule", + "type": "address" + } + ], + "name": "AddRule", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "ClearRules", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract IRule", + "name": "rule", + "type": "address" + } + ], + "name": "RemoveRule", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "maxRules", + "type": "uint256" + } + ], + "name": "SetMaxRules", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "TokenBound", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address[]", + "name": "tokens", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "TokenSelfBindingApprovalBatchSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "TokenSelfBindingApprovalSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "TokenUnbound", + "type": "event" + }, + { + "inputs": [], + "name": "DEFAULT_MAX_RULES", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IRule", + "name": "rule_", + "type": "address" + } + ], + "name": "addRule", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "bindToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "tokens", + "type": "address[]" + } + ], + "name": "bindTokens", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "canTransfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "canTransferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "clearRules", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IRule", + "name": "rule_", + "type": "address" + } + ], + "name": "containsRule", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "created", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "destroyed", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "detectTransferRestriction", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "detectTransferRestrictionFrom", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getTokenBound", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getTokenBounds", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "isTokenBound", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "isTokenSelfBindingApproved", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "forwarder", + "type": "address" + } + ], + "name": "isTrustedForwarder", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maxRules", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "restrictionCode", + "type": "uint8" + } + ], + "name": "messageForTransferRestriction", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IRule", + "name": "rule_", + "type": "address" + } + ], + "name": "removeRule", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "ruleId", + "type": "uint256" + } + ], + "name": "rule", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "rules", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "rulesCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "maxRules_", + "type": "uint256" + } + ], + "name": "setMaxRules", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IRule[]", + "name": "rules_", + "type": "address[]" + } + ], + "name": "setRules", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setTokenSelfBindingApproval", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "tokens", + "type": "address[]" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setTokenSelfBindingApprovalBatch", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transferred", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transferred", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "trustedForwarder", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "unbindToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "tokens", + "type": "address[]" + } + ], + "name": "unbindTokens", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "version_", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x60a0604052600a600255348015610014575f5ffd5b50604051611fe1380380611fe1833981016040819052610033916102b3565b6001600160a01b03808316608052839082908290829081161561005957610059816100a5565b610063600a61013d565b506001600160a01b03811661009157604051631e4fbdf760e01b81525f600482015260240160405180910390fd5b61009a81610192565b5050505050506102f3565b6001600160a01b0381166100cc5760405163135217db60e21b815260040160405180910390fd5b6100d5816101e3565b6100e060038261020e565b6100fd576040516371b3c56560e11b815260040160405180910390fd5b6040516001600160a01b03821681527f2de35142b19ed5a07796cf30791959c592018f70b1d2d7c460eef8ffe713692b906020015b60405180910390a150565b805f0361015d57604051631e69e71760e21b815260040160405180910390fd5b60028190556040518181527f2292ad4720fff63e2bd104c6b1c0d72c2c729a6001c8ab4bb947cbcc5110986390602001610132565b600680546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b6101ed5f8261022b565b1561020b576040516302925f7360e11b815260040160405180910390fd5b50565b5f610222836001600160a01b03841661024c565b90505b92915050565b6001600160a01b0381165f9081526001830160205260408120541515610222565b5f81815260018301602052604081205461029157508154600181810184555f848152602080822090930184905584548482528286019093526040902091909155610225565b505f610225565b80516001600160a01b03811681146102ae575f5ffd5b919050565b5f5f5f606084860312156102c5575f5ffd5b6102ce84610298565b92506102dc60208501610298565b91506102ea60408501610298565b90509250925092565b608051611cc86103195f395f8181610324015281816103b601526115110152611cc85ff3fe608060405234801561000f575f5ffd5b506004361061021e575f3560e01c80638baf29b41161012a578063d32c7bb5116100b4578063e3c4602c11610079578063e3c4602c14610509578063e46638e61461051c578063e54621d21461052f578063f2fde38b14610537578063f76bf5501461054a575f5ffd5b8063d32c7bb514610480578063d4ce1415146104a5578063db18af6c146104b8578063db75d017146104cb578063df21950f146104f6575f5ffd5b8063b043572e116100fa578063b043572e14610437578063b27aef3a1461043f578063bb4b612114610452578063bc13eacc14610465578063c7c24b181461046d575f5ffd5b80638baf29b4146103ed5780638d2ea772146104005780638da5cb5b14610413578063993e8b9514610424575f5ffd5b806354fd4d50116101ab5780636ae728c61161017b5780636ae728c614610387578063715018a6146103995780637157797f146103a15780637da0a877146103b45780637f4ab1dd146103da575f5ffd5b806354fd4d50146102e6578063572b6c05146103145780635f8dead3146103545780636a3edf2814610367575f5ffd5b80633e5af4ca116101f15780633e5af4ca146102855780633ff5aa021461029857806340db3b50146102ab57806352f6747a146102be57806354e4b945146102d3575f5ffd5b806301ffc9a7146102225780631455d0e71461024a5780633284a9a51461025f5780633a56d6d514610272575b5f5ffd5b6102356102303660046117a5565b610552565b60405190151581526020015b60405180910390f35b61025d610258366004611814565b610598565b005b61025d61026d366004611874565b6105e6565b61025d6102803660046118ab565b610623565b61025d6102933660046118c2565b610637565b61025d6102a6366004611910565b610651565b61025d6102b9366004611910565b610663565b6102c6610675565b604051610241919061192b565b6102356102e1366004611910565b610685565b604080518082019091526009815268332e302e302d72633760b81b60208201525b6040516102419190611976565b610235610322366004611910565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0390811691161490565b61025d6103623660046119ab565b610690565b61036f6106a3565b6040516001600160a01b039091168152602001610241565b6002545b604051908152602001610241565b61025d6106c5565b6102356103af3660046118c2565b6106d8565b7f000000000000000000000000000000000000000000000000000000000000000061036f565b6103076103e83660046119e3565b6106f5565b61025d6103fb3660046119fe565b610700565b61025d61040e3660046119ab565b610713565b6006546001600160a01b031661036f565b610235610432366004611910565b610726565b61025d610732565b61025d61044d366004611814565b610742565b61025d610460366004611a3c565b6107f5565b61038b6108c3565b61025d61047b366004611814565b6108cd565b61049361048e3660046118c2565b610916565b60405160ff9091168152602001610241565b6104936104b33660046119fe565b61092c565b61036f6104c63660046118ab565b610942565b6102356104d9366004611910565b6001600160a01b03165f9081526005602052604090205460ff1690565b61025d610504366004611910565b610964565b61025d610517366004611910565b610975565b61023561052a3660046119fe565b6109b7565b6102c66109d0565b61025d610545366004611910565b6109dc565b61038b600a81565b5f61055c826109f6565b8061057757506001600160e01b031982166307f5828d60e41b145b8061059257506301ffc9a760e01b6001600160e01b03198316145b92915050565b6105a0610a97565b5f5b818110156105e1576105d98383838181106105bf576105bf611a8f565b90506020020160208101906105d49190611910565b610a9f565b6001016105a2565b505050565b6105ee610a97565b6001600160a01b0382166106155760405163135217db60e21b815260040160405180910390fd5b61061f8282610aa8565b5050565b61062b610b06565b61063481610b0e565b50565b61063f610b6a565b61064b84848484610b92565b50505050565b61065a81610c34565b61063481610c3d565b61066c81610c34565b61063481610a9f565b60606106805f610cce565b905090565b5f6105928183610cda565b610698610b6a565b61061f5f8383610cfa565b5f5f6106af6003610d93565b11156106c05761068060035f610d9c565b505f90565b6106cd610da7565b6106d65f610e05565b565b5f806106e686868686610916565b60ff161490505b949350505050565b606061059282610e56565b610708610b6a565b6105e1838383610cfa565b61071b610b6a565b61061f825f83610cfa565b5f610592600383610cda565b61073a610b06565b6106d6610fcb565b61074a610b06565b5f81900361076b576040516359203cb960e01b815260040160405180910390fd5b6002548082111561079b57604051630befc49d60e01b815260040161079291815260200190565b60405180910390fd5b505f6107a65f610d93565b11156107b4576107b4610fcb565b5f5b818110156105e1576107ed8383838181106107d3576107d3611a8f565b90506020020160208101906107e89190611910565b610ffc565b6001016107b6565b6107fd610a97565b5f5b82811015610882575f84848381811061081a5761081a611a8f565b905060200201602081019061082f9190611910565b90506001600160a01b0381166108585760405163135217db60e21b815260040160405180910390fd5b6001600160a01b03165f908152600560205260409020805460ff19168315151790556001016107ff565b507f430881f04f203566ee9b32d6444cf02e1b2a0f17ab6b4263a1ee2074d3d0f4838383836040516108b693929190611aa3565b60405180910390a1505050565b5f6106805f610d93565b6108d5610a97565b5f5b818110156105e15761090e8383838181106108f4576108f4611a8f565b90506020020160208101906109099190611910565b610c3d565b6001016108d7565b5f61092385858585611062565b95945050505050565b5f61093884848461112f565b90505b9392505050565b5f61094c5f610d93565b82101561095d576105925f83610d9c565b505f919050565b61096c610b06565b610634816111f3565b61097d610b06565b6002548061098a5f610d93565b1081906109ad57604051630befc49d60e01b815260040161079291815260200190565b5061061f82610ffc565b5f806109c485858561092c565b60ff1614949350505050565b60606106806003610cce565b6109e4610da7565b6109ed81611250565b61063481611277565b5f6001600160e01b031982166320c49ce760e01b1480610a2657506001600160e01b0319821663157094b960e31b145b80610a4157506001600160e01b031982166378a8de7d60e01b145b80610a5c57506001600160e01b03198216630c51264760e21b145b80610a7757506001600160e01b03198216633235d15f60e11b145b8061059257506001600160e01b03198216637157797f60e01b1492915050565b6106d6610b06565b610634816112b1565b6001600160a01b0382165f81815260056020908152604091829020805460ff191685151590811790915591519182527f407b412a9b6db334d48445ec9bcad46fb50bc4b2e97f73e963e397101957a729910160405180910390a25050565b6106d6610da7565b805f03610b2e57604051631e69e71760e21b815260040160405180910390fd5b60028190556040518181527f2292ad4720fff63e2bd104c6b1c0d72c2c729a6001c8ab4bb947cbcc51109863906020015b60405180910390a150565b610b75600333610cda565b6106d657604051630599c0e960e01b815260040160405180910390fd5b5f610b9c5f610d93565b90505f5b81811015610c2c57610bb25f82610d9c565b604051631f2d7a6560e11b81526001600160a01b03888116600483015287811660248301528681166044830152606482018690529190911690633e5af4ca906084015f604051808303815f87803b158015610c0b575f5ffd5b505af1158015610c1d573d5f5f3e3d5ffd5b50505050806001019050610ba0565b505050505050565b610634816112f9565b6001600160a01b038116610c645760405163135217db60e21b815260040160405180910390fd5b610c6d81611338565b610c78600382611342565b610c95576040516371b3c56560e11b815260040160405180910390fd5b6040516001600160a01b03821681527f2de35142b19ed5a07796cf30791959c592018f70b1d2d7c460eef8ffe713692b90602001610b5f565b60605f61093b83611356565b6001600160a01b03165f9081526001919091016020526040902054151590565b5f610d045f610d93565b90505f5b81811015610d8c57610d1a5f82610d9c565b6040516322ebca6d60e21b81526001600160a01b0387811660048301528681166024830152604482018690529190911690638baf29b4906064015f604051808303815f87803b158015610d6b575f5ffd5b505af1158015610d7d573d5f5f3e3d5ffd5b50505050806001019050610d08565b5050505050565b5f610592825490565b5f61093b83836113af565b610daf6113d5565b6001600160a01b0316610dca6006546001600160a01b031690565b6001600160a01b0316146106d657610de06113d5565b60405163118cdaa760e01b81526001600160a01b039091166004820152602401610792565b600680546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b606060ff8216610e8957505060408051808201909152600d81526c2737a932b9ba3934b1ba34b7b760991b602082015290565b5f610e935f610d93565b90505f5b81811015610f8f575f610eaa8183610d9c565b604051633e822efb60e11b815260ff871660048201529091506001600160a01b03821690637d045df690602401602060405180830381865afa158015610ef2573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f169190611afb565b15610f8657604051637f4ab1dd60e01b815260ff861660048201526001600160a01b03821690637f4ab1dd906024015f60405180830381865afa158015610f5f573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526109239190810190611b2a565b50600101610e97565b505060408051808201909152601881527f556e6b6e6f776e207265737472696374696f6e20636f64650000000000000000602082015292915050565b6040517fdbf61473843cd9be1c9791ce51ef66d0da6c9026d62ba80c1ca433b13fb729b2905f90a16106d65f6113de565b611005816113e7565b61100f5f82611342565b61102c5760405163cc790a4b60e01b815260040160405180910390fd5b6040516001600160a01b038216907f60305ce6c9104acd0969d358f926bf391174340660aaf5e6215261fd6847bf46905f90a250565b5f5f61106d5f610d93565b90505f5b81811015611123575f6110848183610d9c565b60405163d32c7bb560e01b81526001600160a01b038a811660048301528981166024830152888116604483015260648201889052919091169063d32c7bb590608401602060405180830381865afa1580156110e1573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111059190611bdd565b905060ff81161561111a5792506106ed915050565b50600101611071565b505f9695505050505050565b5f5f61113a5f610d93565b90505f5b818110156111e8575f6111518183610d9c565b60405163d4ce141560e01b81526001600160a01b038981166004830152888116602483015260448201889052919091169063d4ce141590606401602060405180830381865afa1580156111a6573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111ca9190611bdd565b905060ff8116156111df57925061093b915050565b5060010161113e565b505f95945050505050565b6111fd5f8261143f565b61121a57604051632cdc3a4160e21b815260040160405180910390fd5b6040516001600160a01b038216907f6d83315c9718799346b67584ec64301b1457e989c8e35a8e2982a7776c04bfc4905f90a250565b61125981610685565b15610634576040516302925f7360e11b815260040160405180910390fd5b61127f610da7565b6001600160a01b0381166112a857604051631e4fbdf760e01b81525f6004820152602401610792565b61063481610e05565b6112ba81611453565b336001600160a01b038216148015906112ea57506001600160a01b0381165f9081526005602052604090205460ff165b1561063457610634815f610aa8565b336001600160a01b03821614801561132857506001600160a01b0381165f9081526005602052604090205460ff165b156113305750565b610634610a97565b6112595f82610cda565b5f61093b836001600160a01b0384166114b4565b6060815f018054806020026020016040519081016040528092919081815260200182805480156113a357602002820191905f5260205f20905b81548152602001906001019080831161138f575b50505050509050919050565b5f825f0182815481106113c4576113c4611a8f565b905f5260205f200154905092915050565b5f610680611500565b6106348161156a565b6113f0816115c3565b6113fb600382610cda565b15611419576040516302925f7360e11b815260040160405180910390fd5b611422816115ea565b61063457604051639952e34360e01b815260040160405180910390fd5b5f61093b836001600160a01b038416611627565b61145e60038261143f565b61147b57604051633477dd1760e01b815260040160405180910390fd5b6040516001600160a01b03821681527f28a4ca7134a3b3f9aff286e79ad3daadb4a06d1b43d037a3a98bdc074edd9b7a90602001610b5f565b5f8181526001830160205260408120546114f957508154600181810184555f848152602080822090930184905584548482528286019093526040902091909155610592565b505f610592565b5f36601480821080159061153c57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031633145b156115625761154f36828403815f611bf8565b61155891611c1f565b60601c9250505090565b339250505090565b5f611573825490565b90505f5b818110156115bc57826001015f845f01838154811061159857611598611a8f565b905f5260205f20015481526020019081526020015f205f9055806001019050611577565b50505f9055565b6001600160a01b0381166106345760405163f9d152fb60e01b815260040160405180910390fd5b5f6115f482611711565b6115ff57505f919050565b611610826358d34ba960e11b611750565b80610592575061059282632497d6cb60e01b611750565b5f8181526001830160205260408120548015611701575f611649600183611c5f565b85549091505f9061165c90600190611c5f565b90508082146116bb575f865f01828154811061167a5761167a611a8f565b905f5260205f200154905080875f01848154811061169a5761169a611a8f565b5f918252602080832090910192909255918252600188019052604090208390555b85548690806116cc576116cc611c7e565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f905560019350505050610592565b5f915050610592565b5092915050565b5f611723826301ffc9a760e01b611750565b1561095d575f8061173c846001600160e01b0319611771565b915091508180156106ed5750159392505050565b5f5f5f61175d8585611771565b915091508180156109235750949350505050565b6301ffc9a760e01b5f818152600483905290819060208260248188617530fa92505f511515601f3d11169150509250929050565b5f602082840312156117b5575f5ffd5b81356001600160e01b03198116811461093b575f5ffd5b5f5f83601f8401126117dc575f5ffd5b50813567ffffffffffffffff8111156117f3575f5ffd5b6020830191508360208260051b850101111561180d575f5ffd5b9250929050565b5f5f60208385031215611825575f5ffd5b823567ffffffffffffffff81111561183b575f5ffd5b611847858286016117cc565b90969095509350505050565b6001600160a01b0381168114610634575f5ffd5b8015158114610634575f5ffd5b5f5f60408385031215611885575f5ffd5b823561189081611853565b915060208301356118a081611867565b809150509250929050565b5f602082840312156118bb575f5ffd5b5035919050565b5f5f5f5f608085870312156118d5575f5ffd5b84356118e081611853565b935060208501356118f081611853565b9250604085013561190081611853565b9396929550929360600135925050565b5f60208284031215611920575f5ffd5b813561093b81611853565b602080825282518282018190525f918401906040840190835b8181101561196b5783516001600160a01b0316835260209384019390920191600101611944565b509095945050505050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b5f5f604083850312156119bc575f5ffd5b82356119c781611853565b946020939093013593505050565b60ff81168114610634575f5ffd5b5f602082840312156119f3575f5ffd5b813561093b816119d5565b5f5f5f60608486031215611a10575f5ffd5b8335611a1b81611853565b92506020840135611a2b81611853565b929592945050506040919091013590565b5f5f5f60408486031215611a4e575f5ffd5b833567ffffffffffffffff811115611a64575f5ffd5b611a70868287016117cc565b9094509250506020840135611a8481611867565b809150509250925092565b634e487b7160e01b5f52603260045260245ffd5b604080825281018390525f8460608301825b86811015611ae5578235611ac881611853565b6001600160a01b0316825260209283019290910190600101611ab5565b5080925050508215156020830152949350505050565b5f60208284031215611b0b575f5ffd5b815161093b81611867565b634e487b7160e01b5f52604160045260245ffd5b5f60208284031215611b3a575f5ffd5b815167ffffffffffffffff811115611b50575f5ffd5b8201601f81018413611b60575f5ffd5b805167ffffffffffffffff811115611b7a57611b7a611b16565b604051601f8201601f19908116603f0116810167ffffffffffffffff81118282101715611ba957611ba9611b16565b604052818152828201602001861015611bc0575f5ffd5b8160208401602083015e5f91810160200191909152949350505050565b5f60208284031215611bed575f5ffd5b815161093b816119d5565b5f5f85851115611c06575f5ffd5b83861115611c12575f5ffd5b5050820193919092039150565b80356bffffffffffffffffffffffff19811690601484101561170a576bffffffffffffffffffffffff1960149490940360031b84901b1690921692915050565b8181038181111561059257634e487b7160e01b5f52601160045260245ffd5b634e487b7160e01b5f52603160045260245ffdfea264697066735822122039be34739e2babdcc08c279eff5773f7b1777ed8900b1a83d0c5828dc6e09c6264736f6c63430008250033", + "deployedBytecode": "0x608060405234801561000f575f5ffd5b506004361061021e575f3560e01c80638baf29b41161012a578063d32c7bb5116100b4578063e3c4602c11610079578063e3c4602c14610509578063e46638e61461051c578063e54621d21461052f578063f2fde38b14610537578063f76bf5501461054a575f5ffd5b8063d32c7bb514610480578063d4ce1415146104a5578063db18af6c146104b8578063db75d017146104cb578063df21950f146104f6575f5ffd5b8063b043572e116100fa578063b043572e14610437578063b27aef3a1461043f578063bb4b612114610452578063bc13eacc14610465578063c7c24b181461046d575f5ffd5b80638baf29b4146103ed5780638d2ea772146104005780638da5cb5b14610413578063993e8b9514610424575f5ffd5b806354fd4d50116101ab5780636ae728c61161017b5780636ae728c614610387578063715018a6146103995780637157797f146103a15780637da0a877146103b45780637f4ab1dd146103da575f5ffd5b806354fd4d50146102e6578063572b6c05146103145780635f8dead3146103545780636a3edf2814610367575f5ffd5b80633e5af4ca116101f15780633e5af4ca146102855780633ff5aa021461029857806340db3b50146102ab57806352f6747a146102be57806354e4b945146102d3575f5ffd5b806301ffc9a7146102225780631455d0e71461024a5780633284a9a51461025f5780633a56d6d514610272575b5f5ffd5b6102356102303660046117a5565b610552565b60405190151581526020015b60405180910390f35b61025d610258366004611814565b610598565b005b61025d61026d366004611874565b6105e6565b61025d6102803660046118ab565b610623565b61025d6102933660046118c2565b610637565b61025d6102a6366004611910565b610651565b61025d6102b9366004611910565b610663565b6102c6610675565b604051610241919061192b565b6102356102e1366004611910565b610685565b604080518082019091526009815268332e302e302d72633760b81b60208201525b6040516102419190611976565b610235610322366004611910565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0390811691161490565b61025d6103623660046119ab565b610690565b61036f6106a3565b6040516001600160a01b039091168152602001610241565b6002545b604051908152602001610241565b61025d6106c5565b6102356103af3660046118c2565b6106d8565b7f000000000000000000000000000000000000000000000000000000000000000061036f565b6103076103e83660046119e3565b6106f5565b61025d6103fb3660046119fe565b610700565b61025d61040e3660046119ab565b610713565b6006546001600160a01b031661036f565b610235610432366004611910565b610726565b61025d610732565b61025d61044d366004611814565b610742565b61025d610460366004611a3c565b6107f5565b61038b6108c3565b61025d61047b366004611814565b6108cd565b61049361048e3660046118c2565b610916565b60405160ff9091168152602001610241565b6104936104b33660046119fe565b61092c565b61036f6104c63660046118ab565b610942565b6102356104d9366004611910565b6001600160a01b03165f9081526005602052604090205460ff1690565b61025d610504366004611910565b610964565b61025d610517366004611910565b610975565b61023561052a3660046119fe565b6109b7565b6102c66109d0565b61025d610545366004611910565b6109dc565b61038b600a81565b5f61055c826109f6565b8061057757506001600160e01b031982166307f5828d60e41b145b8061059257506301ffc9a760e01b6001600160e01b03198316145b92915050565b6105a0610a97565b5f5b818110156105e1576105d98383838181106105bf576105bf611a8f565b90506020020160208101906105d49190611910565b610a9f565b6001016105a2565b505050565b6105ee610a97565b6001600160a01b0382166106155760405163135217db60e21b815260040160405180910390fd5b61061f8282610aa8565b5050565b61062b610b06565b61063481610b0e565b50565b61063f610b6a565b61064b84848484610b92565b50505050565b61065a81610c34565b61063481610c3d565b61066c81610c34565b61063481610a9f565b60606106805f610cce565b905090565b5f6105928183610cda565b610698610b6a565b61061f5f8383610cfa565b5f5f6106af6003610d93565b11156106c05761068060035f610d9c565b505f90565b6106cd610da7565b6106d65f610e05565b565b5f806106e686868686610916565b60ff161490505b949350505050565b606061059282610e56565b610708610b6a565b6105e1838383610cfa565b61071b610b6a565b61061f825f83610cfa565b5f610592600383610cda565b61073a610b06565b6106d6610fcb565b61074a610b06565b5f81900361076b576040516359203cb960e01b815260040160405180910390fd5b6002548082111561079b57604051630befc49d60e01b815260040161079291815260200190565b60405180910390fd5b505f6107a65f610d93565b11156107b4576107b4610fcb565b5f5b818110156105e1576107ed8383838181106107d3576107d3611a8f565b90506020020160208101906107e89190611910565b610ffc565b6001016107b6565b6107fd610a97565b5f5b82811015610882575f84848381811061081a5761081a611a8f565b905060200201602081019061082f9190611910565b90506001600160a01b0381166108585760405163135217db60e21b815260040160405180910390fd5b6001600160a01b03165f908152600560205260409020805460ff19168315151790556001016107ff565b507f430881f04f203566ee9b32d6444cf02e1b2a0f17ab6b4263a1ee2074d3d0f4838383836040516108b693929190611aa3565b60405180910390a1505050565b5f6106805f610d93565b6108d5610a97565b5f5b818110156105e15761090e8383838181106108f4576108f4611a8f565b90506020020160208101906109099190611910565b610c3d565b6001016108d7565b5f61092385858585611062565b95945050505050565b5f61093884848461112f565b90505b9392505050565b5f61094c5f610d93565b82101561095d576105925f83610d9c565b505f919050565b61096c610b06565b610634816111f3565b61097d610b06565b6002548061098a5f610d93565b1081906109ad57604051630befc49d60e01b815260040161079291815260200190565b5061061f82610ffc565b5f806109c485858561092c565b60ff1614949350505050565b60606106806003610cce565b6109e4610da7565b6109ed81611250565b61063481611277565b5f6001600160e01b031982166320c49ce760e01b1480610a2657506001600160e01b0319821663157094b960e31b145b80610a4157506001600160e01b031982166378a8de7d60e01b145b80610a5c57506001600160e01b03198216630c51264760e21b145b80610a7757506001600160e01b03198216633235d15f60e11b145b8061059257506001600160e01b03198216637157797f60e01b1492915050565b6106d6610b06565b610634816112b1565b6001600160a01b0382165f81815260056020908152604091829020805460ff191685151590811790915591519182527f407b412a9b6db334d48445ec9bcad46fb50bc4b2e97f73e963e397101957a729910160405180910390a25050565b6106d6610da7565b805f03610b2e57604051631e69e71760e21b815260040160405180910390fd5b60028190556040518181527f2292ad4720fff63e2bd104c6b1c0d72c2c729a6001c8ab4bb947cbcc51109863906020015b60405180910390a150565b610b75600333610cda565b6106d657604051630599c0e960e01b815260040160405180910390fd5b5f610b9c5f610d93565b90505f5b81811015610c2c57610bb25f82610d9c565b604051631f2d7a6560e11b81526001600160a01b03888116600483015287811660248301528681166044830152606482018690529190911690633e5af4ca906084015f604051808303815f87803b158015610c0b575f5ffd5b505af1158015610c1d573d5f5f3e3d5ffd5b50505050806001019050610ba0565b505050505050565b610634816112f9565b6001600160a01b038116610c645760405163135217db60e21b815260040160405180910390fd5b610c6d81611338565b610c78600382611342565b610c95576040516371b3c56560e11b815260040160405180910390fd5b6040516001600160a01b03821681527f2de35142b19ed5a07796cf30791959c592018f70b1d2d7c460eef8ffe713692b90602001610b5f565b60605f61093b83611356565b6001600160a01b03165f9081526001919091016020526040902054151590565b5f610d045f610d93565b90505f5b81811015610d8c57610d1a5f82610d9c565b6040516322ebca6d60e21b81526001600160a01b0387811660048301528681166024830152604482018690529190911690638baf29b4906064015f604051808303815f87803b158015610d6b575f5ffd5b505af1158015610d7d573d5f5f3e3d5ffd5b50505050806001019050610d08565b5050505050565b5f610592825490565b5f61093b83836113af565b610daf6113d5565b6001600160a01b0316610dca6006546001600160a01b031690565b6001600160a01b0316146106d657610de06113d5565b60405163118cdaa760e01b81526001600160a01b039091166004820152602401610792565b600680546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b606060ff8216610e8957505060408051808201909152600d81526c2737a932b9ba3934b1ba34b7b760991b602082015290565b5f610e935f610d93565b90505f5b81811015610f8f575f610eaa8183610d9c565b604051633e822efb60e11b815260ff871660048201529091506001600160a01b03821690637d045df690602401602060405180830381865afa158015610ef2573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f169190611afb565b15610f8657604051637f4ab1dd60e01b815260ff861660048201526001600160a01b03821690637f4ab1dd906024015f60405180830381865afa158015610f5f573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526109239190810190611b2a565b50600101610e97565b505060408051808201909152601881527f556e6b6e6f776e207265737472696374696f6e20636f64650000000000000000602082015292915050565b6040517fdbf61473843cd9be1c9791ce51ef66d0da6c9026d62ba80c1ca433b13fb729b2905f90a16106d65f6113de565b611005816113e7565b61100f5f82611342565b61102c5760405163cc790a4b60e01b815260040160405180910390fd5b6040516001600160a01b038216907f60305ce6c9104acd0969d358f926bf391174340660aaf5e6215261fd6847bf46905f90a250565b5f5f61106d5f610d93565b90505f5b81811015611123575f6110848183610d9c565b60405163d32c7bb560e01b81526001600160a01b038a811660048301528981166024830152888116604483015260648201889052919091169063d32c7bb590608401602060405180830381865afa1580156110e1573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111059190611bdd565b905060ff81161561111a5792506106ed915050565b50600101611071565b505f9695505050505050565b5f5f61113a5f610d93565b90505f5b818110156111e8575f6111518183610d9c565b60405163d4ce141560e01b81526001600160a01b038981166004830152888116602483015260448201889052919091169063d4ce141590606401602060405180830381865afa1580156111a6573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111ca9190611bdd565b905060ff8116156111df57925061093b915050565b5060010161113e565b505f95945050505050565b6111fd5f8261143f565b61121a57604051632cdc3a4160e21b815260040160405180910390fd5b6040516001600160a01b038216907f6d83315c9718799346b67584ec64301b1457e989c8e35a8e2982a7776c04bfc4905f90a250565b61125981610685565b15610634576040516302925f7360e11b815260040160405180910390fd5b61127f610da7565b6001600160a01b0381166112a857604051631e4fbdf760e01b81525f6004820152602401610792565b61063481610e05565b6112ba81611453565b336001600160a01b038216148015906112ea57506001600160a01b0381165f9081526005602052604090205460ff165b1561063457610634815f610aa8565b336001600160a01b03821614801561132857506001600160a01b0381165f9081526005602052604090205460ff165b156113305750565b610634610a97565b6112595f82610cda565b5f61093b836001600160a01b0384166114b4565b6060815f018054806020026020016040519081016040528092919081815260200182805480156113a357602002820191905f5260205f20905b81548152602001906001019080831161138f575b50505050509050919050565b5f825f0182815481106113c4576113c4611a8f565b905f5260205f200154905092915050565b5f610680611500565b6106348161156a565b6113f0816115c3565b6113fb600382610cda565b15611419576040516302925f7360e11b815260040160405180910390fd5b611422816115ea565b61063457604051639952e34360e01b815260040160405180910390fd5b5f61093b836001600160a01b038416611627565b61145e60038261143f565b61147b57604051633477dd1760e01b815260040160405180910390fd5b6040516001600160a01b03821681527f28a4ca7134a3b3f9aff286e79ad3daadb4a06d1b43d037a3a98bdc074edd9b7a90602001610b5f565b5f8181526001830160205260408120546114f957508154600181810184555f848152602080822090930184905584548482528286019093526040902091909155610592565b505f610592565b5f36601480821080159061153c57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031633145b156115625761154f36828403815f611bf8565b61155891611c1f565b60601c9250505090565b339250505090565b5f611573825490565b90505f5b818110156115bc57826001015f845f01838154811061159857611598611a8f565b905f5260205f20015481526020019081526020015f205f9055806001019050611577565b50505f9055565b6001600160a01b0381166106345760405163f9d152fb60e01b815260040160405180910390fd5b5f6115f482611711565b6115ff57505f919050565b611610826358d34ba960e11b611750565b80610592575061059282632497d6cb60e01b611750565b5f8181526001830160205260408120548015611701575f611649600183611c5f565b85549091505f9061165c90600190611c5f565b90508082146116bb575f865f01828154811061167a5761167a611a8f565b905f5260205f200154905080875f01848154811061169a5761169a611a8f565b5f918252602080832090910192909255918252600188019052604090208390555b85548690806116cc576116cc611c7e565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f905560019350505050610592565b5f915050610592565b5092915050565b5f611723826301ffc9a760e01b611750565b1561095d575f8061173c846001600160e01b0319611771565b915091508180156106ed5750159392505050565b5f5f5f61175d8585611771565b915091508180156109235750949350505050565b6301ffc9a760e01b5f818152600483905290819060208260248188617530fa92505f511515601f3d11169150509250929050565b5f602082840312156117b5575f5ffd5b81356001600160e01b03198116811461093b575f5ffd5b5f5f83601f8401126117dc575f5ffd5b50813567ffffffffffffffff8111156117f3575f5ffd5b6020830191508360208260051b850101111561180d575f5ffd5b9250929050565b5f5f60208385031215611825575f5ffd5b823567ffffffffffffffff81111561183b575f5ffd5b611847858286016117cc565b90969095509350505050565b6001600160a01b0381168114610634575f5ffd5b8015158114610634575f5ffd5b5f5f60408385031215611885575f5ffd5b823561189081611853565b915060208301356118a081611867565b809150509250929050565b5f602082840312156118bb575f5ffd5b5035919050565b5f5f5f5f608085870312156118d5575f5ffd5b84356118e081611853565b935060208501356118f081611853565b9250604085013561190081611853565b9396929550929360600135925050565b5f60208284031215611920575f5ffd5b813561093b81611853565b602080825282518282018190525f918401906040840190835b8181101561196b5783516001600160a01b0316835260209384019390920191600101611944565b509095945050505050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b5f5f604083850312156119bc575f5ffd5b82356119c781611853565b946020939093013593505050565b60ff81168114610634575f5ffd5b5f602082840312156119f3575f5ffd5b813561093b816119d5565b5f5f5f60608486031215611a10575f5ffd5b8335611a1b81611853565b92506020840135611a2b81611853565b929592945050506040919091013590565b5f5f5f60408486031215611a4e575f5ffd5b833567ffffffffffffffff811115611a64575f5ffd5b611a70868287016117cc565b9094509250506020840135611a8481611867565b809150509250925092565b634e487b7160e01b5f52603260045260245ffd5b604080825281018390525f8460608301825b86811015611ae5578235611ac881611853565b6001600160a01b0316825260209283019290910190600101611ab5565b5080925050508215156020830152949350505050565b5f60208284031215611b0b575f5ffd5b815161093b81611867565b634e487b7160e01b5f52604160045260245ffd5b5f60208284031215611b3a575f5ffd5b815167ffffffffffffffff811115611b50575f5ffd5b8201601f81018413611b60575f5ffd5b805167ffffffffffffffff811115611b7a57611b7a611b16565b604051601f8201601f19908116603f0116810167ffffffffffffffff81118282101715611ba957611ba9611b16565b604052818152828201602001861015611bc0575f5ffd5b8160208401602083015e5f91810160200191909152949350505050565b5f60208284031215611bed575f5ffd5b815161093b816119d5565b5f5f85851115611c06575f5ffd5b83861115611c12575f5ffd5b5050820193919092039150565b80356bffffffffffffffffffffffff19811690601484101561170a576bffffffffffffffffffffffff1960149490940360031b84901b1690921692915050565b8181038181111561059257634e487b7160e01b5f52601160045260245ffd5b634e487b7160e01b5f52603160045260245ffdfea264697066735822122039be34739e2babdcc08c279eff5773f7b1777ed8900b1a83d0c5828dc6e09c6264736f6c63430008250033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/doc/compilation/v3.0.0-rc7/hardhat/RuleEngineOwnable2Step.sol/RuleEngineOwnable2Step.dbg.json b/doc/compilation/v3.0.0-rc7/hardhat/RuleEngineOwnable2Step.sol/RuleEngineOwnable2Step.dbg.json new file mode 100644 index 00000000..c25ba54e --- /dev/null +++ b/doc/compilation/v3.0.0-rc7/hardhat/RuleEngineOwnable2Step.sol/RuleEngineOwnable2Step.dbg.json @@ -0,0 +1,4 @@ +{ + "_format": "hh-sol-dbg-1", + "buildInfo": "../../../../build-info/315e205e547361276a4bba3ad0401f98.json" +} diff --git a/doc/compilation/v3.0.0-rc7/hardhat/RuleEngineOwnable2Step.sol/RuleEngineOwnable2Step.json b/doc/compilation/v3.0.0-rc7/hardhat/RuleEngineOwnable2Step.sol/RuleEngineOwnable2Step.json new file mode 100644 index 00000000..7e9363ea --- /dev/null +++ b/doc/compilation/v3.0.0-rc7/hardhat/RuleEngineOwnable2Step.sol/RuleEngineOwnable2Step.json @@ -0,0 +1,885 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "RuleEngineOwnable2Step", + "sourceName": "src/deployment/ownable/RuleEngineOwnable2Step.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "owner_", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenContract", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "OwnableInvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "OwnableUnauthorizedAccount", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_AdminWithAddressZeroNotAllowed", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_RuleInvalidInterface", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_RulesManagementModule_ArrayIsEmpty", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "maxRules", + "type": "uint256" + } + ], + "name": "RuleEngine_RulesManagementModule_MaxRulesExceeded", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_RulesManagementModule_MaxRulesZeroNotAllowed", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_RulesManagementModule_RuleAccountCannotReceivePrivileges", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_RulesManagementModule_RuleAddressZeroNotAllowed", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_RulesManagementModule_RuleAlreadyExists", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_RulesManagementModule_RuleDoNotMatch", + "type": "error" + }, + { + "inputs": [], + "name": "TokenBinding_InvalidTokenAddress", + "type": "error" + }, + { + "inputs": [], + "name": "TokenBinding_TokenAlreadyBound", + "type": "error" + }, + { + "inputs": [], + "name": "TokenBinding_TokenNotBound", + "type": "error" + }, + { + "inputs": [], + "name": "TokenBinding_UnauthorizedCaller", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract IRule", + "name": "rule", + "type": "address" + } + ], + "name": "AddRule", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "ClearRules", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferStarted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract IRule", + "name": "rule", + "type": "address" + } + ], + "name": "RemoveRule", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "maxRules", + "type": "uint256" + } + ], + "name": "SetMaxRules", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "TokenBound", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address[]", + "name": "tokens", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "TokenSelfBindingApprovalBatchSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "TokenSelfBindingApprovalSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "TokenUnbound", + "type": "event" + }, + { + "inputs": [], + "name": "DEFAULT_MAX_RULES", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IRule", + "name": "rule_", + "type": "address" + } + ], + "name": "addRule", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "bindToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "tokens", + "type": "address[]" + } + ], + "name": "bindTokens", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "canTransfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "canTransferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "clearRules", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IRule", + "name": "rule_", + "type": "address" + } + ], + "name": "containsRule", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "created", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "destroyed", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "detectTransferRestriction", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "detectTransferRestrictionFrom", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getTokenBound", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getTokenBounds", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "isTokenBound", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "isTokenSelfBindingApproved", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maxRules", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "restrictionCode", + "type": "uint8" + } + ], + "name": "messageForTransferRestriction", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IRule", + "name": "rule_", + "type": "address" + } + ], + "name": "removeRule", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "ruleId", + "type": "uint256" + } + ], + "name": "rule", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "rules", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "rulesCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "maxRules_", + "type": "uint256" + } + ], + "name": "setMaxRules", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IRule[]", + "name": "rules_", + "type": "address[]" + } + ], + "name": "setRules", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setTokenSelfBindingApproval", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "tokens", + "type": "address[]" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setTokenSelfBindingApprovalBatch", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transferred", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transferred", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "unbindToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "tokens", + "type": "address[]" + } + ], + "name": "unbindTokens", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "version_", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x6080604052600a600255348015610014575f5ffd5b50604051611f2e380380611f2e833981016040819052610033916102bd565b81816001600160a01b0381161561004d5761004d81610096565b610057600a61012e565b506001600160a01b03811661008557604051631e4fbdf760e01b81525f600482015260240160405180910390fd5b61008e81610183565b5050506102ee565b6001600160a01b0381166100bd5760405163135217db60e21b815260040160405180910390fd5b6100c68161019f565b6100d16003826101c7565b6100ee576040516371b3c56560e11b815260040160405180910390fd5b6040516001600160a01b03821681527f2de35142b19ed5a07796cf30791959c592018f70b1d2d7c460eef8ffe713692b906020015b60405180910390a150565b805f0361014e57604051631e69e71760e21b815260040160405180910390fd5b60028190556040518181527f2292ad4720fff63e2bd104c6b1c0d72c2c729a6001c8ab4bb947cbcc5110986390602001610123565b600780546001600160a01b031916905561019c816101e4565b50565b6101a95f82610235565b1561019c576040516302925f7360e11b815260040160405180910390fd5b5f6101db836001600160a01b038416610256565b90505b92915050565b600680546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b6001600160a01b0381165f90815260018301602052604081205415156101db565b5f81815260018301602052604081205461029b57508154600181810184555f8481526020808220909301849055845484825282860190935260409020919091556101de565b505f6101de565b80516001600160a01b03811681146102b8575f5ffd5b919050565b5f5f604083850312156102ce575f5ffd5b6102d7836102a2565b91506102e5602084016102a2565b90509250929050565b611c33806102fb5f395ff3fe608060405234801561000f575f5ffd5b506004361061021e575f3560e01c80638d2ea7721161012a578063d4ce1415116100b4578063e3c4602c11610079578063e3c4602c146104bc578063e46638e6146104cf578063e54621d2146104e2578063f2fde38b146104ea578063f76bf550146104fd575f5ffd5b8063d4ce141514610447578063db18af6c1461045a578063db75d0171461046d578063df21950f14610498578063e30c3978146104ab575f5ffd5b8063b27aef3a116100fa578063b27aef3a146103e1578063bb4b6121146103f4578063bc13eacc14610407578063c7c24b181461040f578063d32c7bb514610422575f5ffd5b80638d2ea772146103a25780638da5cb5b146103b5578063993e8b95146103c6578063b043572e146103d9575f5ffd5b806354fd4d50116101ab578063715018a61161017b578063715018a6146103595780637157797f1461036157806379ba5097146103745780637f4ab1dd1461037c5780638baf29b41461038f575f5ffd5b806354fd4d50146102e65780635f8dead3146103145780636a3edf28146103275780636ae728c614610347575f5ffd5b80633e5af4ca116101f15780633e5af4ca146102855780633ff5aa021461029857806340db3b50146102ab57806352f6747a146102be57806354e4b945146102d3575f5ffd5b806301ffc9a7146102225780631455d0e71461024a5780633284a9a51461025f5780633a56d6d514610272575b5f5ffd5b610235610230366004611777565b610505565b60405190151581526020015b60405180910390f35b61025d6102583660046117e6565b61052f565b005b61025d61026d366004611846565b61057d565b61025d61028036600461187d565b6105ba565b61025d610293366004611894565b6105ce565b61025d6102a63660046118e2565b6105e8565b61025d6102b93660046118e2565b6105fa565b6102c661060c565b60405161024191906118fd565b6102356102e13660046118e2565b61061c565b604080518082019091526009815268332e302e302d72633760b81b60208201525b6040516102419190611948565b61025d61032236600461197d565b610627565b61032f61063a565b6040516001600160a01b039091168152602001610241565b6002545b604051908152602001610241565b61025d61065c565b61023561036f366004611894565b61066f565b61025d61068c565b61030761038a3660046119b5565b61069d565b61025d61039d3660046119d0565b6106a8565b61025d6103b036600461197d565b6106bb565b6006546001600160a01b031661032f565b6102356103d43660046118e2565b6106ce565b61025d6106da565b61025d6103ef3660046117e6565b6106ea565b61025d610402366004611a0e565b61079d565b61034b61086b565b61025d61041d3660046117e6565b610875565b610435610430366004611894565b6108be565b60405160ff9091168152602001610241565b6104356104553660046119d0565b6108d4565b61032f61046836600461187d565b6108ea565b61023561047b3660046118e2565b6001600160a01b03165f9081526005602052604090205460ff1690565b61025d6104a63660046118e2565b61090c565b6007546001600160a01b031661032f565b61025d6104ca3660046118e2565b61091d565b6102356104dd3660046119d0565b61095f565b6102c6610978565b61025d6104f83660046118e2565b610984565b61034b600a81565b5f6001600160e01b03198216639ab669ef60e01b148061052957506105298261099e565b92915050565b6105376109e2565b5f5b818110156105785761057083838381811061055657610556611a61565b905060200201602081019061056b91906118e2565b6109ea565b600101610539565b505050565b6105856109e2565b6001600160a01b0382166105ac5760405163135217db60e21b815260040160405180910390fd5b6105b682826109f3565b5050565b6105c2610a51565b6105cb81610a59565b50565b6105d6610ab5565b6105e284848484610add565b50505050565b6105f181610b7f565b6105cb81610b88565b61060381610b7f565b6105cb816109ea565b60606106175f610c19565b905090565b5f6105298183610c25565b61062f610ab5565b6105b65f8383610c45565b5f5f6106466003610cde565b11156106575761061760035f610ce7565b505f90565b610664610cf2565b61066d5f610d1f565b565b5f8061067d868686866108be565b60ff161490505b949350505050565b61069533610d38565b61066d610d5f565b606061052982610da0565b6106b0610ab5565b610578838383610c45565b6106c3610ab5565b6105b6825f83610c45565b5f610529600383610c25565b6106e2610a51565b61066d610f15565b6106f2610a51565b5f819003610713576040516359203cb960e01b815260040160405180910390fd5b6002548082111561074357604051630befc49d60e01b815260040161073a91815260200190565b60405180910390fd5b505f61074e5f610cde565b111561075c5761075c610f15565b5f5b818110156105785761079583838381811061077b5761077b611a61565b905060200201602081019061079091906118e2565b610f46565b60010161075e565b6107a56109e2565b5f5b8281101561082a575f8484838181106107c2576107c2611a61565b90506020020160208101906107d791906118e2565b90506001600160a01b0381166108005760405163135217db60e21b815260040160405180910390fd5b6001600160a01b03165f908152600560205260409020805460ff19168315151790556001016107a7565b507f430881f04f203566ee9b32d6444cf02e1b2a0f17ab6b4263a1ee2074d3d0f48383838360405161085e93929190611a75565b60405180910390a1505050565b5f6106175f610cde565b61087d6109e2565b5f5b81811015610578576108b683838381811061089c5761089c611a61565b90506020020160208101906108b191906118e2565b610b88565b60010161087f565b5f6108cb85858585610fac565b95945050505050565b5f6108e0848484611079565b90505b9392505050565b5f6108f45f610cde565b821015610905576105295f83610ce7565b505f919050565b610914610a51565b6105cb8161113d565b610925610a51565b600254806109325f610cde565b10819061095557604051630befc49d60e01b815260040161073a91815260200190565b506105b682610f46565b5f8061096c8585856108d4565b60ff1614949350505050565b60606106176003610c19565b61098c610cf2565b61099581610d38565b6105cb8161119a565b5f6109a88261120b565b806109c357506001600160e01b031982166307f5828d60e41b145b8061052957506301ffc9a760e01b6001600160e01b0319831614610529565b61066d610a51565b6105cb816112ac565b6001600160a01b0382165f81815260056020908152604091829020805460ff191685151590811790915591519182527f407b412a9b6db334d48445ec9bcad46fb50bc4b2e97f73e963e397101957a729910160405180910390a25050565b61066d610cf2565b805f03610a7957604051631e69e71760e21b815260040160405180910390fd5b60028190556040518181527f2292ad4720fff63e2bd104c6b1c0d72c2c729a6001c8ab4bb947cbcc51109863906020015b60405180910390a150565b610ac0600333610c25565b61066d57604051630599c0e960e01b815260040160405180910390fd5b5f610ae75f610cde565b90505f5b81811015610b7757610afd5f82610ce7565b604051631f2d7a6560e11b81526001600160a01b03888116600483015287811660248301528681166044830152606482018690529190911690633e5af4ca906084015f604051808303815f87803b158015610b56575f5ffd5b505af1158015610b68573d5f5f3e3d5ffd5b50505050806001019050610aeb565b505050505050565b6105cb816112f4565b6001600160a01b038116610baf5760405163135217db60e21b815260040160405180910390fd5b610bb881611333565b610bc360038261133d565b610be0576040516371b3c56560e11b815260040160405180910390fd5b6040516001600160a01b03821681527f2de35142b19ed5a07796cf30791959c592018f70b1d2d7c460eef8ffe713692b90602001610aaa565b60605f6108e383611351565b6001600160a01b03165f9081526001919091016020526040902054151590565b5f610c4f5f610cde565b90505f5b81811015610cd757610c655f82610ce7565b6040516322ebca6d60e21b81526001600160a01b0387811660048301528681166024830152604482018690529190911690638baf29b4906064015f604051808303815f87803b158015610cb6575f5ffd5b505af1158015610cc8573d5f5f3e3d5ffd5b50505050806001019050610c53565b5050505050565b5f610529825490565b5f6108e383836113aa565b6006546001600160a01b0316331461066d5760405163118cdaa760e01b815233600482015260240161073a565b600780546001600160a01b03191690556105cb816113d0565b610d418161061c565b156105cb576040516302925f7360e11b815260040160405180910390fd5b60075433906001600160a01b03168114610d975760405163118cdaa760e01b81526001600160a01b038216600482015260240161073a565b6105cb81610d1f565b606060ff8216610dd357505060408051808201909152600d81526c2737a932b9ba3934b1ba34b7b760991b602082015290565b5f610ddd5f610cde565b90505f5b81811015610ed9575f610df48183610ce7565b604051633e822efb60e11b815260ff871660048201529091506001600160a01b03821690637d045df690602401602060405180830381865afa158015610e3c573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e609190611acd565b15610ed057604051637f4ab1dd60e01b815260ff861660048201526001600160a01b03821690637f4ab1dd906024015f60405180830381865afa158015610ea9573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526108cb9190810190611afc565b50600101610de1565b505060408051808201909152601881527f556e6b6e6f776e207265737472696374696f6e20636f64650000000000000000602082015292915050565b6040517fdbf61473843cd9be1c9791ce51ef66d0da6c9026d62ba80c1ca433b13fb729b2905f90a161066d5f611421565b610f4f8161142a565b610f595f8261133d565b610f765760405163cc790a4b60e01b815260040160405180910390fd5b6040516001600160a01b038216907f60305ce6c9104acd0969d358f926bf391174340660aaf5e6215261fd6847bf46905f90a250565b5f5f610fb75f610cde565b90505f5b8181101561106d575f610fce8183610ce7565b60405163d32c7bb560e01b81526001600160a01b038a811660048301528981166024830152888116604483015260648201889052919091169063d32c7bb590608401602060405180830381865afa15801561102b573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061104f9190611baf565b905060ff811615611064579250610684915050565b50600101610fbb565b505f9695505050505050565b5f5f6110845f610cde565b90505f5b81811015611132575f61109b8183610ce7565b60405163d4ce141560e01b81526001600160a01b038981166004830152888116602483015260448201889052919091169063d4ce141590606401602060405180830381865afa1580156110f0573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111149190611baf565b905060ff8116156111295792506108e3915050565b50600101611088565b505f95945050505050565b6111475f82611482565b61116457604051632cdc3a4160e21b815260040160405180910390fd5b6040516001600160a01b038216907f6d83315c9718799346b67584ec64301b1457e989c8e35a8e2982a7776c04bfc4905f90a250565b6111a2610cf2565b600780546001600160a01b0383166001600160a01b031990911681179091556111d36006546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b5f6001600160e01b031982166320c49ce760e01b148061123b57506001600160e01b0319821663157094b960e31b145b8061125657506001600160e01b031982166378a8de7d60e01b145b8061127157506001600160e01b03198216630c51264760e21b145b8061128c57506001600160e01b03198216633235d15f60e11b145b8061052957506001600160e01b03198216637157797f60e01b1492915050565b6112b581611496565b336001600160a01b038216148015906112e557506001600160a01b0381165f9081526005602052604090205460ff165b156105cb576105cb815f6109f3565b336001600160a01b03821614801561132357506001600160a01b0381165f9081526005602052604090205460ff165b1561132b5750565b6105cb6109e2565b610d415f82610c25565b5f6108e3836001600160a01b0384166114f7565b6060815f0180548060200260200160405190810160405280929190818152602001828054801561139e57602002820191905f5260205f20905b81548152602001906001019080831161138a575b50505050509050919050565b5f825f0182815481106113bf576113bf611a61565b905f5260205f200154905092915050565b600680546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b6105cb81611543565b6114338161159c565b61143e600382610c25565b1561145c576040516302925f7360e11b815260040160405180910390fd5b611465816115c3565b6105cb57604051639952e34360e01b815260040160405180910390fd5b5f6108e3836001600160a01b038416611600565b6114a1600382611482565b6114be57604051633477dd1760e01b815260040160405180910390fd5b6040516001600160a01b03821681527f28a4ca7134a3b3f9aff286e79ad3daadb4a06d1b43d037a3a98bdc074edd9b7a90602001610aaa565b5f81815260018301602052604081205461153c57508154600181810184555f848152602080822090930184905584548482528286019093526040902091909155610529565b505f610529565b5f61154c825490565b90505f5b8181101561159557826001015f845f01838154811061157157611571611a61565b905f5260205f20015481526020019081526020015f205f9055806001019050611550565b50505f9055565b6001600160a01b0381166105cb5760405163f9d152fb60e01b815260040160405180910390fd5b5f6115cd826116e3565b6115d857505f919050565b6115e9826358d34ba960e11b611722565b80610529575061052982632497d6cb60e01b611722565b5f81815260018301602052604081205480156116da575f611622600183611bca565b85549091505f9061163590600190611bca565b9050808214611694575f865f01828154811061165357611653611a61565b905f5260205f200154905080875f01848154811061167357611673611a61565b5f918252602080832090910192909255918252600188019052604090208390555b85548690806116a5576116a5611be9565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f905560019350505050610529565b5f915050610529565b5f6116f5826301ffc9a760e01b611722565b15610905575f8061170e846001600160e01b0319611743565b915091508180156106845750159392505050565b5f5f5f61172f8585611743565b915091508180156108cb5750949350505050565b6301ffc9a760e01b5f818152600483905290819060208260248188617530fa92505f511515601f3d11169150509250929050565b5f60208284031215611787575f5ffd5b81356001600160e01b0319811681146108e3575f5ffd5b5f5f83601f8401126117ae575f5ffd5b50813567ffffffffffffffff8111156117c5575f5ffd5b6020830191508360208260051b85010111156117df575f5ffd5b9250929050565b5f5f602083850312156117f7575f5ffd5b823567ffffffffffffffff81111561180d575f5ffd5b6118198582860161179e565b90969095509350505050565b6001600160a01b03811681146105cb575f5ffd5b80151581146105cb575f5ffd5b5f5f60408385031215611857575f5ffd5b823561186281611825565b9150602083013561187281611839565b809150509250929050565b5f6020828403121561188d575f5ffd5b5035919050565b5f5f5f5f608085870312156118a7575f5ffd5b84356118b281611825565b935060208501356118c281611825565b925060408501356118d281611825565b9396929550929360600135925050565b5f602082840312156118f2575f5ffd5b81356108e381611825565b602080825282518282018190525f918401906040840190835b8181101561193d5783516001600160a01b0316835260209384019390920191600101611916565b509095945050505050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b5f5f6040838503121561198e575f5ffd5b823561199981611825565b946020939093013593505050565b60ff811681146105cb575f5ffd5b5f602082840312156119c5575f5ffd5b81356108e3816119a7565b5f5f5f606084860312156119e2575f5ffd5b83356119ed81611825565b925060208401356119fd81611825565b929592945050506040919091013590565b5f5f5f60408486031215611a20575f5ffd5b833567ffffffffffffffff811115611a36575f5ffd5b611a428682870161179e565b9094509250506020840135611a5681611839565b809150509250925092565b634e487b7160e01b5f52603260045260245ffd5b604080825281018390525f8460608301825b86811015611ab7578235611a9a81611825565b6001600160a01b0316825260209283019290910190600101611a87565b5080925050508215156020830152949350505050565b5f60208284031215611add575f5ffd5b81516108e381611839565b634e487b7160e01b5f52604160045260245ffd5b5f60208284031215611b0c575f5ffd5b815167ffffffffffffffff811115611b22575f5ffd5b8201601f81018413611b32575f5ffd5b805167ffffffffffffffff811115611b4c57611b4c611ae8565b604051601f8201601f19908116603f0116810167ffffffffffffffff81118282101715611b7b57611b7b611ae8565b604052818152828201602001861015611b92575f5ffd5b8160208401602083015e5f91810160200191909152949350505050565b5f60208284031215611bbf575f5ffd5b81516108e3816119a7565b8181038181111561052957634e487b7160e01b5f52601160045260245ffd5b634e487b7160e01b5f52603160045260245ffdfea2646970667358221220e848d9b6377117bb40b527b8d79a6f1523a283d8ad3cc4c9c69c04129020a36364736f6c63430008250033", + "deployedBytecode": "0x608060405234801561000f575f5ffd5b506004361061021e575f3560e01c80638d2ea7721161012a578063d4ce1415116100b4578063e3c4602c11610079578063e3c4602c146104bc578063e46638e6146104cf578063e54621d2146104e2578063f2fde38b146104ea578063f76bf550146104fd575f5ffd5b8063d4ce141514610447578063db18af6c1461045a578063db75d0171461046d578063df21950f14610498578063e30c3978146104ab575f5ffd5b8063b27aef3a116100fa578063b27aef3a146103e1578063bb4b6121146103f4578063bc13eacc14610407578063c7c24b181461040f578063d32c7bb514610422575f5ffd5b80638d2ea772146103a25780638da5cb5b146103b5578063993e8b95146103c6578063b043572e146103d9575f5ffd5b806354fd4d50116101ab578063715018a61161017b578063715018a6146103595780637157797f1461036157806379ba5097146103745780637f4ab1dd1461037c5780638baf29b41461038f575f5ffd5b806354fd4d50146102e65780635f8dead3146103145780636a3edf28146103275780636ae728c614610347575f5ffd5b80633e5af4ca116101f15780633e5af4ca146102855780633ff5aa021461029857806340db3b50146102ab57806352f6747a146102be57806354e4b945146102d3575f5ffd5b806301ffc9a7146102225780631455d0e71461024a5780633284a9a51461025f5780633a56d6d514610272575b5f5ffd5b610235610230366004611777565b610505565b60405190151581526020015b60405180910390f35b61025d6102583660046117e6565b61052f565b005b61025d61026d366004611846565b61057d565b61025d61028036600461187d565b6105ba565b61025d610293366004611894565b6105ce565b61025d6102a63660046118e2565b6105e8565b61025d6102b93660046118e2565b6105fa565b6102c661060c565b60405161024191906118fd565b6102356102e13660046118e2565b61061c565b604080518082019091526009815268332e302e302d72633760b81b60208201525b6040516102419190611948565b61025d61032236600461197d565b610627565b61032f61063a565b6040516001600160a01b039091168152602001610241565b6002545b604051908152602001610241565b61025d61065c565b61023561036f366004611894565b61066f565b61025d61068c565b61030761038a3660046119b5565b61069d565b61025d61039d3660046119d0565b6106a8565b61025d6103b036600461197d565b6106bb565b6006546001600160a01b031661032f565b6102356103d43660046118e2565b6106ce565b61025d6106da565b61025d6103ef3660046117e6565b6106ea565b61025d610402366004611a0e565b61079d565b61034b61086b565b61025d61041d3660046117e6565b610875565b610435610430366004611894565b6108be565b60405160ff9091168152602001610241565b6104356104553660046119d0565b6108d4565b61032f61046836600461187d565b6108ea565b61023561047b3660046118e2565b6001600160a01b03165f9081526005602052604090205460ff1690565b61025d6104a63660046118e2565b61090c565b6007546001600160a01b031661032f565b61025d6104ca3660046118e2565b61091d565b6102356104dd3660046119d0565b61095f565b6102c6610978565b61025d6104f83660046118e2565b610984565b61034b600a81565b5f6001600160e01b03198216639ab669ef60e01b148061052957506105298261099e565b92915050565b6105376109e2565b5f5b818110156105785761057083838381811061055657610556611a61565b905060200201602081019061056b91906118e2565b6109ea565b600101610539565b505050565b6105856109e2565b6001600160a01b0382166105ac5760405163135217db60e21b815260040160405180910390fd5b6105b682826109f3565b5050565b6105c2610a51565b6105cb81610a59565b50565b6105d6610ab5565b6105e284848484610add565b50505050565b6105f181610b7f565b6105cb81610b88565b61060381610b7f565b6105cb816109ea565b60606106175f610c19565b905090565b5f6105298183610c25565b61062f610ab5565b6105b65f8383610c45565b5f5f6106466003610cde565b11156106575761061760035f610ce7565b505f90565b610664610cf2565b61066d5f610d1f565b565b5f8061067d868686866108be565b60ff161490505b949350505050565b61069533610d38565b61066d610d5f565b606061052982610da0565b6106b0610ab5565b610578838383610c45565b6106c3610ab5565b6105b6825f83610c45565b5f610529600383610c25565b6106e2610a51565b61066d610f15565b6106f2610a51565b5f819003610713576040516359203cb960e01b815260040160405180910390fd5b6002548082111561074357604051630befc49d60e01b815260040161073a91815260200190565b60405180910390fd5b505f61074e5f610cde565b111561075c5761075c610f15565b5f5b818110156105785761079583838381811061077b5761077b611a61565b905060200201602081019061079091906118e2565b610f46565b60010161075e565b6107a56109e2565b5f5b8281101561082a575f8484838181106107c2576107c2611a61565b90506020020160208101906107d791906118e2565b90506001600160a01b0381166108005760405163135217db60e21b815260040160405180910390fd5b6001600160a01b03165f908152600560205260409020805460ff19168315151790556001016107a7565b507f430881f04f203566ee9b32d6444cf02e1b2a0f17ab6b4263a1ee2074d3d0f48383838360405161085e93929190611a75565b60405180910390a1505050565b5f6106175f610cde565b61087d6109e2565b5f5b81811015610578576108b683838381811061089c5761089c611a61565b90506020020160208101906108b191906118e2565b610b88565b60010161087f565b5f6108cb85858585610fac565b95945050505050565b5f6108e0848484611079565b90505b9392505050565b5f6108f45f610cde565b821015610905576105295f83610ce7565b505f919050565b610914610a51565b6105cb8161113d565b610925610a51565b600254806109325f610cde565b10819061095557604051630befc49d60e01b815260040161073a91815260200190565b506105b682610f46565b5f8061096c8585856108d4565b60ff1614949350505050565b60606106176003610c19565b61098c610cf2565b61099581610d38565b6105cb8161119a565b5f6109a88261120b565b806109c357506001600160e01b031982166307f5828d60e41b145b8061052957506301ffc9a760e01b6001600160e01b0319831614610529565b61066d610a51565b6105cb816112ac565b6001600160a01b0382165f81815260056020908152604091829020805460ff191685151590811790915591519182527f407b412a9b6db334d48445ec9bcad46fb50bc4b2e97f73e963e397101957a729910160405180910390a25050565b61066d610cf2565b805f03610a7957604051631e69e71760e21b815260040160405180910390fd5b60028190556040518181527f2292ad4720fff63e2bd104c6b1c0d72c2c729a6001c8ab4bb947cbcc51109863906020015b60405180910390a150565b610ac0600333610c25565b61066d57604051630599c0e960e01b815260040160405180910390fd5b5f610ae75f610cde565b90505f5b81811015610b7757610afd5f82610ce7565b604051631f2d7a6560e11b81526001600160a01b03888116600483015287811660248301528681166044830152606482018690529190911690633e5af4ca906084015f604051808303815f87803b158015610b56575f5ffd5b505af1158015610b68573d5f5f3e3d5ffd5b50505050806001019050610aeb565b505050505050565b6105cb816112f4565b6001600160a01b038116610baf5760405163135217db60e21b815260040160405180910390fd5b610bb881611333565b610bc360038261133d565b610be0576040516371b3c56560e11b815260040160405180910390fd5b6040516001600160a01b03821681527f2de35142b19ed5a07796cf30791959c592018f70b1d2d7c460eef8ffe713692b90602001610aaa565b60605f6108e383611351565b6001600160a01b03165f9081526001919091016020526040902054151590565b5f610c4f5f610cde565b90505f5b81811015610cd757610c655f82610ce7565b6040516322ebca6d60e21b81526001600160a01b0387811660048301528681166024830152604482018690529190911690638baf29b4906064015f604051808303815f87803b158015610cb6575f5ffd5b505af1158015610cc8573d5f5f3e3d5ffd5b50505050806001019050610c53565b5050505050565b5f610529825490565b5f6108e383836113aa565b6006546001600160a01b0316331461066d5760405163118cdaa760e01b815233600482015260240161073a565b600780546001600160a01b03191690556105cb816113d0565b610d418161061c565b156105cb576040516302925f7360e11b815260040160405180910390fd5b60075433906001600160a01b03168114610d975760405163118cdaa760e01b81526001600160a01b038216600482015260240161073a565b6105cb81610d1f565b606060ff8216610dd357505060408051808201909152600d81526c2737a932b9ba3934b1ba34b7b760991b602082015290565b5f610ddd5f610cde565b90505f5b81811015610ed9575f610df48183610ce7565b604051633e822efb60e11b815260ff871660048201529091506001600160a01b03821690637d045df690602401602060405180830381865afa158015610e3c573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610e609190611acd565b15610ed057604051637f4ab1dd60e01b815260ff861660048201526001600160a01b03821690637f4ab1dd906024015f60405180830381865afa158015610ea9573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f191682016040526108cb9190810190611afc565b50600101610de1565b505060408051808201909152601881527f556e6b6e6f776e207265737472696374696f6e20636f64650000000000000000602082015292915050565b6040517fdbf61473843cd9be1c9791ce51ef66d0da6c9026d62ba80c1ca433b13fb729b2905f90a161066d5f611421565b610f4f8161142a565b610f595f8261133d565b610f765760405163cc790a4b60e01b815260040160405180910390fd5b6040516001600160a01b038216907f60305ce6c9104acd0969d358f926bf391174340660aaf5e6215261fd6847bf46905f90a250565b5f5f610fb75f610cde565b90505f5b8181101561106d575f610fce8183610ce7565b60405163d32c7bb560e01b81526001600160a01b038a811660048301528981166024830152888116604483015260648201889052919091169063d32c7bb590608401602060405180830381865afa15801561102b573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061104f9190611baf565b905060ff811615611064579250610684915050565b50600101610fbb565b505f9695505050505050565b5f5f6110845f610cde565b90505f5b81811015611132575f61109b8183610ce7565b60405163d4ce141560e01b81526001600160a01b038981166004830152888116602483015260448201889052919091169063d4ce141590606401602060405180830381865afa1580156110f0573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111149190611baf565b905060ff8116156111295792506108e3915050565b50600101611088565b505f95945050505050565b6111475f82611482565b61116457604051632cdc3a4160e21b815260040160405180910390fd5b6040516001600160a01b038216907f6d83315c9718799346b67584ec64301b1457e989c8e35a8e2982a7776c04bfc4905f90a250565b6111a2610cf2565b600780546001600160a01b0383166001600160a01b031990911681179091556111d36006546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b5f6001600160e01b031982166320c49ce760e01b148061123b57506001600160e01b0319821663157094b960e31b145b8061125657506001600160e01b031982166378a8de7d60e01b145b8061127157506001600160e01b03198216630c51264760e21b145b8061128c57506001600160e01b03198216633235d15f60e11b145b8061052957506001600160e01b03198216637157797f60e01b1492915050565b6112b581611496565b336001600160a01b038216148015906112e557506001600160a01b0381165f9081526005602052604090205460ff165b156105cb576105cb815f6109f3565b336001600160a01b03821614801561132357506001600160a01b0381165f9081526005602052604090205460ff165b1561132b5750565b6105cb6109e2565b610d415f82610c25565b5f6108e3836001600160a01b0384166114f7565b6060815f0180548060200260200160405190810160405280929190818152602001828054801561139e57602002820191905f5260205f20905b81548152602001906001019080831161138a575b50505050509050919050565b5f825f0182815481106113bf576113bf611a61565b905f5260205f200154905092915050565b600680546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b6105cb81611543565b6114338161159c565b61143e600382610c25565b1561145c576040516302925f7360e11b815260040160405180910390fd5b611465816115c3565b6105cb57604051639952e34360e01b815260040160405180910390fd5b5f6108e3836001600160a01b038416611600565b6114a1600382611482565b6114be57604051633477dd1760e01b815260040160405180910390fd5b6040516001600160a01b03821681527f28a4ca7134a3b3f9aff286e79ad3daadb4a06d1b43d037a3a98bdc074edd9b7a90602001610aaa565b5f81815260018301602052604081205461153c57508154600181810184555f848152602080822090930184905584548482528286019093526040902091909155610529565b505f610529565b5f61154c825490565b90505f5b8181101561159557826001015f845f01838154811061157157611571611a61565b905f5260205f20015481526020019081526020015f205f9055806001019050611550565b50505f9055565b6001600160a01b0381166105cb5760405163f9d152fb60e01b815260040160405180910390fd5b5f6115cd826116e3565b6115d857505f919050565b6115e9826358d34ba960e11b611722565b80610529575061052982632497d6cb60e01b611722565b5f81815260018301602052604081205480156116da575f611622600183611bca565b85549091505f9061163590600190611bca565b9050808214611694575f865f01828154811061165357611653611a61565b905f5260205f200154905080875f01848154811061167357611673611a61565b5f918252602080832090910192909255918252600188019052604090208390555b85548690806116a5576116a5611be9565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f905560019350505050610529565b5f915050610529565b5f6116f5826301ffc9a760e01b611722565b15610905575f8061170e846001600160e01b0319611743565b915091508180156106845750159392505050565b5f5f5f61172f8585611743565b915091508180156108cb5750949350505050565b6301ffc9a760e01b5f818152600483905290819060208260248188617530fa92505f511515601f3d11169150509250929050565b5f60208284031215611787575f5ffd5b81356001600160e01b0319811681146108e3575f5ffd5b5f5f83601f8401126117ae575f5ffd5b50813567ffffffffffffffff8111156117c5575f5ffd5b6020830191508360208260051b85010111156117df575f5ffd5b9250929050565b5f5f602083850312156117f7575f5ffd5b823567ffffffffffffffff81111561180d575f5ffd5b6118198582860161179e565b90969095509350505050565b6001600160a01b03811681146105cb575f5ffd5b80151581146105cb575f5ffd5b5f5f60408385031215611857575f5ffd5b823561186281611825565b9150602083013561187281611839565b809150509250929050565b5f6020828403121561188d575f5ffd5b5035919050565b5f5f5f5f608085870312156118a7575f5ffd5b84356118b281611825565b935060208501356118c281611825565b925060408501356118d281611825565b9396929550929360600135925050565b5f602082840312156118f2575f5ffd5b81356108e381611825565b602080825282518282018190525f918401906040840190835b8181101561193d5783516001600160a01b0316835260209384019390920191600101611916565b509095945050505050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b5f5f6040838503121561198e575f5ffd5b823561199981611825565b946020939093013593505050565b60ff811681146105cb575f5ffd5b5f602082840312156119c5575f5ffd5b81356108e3816119a7565b5f5f5f606084860312156119e2575f5ffd5b83356119ed81611825565b925060208401356119fd81611825565b929592945050506040919091013590565b5f5f5f60408486031215611a20575f5ffd5b833567ffffffffffffffff811115611a36575f5ffd5b611a428682870161179e565b9094509250506020840135611a5681611839565b809150509250925092565b634e487b7160e01b5f52603260045260245ffd5b604080825281018390525f8460608301825b86811015611ab7578235611a9a81611825565b6001600160a01b0316825260209283019290910190600101611a87565b5080925050508215156020830152949350505050565b5f60208284031215611add575f5ffd5b81516108e381611839565b634e487b7160e01b5f52604160045260245ffd5b5f60208284031215611b0c575f5ffd5b815167ffffffffffffffff811115611b22575f5ffd5b8201601f81018413611b32575f5ffd5b805167ffffffffffffffff811115611b4c57611b4c611ae8565b604051601f8201601f19908116603f0116810167ffffffffffffffff81118282101715611b7b57611b7b611ae8565b604052818152828201602001861015611b92575f5ffd5b8160208401602083015e5f91810160200191909152949350505050565b5f60208284031215611bbf575f5ffd5b81516108e3816119a7565b8181038181111561052957634e487b7160e01b5f52601160045260245ffd5b634e487b7160e01b5f52603160045260245ffdfea2646970667358221220e848d9b6377117bb40b527b8d79a6f1523a283d8ad3cc4c9c69c04129020a36364736f6c63430008250033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/doc/compilation/v3.0.0-rc7/hardhat/RuleEngineOwnable2Step2771.sol/RuleEngineOwnable2Step2771.dbg.json b/doc/compilation/v3.0.0-rc7/hardhat/RuleEngineOwnable2Step2771.sol/RuleEngineOwnable2Step2771.dbg.json new file mode 100644 index 00000000..c25ba54e --- /dev/null +++ b/doc/compilation/v3.0.0-rc7/hardhat/RuleEngineOwnable2Step2771.sol/RuleEngineOwnable2Step2771.dbg.json @@ -0,0 +1,4 @@ +{ + "_format": "hh-sol-dbg-1", + "buildInfo": "../../../../build-info/315e205e547361276a4bba3ad0401f98.json" +} diff --git a/doc/compilation/v3.0.0-rc7/hardhat/RuleEngineOwnable2Step2771.sol/RuleEngineOwnable2Step2771.json b/doc/compilation/v3.0.0-rc7/hardhat/RuleEngineOwnable2Step2771.sol/RuleEngineOwnable2Step2771.json new file mode 100644 index 00000000..8730350c --- /dev/null +++ b/doc/compilation/v3.0.0-rc7/hardhat/RuleEngineOwnable2Step2771.sol/RuleEngineOwnable2Step2771.json @@ -0,0 +1,922 @@ +{ + "_format": "hh-sol-artifact-1", + "contractName": "RuleEngineOwnable2Step2771", + "sourceName": "src/deployment/ownable/RuleEngineOwnable2Step2771.sol", + "abi": [ + { + "inputs": [ + { + "internalType": "address", + "name": "owner_", + "type": "address" + }, + { + "internalType": "address", + "name": "forwarderIrrevocable", + "type": "address" + }, + { + "internalType": "address", + "name": "tokenContract", + "type": "address" + } + ], + "stateMutability": "nonpayable", + "type": "constructor" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "owner", + "type": "address" + } + ], + "name": "OwnableInvalidOwner", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "account", + "type": "address" + } + ], + "name": "OwnableUnauthorizedAccount", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_AdminWithAddressZeroNotAllowed", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_RuleInvalidInterface", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_RulesManagementModule_ArrayIsEmpty", + "type": "error" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "maxRules", + "type": "uint256" + } + ], + "name": "RuleEngine_RulesManagementModule_MaxRulesExceeded", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_RulesManagementModule_MaxRulesZeroNotAllowed", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_RulesManagementModule_RuleAccountCannotReceivePrivileges", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_RulesManagementModule_RuleAddressZeroNotAllowed", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_RulesManagementModule_RuleAlreadyExists", + "type": "error" + }, + { + "inputs": [], + "name": "RuleEngine_RulesManagementModule_RuleDoNotMatch", + "type": "error" + }, + { + "inputs": [], + "name": "TokenBinding_InvalidTokenAddress", + "type": "error" + }, + { + "inputs": [], + "name": "TokenBinding_TokenAlreadyBound", + "type": "error" + }, + { + "inputs": [], + "name": "TokenBinding_TokenNotBound", + "type": "error" + }, + { + "inputs": [], + "name": "TokenBinding_UnauthorizedCaller", + "type": "error" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract IRule", + "name": "rule", + "type": "address" + } + ], + "name": "AddRule", + "type": "event" + }, + { + "anonymous": false, + "inputs": [], + "name": "ClearRules", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferStarted", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "previousOwner", + "type": "address" + }, + { + "indexed": true, + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "OwnershipTransferred", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "contract IRule", + "name": "rule", + "type": "address" + } + ], + "name": "RemoveRule", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "uint256", + "name": "maxRules", + "type": "uint256" + } + ], + "name": "SetMaxRules", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "TokenBound", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address[]", + "name": "tokens", + "type": "address[]" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "TokenSelfBindingApprovalBatchSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": true, + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "indexed": false, + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "TokenSelfBindingApprovalSet", + "type": "event" + }, + { + "anonymous": false, + "inputs": [ + { + "indexed": false, + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "TokenUnbound", + "type": "event" + }, + { + "inputs": [], + "name": "DEFAULT_MAX_RULES", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "acceptOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IRule", + "name": "rule_", + "type": "address" + } + ], + "name": "addRule", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "bindToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "tokens", + "type": "address[]" + } + ], + "name": "bindTokens", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "canTransfer", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "canTransferFrom", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "clearRules", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IRule", + "name": "rule_", + "type": "address" + } + ], + "name": "containsRule", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "created", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "destroyed", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "detectTransferRestriction", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "detectTransferRestrictionFrom", + "outputs": [ + { + "internalType": "uint8", + "name": "", + "type": "uint8" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getTokenBound", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "getTokenBounds", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "isTokenBound", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "isTokenSelfBindingApproved", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "forwarder", + "type": "address" + } + ], + "name": "isTrustedForwarder", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "maxRules", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint8", + "name": "restrictionCode", + "type": "uint8" + } + ], + "name": "messageForTransferRestriction", + "outputs": [ + { + "internalType": "string", + "name": "", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "owner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "pendingOwner", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IRule", + "name": "rule_", + "type": "address" + } + ], + "name": "removeRule", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "renounceOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "ruleId", + "type": "uint256" + } + ], + "name": "rule", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "rules", + "outputs": [ + { + "internalType": "address[]", + "name": "", + "type": "address[]" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [], + "name": "rulesCount", + "outputs": [ + { + "internalType": "uint256", + "name": "", + "type": "uint256" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "uint256", + "name": "maxRules_", + "type": "uint256" + } + ], + "name": "setMaxRules", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "contract IRule[]", + "name": "rules_", + "type": "address[]" + } + ], + "name": "setRules", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setTokenSelfBindingApproval", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "tokens", + "type": "address[]" + }, + { + "internalType": "bool", + "name": "approved", + "type": "bool" + } + ], + "name": "setTokenSelfBindingApprovalBatch", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "bytes4", + "name": "interfaceId", + "type": "bytes4" + } + ], + "name": "supportsInterface", + "outputs": [ + { + "internalType": "bool", + "name": "", + "type": "bool" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "newOwner", + "type": "address" + } + ], + "name": "transferOwnership", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "spender", + "type": "address" + }, + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transferred", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "from", + "type": "address" + }, + { + "internalType": "address", + "name": "to", + "type": "address" + }, + { + "internalType": "uint256", + "name": "value", + "type": "uint256" + } + ], + "name": "transferred", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "trustedForwarder", + "outputs": [ + { + "internalType": "address", + "name": "", + "type": "address" + } + ], + "stateMutability": "view", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address", + "name": "token", + "type": "address" + } + ], + "name": "unbindToken", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [ + { + "internalType": "address[]", + "name": "tokens", + "type": "address[]" + } + ], + "name": "unbindTokens", + "outputs": [], + "stateMutability": "nonpayable", + "type": "function" + }, + { + "inputs": [], + "name": "version", + "outputs": [ + { + "internalType": "string", + "name": "version_", + "type": "string" + } + ], + "stateMutability": "view", + "type": "function" + } + ], + "bytecode": "0x60a0604052600a600255348015610014575f5ffd5b5060405161211b38038061211b833981016040819052610033916102cc565b6001600160a01b03808316608052839082908290829081161561005957610059816100a5565b610063600a61013d565b506001600160a01b03811661009157604051631e4fbdf760e01b81525f600482015260240160405180910390fd5b61009a81610192565b50505050505061030c565b6001600160a01b0381166100cc5760405163135217db60e21b815260040160405180910390fd5b6100d5816101ae565b6100e06003826101d6565b6100fd576040516371b3c56560e11b815260040160405180910390fd5b6040516001600160a01b03821681527f2de35142b19ed5a07796cf30791959c592018f70b1d2d7c460eef8ffe713692b906020015b60405180910390a150565b805f0361015d57604051631e69e71760e21b815260040160405180910390fd5b60028190556040518181527f2292ad4720fff63e2bd104c6b1c0d72c2c729a6001c8ab4bb947cbcc5110986390602001610132565b600780546001600160a01b03191690556101ab816101f3565b50565b6101b85f82610244565b156101ab576040516302925f7360e11b815260040160405180910390fd5b5f6101ea836001600160a01b038416610265565b90505b92915050565b600680546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b6001600160a01b0381165f90815260018301602052604081205415156101ea565b5f8181526001830160205260408120546102aa57508154600181810184555f8481526020808220909301849055845484825282860190935260409020919091556101ed565b505f6101ed565b80516001600160a01b03811681146102c7575f5ffd5b919050565b5f5f5f606084860312156102de575f5ffd5b6102e7846102b1565b92506102f5602085016102b1565b9150610303604085016102b1565b90509250925092565b608051611de96103325f395f818161033a015281816103d401526115100152611de95ff3fe608060405234801561000f575f5ffd5b5060043610610234575f3560e01c80638baf29b411610135578063d4ce1415116100b4578063e3c4602c11610079578063e3c4602c14610538578063e46638e61461054b578063e54621d21461055e578063f2fde38b14610566578063f76bf55014610579575f5ffd5b8063d4ce1415146104c3578063db18af6c146104d6578063db75d017146104e9578063df21950f14610514578063e30c397814610527575f5ffd5b8063b27aef3a116100fa578063b27aef3a1461045d578063bb4b612114610470578063bc13eacc14610483578063c7c24b181461048b578063d32c7bb51461049e575f5ffd5b80638baf29b41461040b5780638d2ea7721461041e5780638da5cb5b14610431578063993e8b9514610442578063b043572e14610455575f5ffd5b806354fd4d50116101c1578063715018a611610186578063715018a6146103af5780637157797f146103b757806379ba5097146103ca5780637da0a877146103d25780637f4ab1dd146103f8575f5ffd5b806354fd4d50146102fc578063572b6c051461032a5780635f8dead31461036a5780636a3edf281461037d5780636ae728c61461039d575f5ffd5b80633e5af4ca116102075780633e5af4ca1461029b5780633ff5aa02146102ae57806340db3b50146102c157806352f6747a146102d457806354e4b945146102e9575f5ffd5b806301ffc9a7146102385780631455d0e7146102605780633284a9a5146102755780633a56d6d514610288575b5f5ffd5b61024b6102463660046118c6565b610581565b60405190151581526020015b60405180910390f35b61027361026e366004611935565b6105ab565b005b610273610283366004611995565b6105f9565b6102736102963660046119cc565b610636565b6102736102a93660046119e3565b61064a565b6102736102bc366004611a31565b610664565b6102736102cf366004611a31565b610676565b6102dc610688565b6040516102579190611a4c565b61024b6102f7366004611a31565b610698565b604080518082019091526009815268332e302e302d72633760b81b60208201525b6040516102579190611a97565b61024b610338366004611a31565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0390811691161490565b610273610378366004611acc565b6106a3565b6103856106b6565b6040516001600160a01b039091168152602001610257565b6002545b604051908152602001610257565b6102736106d8565b61024b6103c53660046119e3565b6106eb565b610273610708565b7f0000000000000000000000000000000000000000000000000000000000000000610385565b61031d610406366004611b04565b610720565b610273610419366004611b1f565b61072b565b61027361042c366004611acc565b61073e565b6006546001600160a01b0316610385565b61024b610450366004611a31565b610751565b61027361075d565b61027361046b366004611935565b61076d565b61027361047e366004611b5d565b610820565b6103a16108ee565b610273610499366004611935565b6108f8565b6104b16104ac3660046119e3565b610941565b60405160ff9091168152602001610257565b6104b16104d1366004611b1f565b610957565b6103856104e43660046119cc565b61096d565b61024b6104f7366004611a31565b6001600160a01b03165f9081526005602052604090205460ff1690565b610273610522366004611a31565b61098f565b6007546001600160a01b0316610385565b610273610546366004611a31565b6109a0565b61024b610559366004611b1f565b6109e2565b6102dc6109fb565b610273610574366004611a31565b610a07565b6103a1600a81565b5f6001600160e01b03198216639ab669ef60e01b14806105a557506105a582610a21565b92915050565b6105b3610a65565b5f5b818110156105f4576105ec8383838181106105d2576105d2611bb0565b90506020020160208101906105e79190611a31565b610a6d565b6001016105b5565b505050565b610601610a65565b6001600160a01b0382166106285760405163135217db60e21b815260040160405180910390fd5b6106328282610a76565b5050565b61063e610ad4565b61064781610adc565b50565b610652610b38565b61065e84848484610b60565b50505050565b61066d81610c02565b61064781610c0b565b61067f81610c02565b61064781610a6d565b60606106935f610c9c565b905090565b5f6105a58183610ca8565b6106ab610b38565b6106325f8383610cc8565b5f5f6106c26003610d61565b11156106d35761069360035f610d6a565b505f90565b6106e0610d75565b6106e95f610dd3565b565b5f806106f986868686610941565b60ff161490505b949350505050565b610718610713610dec565b610df5565b6106e9610e1c565b60606105a582610e7e565b610733610b38565b6105f4838383610cc8565b610746610b38565b610632825f83610cc8565b5f6105a5600383610ca8565b610765610ad4565b6106e9610ff3565b610775610ad4565b5f819003610796576040516359203cb960e01b815260040160405180910390fd5b600254808211156107c657604051630befc49d60e01b81526004016107bd91815260200190565b60405180910390fd5b505f6107d15f610d61565b11156107df576107df610ff3565b5f5b818110156105f4576108188383838181106107fe576107fe611bb0565b90506020020160208101906108139190611a31565b611024565b6001016107e1565b610828610a65565b5f5b828110156108ad575f84848381811061084557610845611bb0565b905060200201602081019061085a9190611a31565b90506001600160a01b0381166108835760405163135217db60e21b815260040160405180910390fd5b6001600160a01b03165f908152600560205260409020805460ff191683151517905560010161082a565b507f430881f04f203566ee9b32d6444cf02e1b2a0f17ab6b4263a1ee2074d3d0f4838383836040516108e193929190611bc4565b60405180910390a1505050565b5f6106935f610d61565b610900610a65565b5f5b818110156105f45761093983838381811061091f5761091f611bb0565b90506020020160208101906109349190611a31565b610c0b565b600101610902565b5f61094e8585858561108a565b95945050505050565b5f610963848484611157565b90505b9392505050565b5f6109775f610d61565b821015610988576105a55f83610d6a565b505f919050565b610997610ad4565b6106478161121b565b6109a8610ad4565b600254806109b55f610d61565b1081906109d857604051630befc49d60e01b81526004016107bd91815260200190565b5061063282611024565b5f806109ef858585610957565b60ff1614949350505050565b60606106936003610c9c565b610a0f610d75565b610a1881610df5565b61064781611278565b5f610a2b826112e9565b80610a4657506001600160e01b031982166307f5828d60e41b145b806105a557506301ffc9a760e01b6001600160e01b03198316146105a5565b6106e9610ad4565b6106478161138a565b6001600160a01b0382165f81815260056020908152604091829020805460ff191685151590811790915591519182527f407b412a9b6db334d48445ec9bcad46fb50bc4b2e97f73e963e397101957a729910160405180910390a25050565b6106e9610d75565b805f03610afc57604051631e69e71760e21b815260040160405180910390fd5b60028190556040518181527f2292ad4720fff63e2bd104c6b1c0d72c2c729a6001c8ab4bb947cbcc51109863906020015b60405180910390a150565b610b43600333610ca8565b6106e957604051630599c0e960e01b815260040160405180910390fd5b5f610b6a5f610d61565b90505f5b81811015610bfa57610b805f82610d6a565b604051631f2d7a6560e11b81526001600160a01b03888116600483015287811660248301528681166044830152606482018690529190911690633e5af4ca906084015f604051808303815f87803b158015610bd9575f5ffd5b505af1158015610beb573d5f5f3e3d5ffd5b50505050806001019050610b6e565b505050505050565b610647816113d2565b6001600160a01b038116610c325760405163135217db60e21b815260040160405180910390fd5b610c3b81611411565b610c4660038261141b565b610c63576040516371b3c56560e11b815260040160405180910390fd5b6040516001600160a01b03821681527f2de35142b19ed5a07796cf30791959c592018f70b1d2d7c460eef8ffe713692b90602001610b2d565b60605f6109668361142f565b6001600160a01b03165f9081526001919091016020526040902054151590565b5f610cd25f610d61565b90505f5b81811015610d5a57610ce85f82610d6a565b6040516322ebca6d60e21b81526001600160a01b0387811660048301528681166024830152604482018690529190911690638baf29b4906064015f604051808303815f87803b158015610d39575f5ffd5b505af1158015610d4b573d5f5f3e3d5ffd5b50505050806001019050610cd6565b5050505050565b5f6105a5825490565b5f6109668383611488565b610d7d610dec565b6001600160a01b0316610d986006546001600160a01b031690565b6001600160a01b0316146106e957610dae610dec565b60405163118cdaa760e01b81526001600160a01b0390911660048201526024016107bd565b600780546001600160a01b0319169055610647816114ae565b5f6106936114ff565b610dfe81610698565b15610647576040516302925f7360e11b815260040160405180910390fd5b5f610e25610dec565b9050806001600160a01b0316610e436007546001600160a01b031690565b6001600160a01b031614610e755760405163118cdaa760e01b81526001600160a01b03821660048201526024016107bd565b61064781610dd3565b606060ff8216610eb157505060408051808201909152600d81526c2737a932b9ba3934b1ba34b7b760991b602082015290565b5f610ebb5f610d61565b90505f5b81811015610fb7575f610ed28183610d6a565b604051633e822efb60e11b815260ff871660048201529091506001600160a01b03821690637d045df690602401602060405180830381865afa158015610f1a573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f3e9190611c1c565b15610fae57604051637f4ab1dd60e01b815260ff861660048201526001600160a01b03821690637f4ab1dd906024015f60405180830381865afa158015610f87573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261094e9190810190611c4b565b50600101610ebf565b505060408051808201909152601881527f556e6b6e6f776e207265737472696374696f6e20636f64650000000000000000602082015292915050565b6040517fdbf61473843cd9be1c9791ce51ef66d0da6c9026d62ba80c1ca433b13fb729b2905f90a16106e95f611569565b61102d81611572565b6110375f8261141b565b6110545760405163cc790a4b60e01b815260040160405180910390fd5b6040516001600160a01b038216907f60305ce6c9104acd0969d358f926bf391174340660aaf5e6215261fd6847bf46905f90a250565b5f5f6110955f610d61565b90505f5b8181101561114b575f6110ac8183610d6a565b60405163d32c7bb560e01b81526001600160a01b038a811660048301528981166024830152888116604483015260648201889052919091169063d32c7bb590608401602060405180830381865afa158015611109573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061112d9190611cfe565b905060ff811615611142579250610700915050565b50600101611099565b505f9695505050505050565b5f5f6111625f610d61565b90505f5b81811015611210575f6111798183610d6a565b60405163d4ce141560e01b81526001600160a01b038981166004830152888116602483015260448201889052919091169063d4ce141590606401602060405180830381865afa1580156111ce573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111f29190611cfe565b905060ff811615611207579250610966915050565b50600101611166565b505f95945050505050565b6112255f826115ca565b61124257604051632cdc3a4160e21b815260040160405180910390fd5b6040516001600160a01b038216907f6d83315c9718799346b67584ec64301b1457e989c8e35a8e2982a7776c04bfc4905f90a250565b611280610d75565b600780546001600160a01b0383166001600160a01b031990911681179091556112b16006546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b5f6001600160e01b031982166320c49ce760e01b148061131957506001600160e01b0319821663157094b960e31b145b8061133457506001600160e01b031982166378a8de7d60e01b145b8061134f57506001600160e01b03198216630c51264760e21b145b8061136a57506001600160e01b03198216633235d15f60e11b145b806105a557506001600160e01b03198216637157797f60e01b1492915050565b611393816115de565b336001600160a01b038216148015906113c357506001600160a01b0381165f9081526005602052604090205460ff165b1561064757610647815f610a76565b336001600160a01b03821614801561140157506001600160a01b0381165f9081526005602052604090205460ff165b156114095750565b610647610a65565b610dfe5f82610ca8565b5f610966836001600160a01b03841661163f565b6060815f0180548060200260200160405190810160405280929190818152602001828054801561147c57602002820191905f5260205f20905b815481526020019060010190808311611468575b50505050509050919050565b5f825f01828154811061149d5761149d611bb0565b905f5260205f200154905092915050565b600680546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b5f36601480821080159061153b57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031633145b156115615761154e36828403815f611d19565b61155791611d40565b60601c9250505090565b339250505090565b6106478161168b565b61157b816116e4565b611586600382610ca8565b156115a4576040516302925f7360e11b815260040160405180910390fd5b6115ad8161170b565b61064757604051639952e34360e01b815260040160405180910390fd5b5f610966836001600160a01b038416611748565b6115e96003826115ca565b61160657604051633477dd1760e01b815260040160405180910390fd5b6040516001600160a01b03821681527f28a4ca7134a3b3f9aff286e79ad3daadb4a06d1b43d037a3a98bdc074edd9b7a90602001610b2d565b5f81815260018301602052604081205461168457508154600181810184555f8481526020808220909301849055845484825282860190935260409020919091556105a5565b505f6105a5565b5f611694825490565b90505f5b818110156116dd57826001015f845f0183815481106116b9576116b9611bb0565b905f5260205f20015481526020019081526020015f205f9055806001019050611698565b50505f9055565b6001600160a01b0381166106475760405163f9d152fb60e01b815260040160405180910390fd5b5f61171582611832565b61172057505f919050565b611731826358d34ba960e11b611871565b806105a557506105a582632497d6cb60e01b611871565b5f8181526001830160205260408120548015611822575f61176a600183611d80565b85549091505f9061177d90600190611d80565b90508082146117dc575f865f01828154811061179b5761179b611bb0565b905f5260205f200154905080875f0184815481106117bb576117bb611bb0565b5f918252602080832090910192909255918252600188019052604090208390555b85548690806117ed576117ed611d9f565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f9055600193505050506105a5565b5f9150506105a5565b5092915050565b5f611844826301ffc9a760e01b611871565b15610988575f8061185d846001600160e01b0319611892565b915091508180156107005750159392505050565b5f5f5f61187e8585611892565b9150915081801561094e5750949350505050565b6301ffc9a760e01b5f818152600483905290819060208260248188617530fa92505f511515601f3d11169150509250929050565b5f602082840312156118d6575f5ffd5b81356001600160e01b031981168114610966575f5ffd5b5f5f83601f8401126118fd575f5ffd5b50813567ffffffffffffffff811115611914575f5ffd5b6020830191508360208260051b850101111561192e575f5ffd5b9250929050565b5f5f60208385031215611946575f5ffd5b823567ffffffffffffffff81111561195c575f5ffd5b611968858286016118ed565b90969095509350505050565b6001600160a01b0381168114610647575f5ffd5b8015158114610647575f5ffd5b5f5f604083850312156119a6575f5ffd5b82356119b181611974565b915060208301356119c181611988565b809150509250929050565b5f602082840312156119dc575f5ffd5b5035919050565b5f5f5f5f608085870312156119f6575f5ffd5b8435611a0181611974565b93506020850135611a1181611974565b92506040850135611a2181611974565b9396929550929360600135925050565b5f60208284031215611a41575f5ffd5b813561096681611974565b602080825282518282018190525f918401906040840190835b81811015611a8c5783516001600160a01b0316835260209384019390920191600101611a65565b509095945050505050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b5f5f60408385031215611add575f5ffd5b8235611ae881611974565b946020939093013593505050565b60ff81168114610647575f5ffd5b5f60208284031215611b14575f5ffd5b813561096681611af6565b5f5f5f60608486031215611b31575f5ffd5b8335611b3c81611974565b92506020840135611b4c81611974565b929592945050506040919091013590565b5f5f5f60408486031215611b6f575f5ffd5b833567ffffffffffffffff811115611b85575f5ffd5b611b91868287016118ed565b9094509250506020840135611ba581611988565b809150509250925092565b634e487b7160e01b5f52603260045260245ffd5b604080825281018390525f8460608301825b86811015611c06578235611be981611974565b6001600160a01b0316825260209283019290910190600101611bd6565b5080925050508215156020830152949350505050565b5f60208284031215611c2c575f5ffd5b815161096681611988565b634e487b7160e01b5f52604160045260245ffd5b5f60208284031215611c5b575f5ffd5b815167ffffffffffffffff811115611c71575f5ffd5b8201601f81018413611c81575f5ffd5b805167ffffffffffffffff811115611c9b57611c9b611c37565b604051601f8201601f19908116603f0116810167ffffffffffffffff81118282101715611cca57611cca611c37565b604052818152828201602001861015611ce1575f5ffd5b8160208401602083015e5f91810160200191909152949350505050565b5f60208284031215611d0e575f5ffd5b815161096681611af6565b5f5f85851115611d27575f5ffd5b83861115611d33575f5ffd5b5050820193919092039150565b80356bffffffffffffffffffffffff19811690601484101561182b576bffffffffffffffffffffffff1960149490940360031b84901b1690921692915050565b818103818111156105a557634e487b7160e01b5f52601160045260245ffd5b634e487b7160e01b5f52603160045260245ffdfea2646970667358221220cf7f43426bd1dea199a8e9edd8c15a10196851fbf5e1bbf35f135975b6078e4464736f6c63430008250033", + "deployedBytecode": "0x608060405234801561000f575f5ffd5b5060043610610234575f3560e01c80638baf29b411610135578063d4ce1415116100b4578063e3c4602c11610079578063e3c4602c14610538578063e46638e61461054b578063e54621d21461055e578063f2fde38b14610566578063f76bf55014610579575f5ffd5b8063d4ce1415146104c3578063db18af6c146104d6578063db75d017146104e9578063df21950f14610514578063e30c397814610527575f5ffd5b8063b27aef3a116100fa578063b27aef3a1461045d578063bb4b612114610470578063bc13eacc14610483578063c7c24b181461048b578063d32c7bb51461049e575f5ffd5b80638baf29b41461040b5780638d2ea7721461041e5780638da5cb5b14610431578063993e8b9514610442578063b043572e14610455575f5ffd5b806354fd4d50116101c1578063715018a611610186578063715018a6146103af5780637157797f146103b757806379ba5097146103ca5780637da0a877146103d25780637f4ab1dd146103f8575f5ffd5b806354fd4d50146102fc578063572b6c051461032a5780635f8dead31461036a5780636a3edf281461037d5780636ae728c61461039d575f5ffd5b80633e5af4ca116102075780633e5af4ca1461029b5780633ff5aa02146102ae57806340db3b50146102c157806352f6747a146102d457806354e4b945146102e9575f5ffd5b806301ffc9a7146102385780631455d0e7146102605780633284a9a5146102755780633a56d6d514610288575b5f5ffd5b61024b6102463660046118c6565b610581565b60405190151581526020015b60405180910390f35b61027361026e366004611935565b6105ab565b005b610273610283366004611995565b6105f9565b6102736102963660046119cc565b610636565b6102736102a93660046119e3565b61064a565b6102736102bc366004611a31565b610664565b6102736102cf366004611a31565b610676565b6102dc610688565b6040516102579190611a4c565b61024b6102f7366004611a31565b610698565b604080518082019091526009815268332e302e302d72633760b81b60208201525b6040516102579190611a97565b61024b610338366004611a31565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b0390811691161490565b610273610378366004611acc565b6106a3565b6103856106b6565b6040516001600160a01b039091168152602001610257565b6002545b604051908152602001610257565b6102736106d8565b61024b6103c53660046119e3565b6106eb565b610273610708565b7f0000000000000000000000000000000000000000000000000000000000000000610385565b61031d610406366004611b04565b610720565b610273610419366004611b1f565b61072b565b61027361042c366004611acc565b61073e565b6006546001600160a01b0316610385565b61024b610450366004611a31565b610751565b61027361075d565b61027361046b366004611935565b61076d565b61027361047e366004611b5d565b610820565b6103a16108ee565b610273610499366004611935565b6108f8565b6104b16104ac3660046119e3565b610941565b60405160ff9091168152602001610257565b6104b16104d1366004611b1f565b610957565b6103856104e43660046119cc565b61096d565b61024b6104f7366004611a31565b6001600160a01b03165f9081526005602052604090205460ff1690565b610273610522366004611a31565b61098f565b6007546001600160a01b0316610385565b610273610546366004611a31565b6109a0565b61024b610559366004611b1f565b6109e2565b6102dc6109fb565b610273610574366004611a31565b610a07565b6103a1600a81565b5f6001600160e01b03198216639ab669ef60e01b14806105a557506105a582610a21565b92915050565b6105b3610a65565b5f5b818110156105f4576105ec8383838181106105d2576105d2611bb0565b90506020020160208101906105e79190611a31565b610a6d565b6001016105b5565b505050565b610601610a65565b6001600160a01b0382166106285760405163135217db60e21b815260040160405180910390fd5b6106328282610a76565b5050565b61063e610ad4565b61064781610adc565b50565b610652610b38565b61065e84848484610b60565b50505050565b61066d81610c02565b61064781610c0b565b61067f81610c02565b61064781610a6d565b60606106935f610c9c565b905090565b5f6105a58183610ca8565b6106ab610b38565b6106325f8383610cc8565b5f5f6106c26003610d61565b11156106d35761069360035f610d6a565b505f90565b6106e0610d75565b6106e95f610dd3565b565b5f806106f986868686610941565b60ff161490505b949350505050565b610718610713610dec565b610df5565b6106e9610e1c565b60606105a582610e7e565b610733610b38565b6105f4838383610cc8565b610746610b38565b610632825f83610cc8565b5f6105a5600383610ca8565b610765610ad4565b6106e9610ff3565b610775610ad4565b5f819003610796576040516359203cb960e01b815260040160405180910390fd5b600254808211156107c657604051630befc49d60e01b81526004016107bd91815260200190565b60405180910390fd5b505f6107d15f610d61565b11156107df576107df610ff3565b5f5b818110156105f4576108188383838181106107fe576107fe611bb0565b90506020020160208101906108139190611a31565b611024565b6001016107e1565b610828610a65565b5f5b828110156108ad575f84848381811061084557610845611bb0565b905060200201602081019061085a9190611a31565b90506001600160a01b0381166108835760405163135217db60e21b815260040160405180910390fd5b6001600160a01b03165f908152600560205260409020805460ff191683151517905560010161082a565b507f430881f04f203566ee9b32d6444cf02e1b2a0f17ab6b4263a1ee2074d3d0f4838383836040516108e193929190611bc4565b60405180910390a1505050565b5f6106935f610d61565b610900610a65565b5f5b818110156105f45761093983838381811061091f5761091f611bb0565b90506020020160208101906109349190611a31565b610c0b565b600101610902565b5f61094e8585858561108a565b95945050505050565b5f610963848484611157565b90505b9392505050565b5f6109775f610d61565b821015610988576105a55f83610d6a565b505f919050565b610997610ad4565b6106478161121b565b6109a8610ad4565b600254806109b55f610d61565b1081906109d857604051630befc49d60e01b81526004016107bd91815260200190565b5061063282611024565b5f806109ef858585610957565b60ff1614949350505050565b60606106936003610c9c565b610a0f610d75565b610a1881610df5565b61064781611278565b5f610a2b826112e9565b80610a4657506001600160e01b031982166307f5828d60e41b145b806105a557506301ffc9a760e01b6001600160e01b03198316146105a5565b6106e9610ad4565b6106478161138a565b6001600160a01b0382165f81815260056020908152604091829020805460ff191685151590811790915591519182527f407b412a9b6db334d48445ec9bcad46fb50bc4b2e97f73e963e397101957a729910160405180910390a25050565b6106e9610d75565b805f03610afc57604051631e69e71760e21b815260040160405180910390fd5b60028190556040518181527f2292ad4720fff63e2bd104c6b1c0d72c2c729a6001c8ab4bb947cbcc51109863906020015b60405180910390a150565b610b43600333610ca8565b6106e957604051630599c0e960e01b815260040160405180910390fd5b5f610b6a5f610d61565b90505f5b81811015610bfa57610b805f82610d6a565b604051631f2d7a6560e11b81526001600160a01b03888116600483015287811660248301528681166044830152606482018690529190911690633e5af4ca906084015f604051808303815f87803b158015610bd9575f5ffd5b505af1158015610beb573d5f5f3e3d5ffd5b50505050806001019050610b6e565b505050505050565b610647816113d2565b6001600160a01b038116610c325760405163135217db60e21b815260040160405180910390fd5b610c3b81611411565b610c4660038261141b565b610c63576040516371b3c56560e11b815260040160405180910390fd5b6040516001600160a01b03821681527f2de35142b19ed5a07796cf30791959c592018f70b1d2d7c460eef8ffe713692b90602001610b2d565b60605f6109668361142f565b6001600160a01b03165f9081526001919091016020526040902054151590565b5f610cd25f610d61565b90505f5b81811015610d5a57610ce85f82610d6a565b6040516322ebca6d60e21b81526001600160a01b0387811660048301528681166024830152604482018690529190911690638baf29b4906064015f604051808303815f87803b158015610d39575f5ffd5b505af1158015610d4b573d5f5f3e3d5ffd5b50505050806001019050610cd6565b5050505050565b5f6105a5825490565b5f6109668383611488565b610d7d610dec565b6001600160a01b0316610d986006546001600160a01b031690565b6001600160a01b0316146106e957610dae610dec565b60405163118cdaa760e01b81526001600160a01b0390911660048201526024016107bd565b600780546001600160a01b0319169055610647816114ae565b5f6106936114ff565b610dfe81610698565b15610647576040516302925f7360e11b815260040160405180910390fd5b5f610e25610dec565b9050806001600160a01b0316610e436007546001600160a01b031690565b6001600160a01b031614610e755760405163118cdaa760e01b81526001600160a01b03821660048201526024016107bd565b61064781610dd3565b606060ff8216610eb157505060408051808201909152600d81526c2737a932b9ba3934b1ba34b7b760991b602082015290565b5f610ebb5f610d61565b90505f5b81811015610fb7575f610ed28183610d6a565b604051633e822efb60e11b815260ff871660048201529091506001600160a01b03821690637d045df690602401602060405180830381865afa158015610f1a573d5f5f3e3d5ffd5b505050506040513d601f19601f82011682018060405250810190610f3e9190611c1c565b15610fae57604051637f4ab1dd60e01b815260ff861660048201526001600160a01b03821690637f4ab1dd906024015f60405180830381865afa158015610f87573d5f5f3e3d5ffd5b505050506040513d5f823e601f3d908101601f1916820160405261094e9190810190611c4b565b50600101610ebf565b505060408051808201909152601881527f556e6b6e6f776e207265737472696374696f6e20636f64650000000000000000602082015292915050565b6040517fdbf61473843cd9be1c9791ce51ef66d0da6c9026d62ba80c1ca433b13fb729b2905f90a16106e95f611569565b61102d81611572565b6110375f8261141b565b6110545760405163cc790a4b60e01b815260040160405180910390fd5b6040516001600160a01b038216907f60305ce6c9104acd0969d358f926bf391174340660aaf5e6215261fd6847bf46905f90a250565b5f5f6110955f610d61565b90505f5b8181101561114b575f6110ac8183610d6a565b60405163d32c7bb560e01b81526001600160a01b038a811660048301528981166024830152888116604483015260648201889052919091169063d32c7bb590608401602060405180830381865afa158015611109573d5f5f3e3d5ffd5b505050506040513d601f19601f8201168201806040525081019061112d9190611cfe565b905060ff811615611142579250610700915050565b50600101611099565b505f9695505050505050565b5f5f6111625f610d61565b90505f5b81811015611210575f6111798183610d6a565b60405163d4ce141560e01b81526001600160a01b038981166004830152888116602483015260448201889052919091169063d4ce141590606401602060405180830381865afa1580156111ce573d5f5f3e3d5ffd5b505050506040513d601f19601f820116820180604052508101906111f29190611cfe565b905060ff811615611207579250610966915050565b50600101611166565b505f95945050505050565b6112255f826115ca565b61124257604051632cdc3a4160e21b815260040160405180910390fd5b6040516001600160a01b038216907f6d83315c9718799346b67584ec64301b1457e989c8e35a8e2982a7776c04bfc4905f90a250565b611280610d75565b600780546001600160a01b0383166001600160a01b031990911681179091556112b16006546001600160a01b031690565b6001600160a01b03167f38d16b8cac22d99fc7c124b9cd0de2d3fa1faef420bfe791d8c362d765e2270060405160405180910390a350565b5f6001600160e01b031982166320c49ce760e01b148061131957506001600160e01b0319821663157094b960e31b145b8061133457506001600160e01b031982166378a8de7d60e01b145b8061134f57506001600160e01b03198216630c51264760e21b145b8061136a57506001600160e01b03198216633235d15f60e11b145b806105a557506001600160e01b03198216637157797f60e01b1492915050565b611393816115de565b336001600160a01b038216148015906113c357506001600160a01b0381165f9081526005602052604090205460ff165b1561064757610647815f610a76565b336001600160a01b03821614801561140157506001600160a01b0381165f9081526005602052604090205460ff165b156114095750565b610647610a65565b610dfe5f82610ca8565b5f610966836001600160a01b03841661163f565b6060815f0180548060200260200160405190810160405280929190818152602001828054801561147c57602002820191905f5260205f20905b815481526020019060010190808311611468575b50505050509050919050565b5f825f01828154811061149d5761149d611bb0565b905f5260205f200154905092915050565b600680546001600160a01b038381166001600160a01b0319831681179093556040519116919082907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0905f90a35050565b5f36601480821080159061153b57507f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031633145b156115615761154e36828403815f611d19565b61155791611d40565b60601c9250505090565b339250505090565b6106478161168b565b61157b816116e4565b611586600382610ca8565b156115a4576040516302925f7360e11b815260040160405180910390fd5b6115ad8161170b565b61064757604051639952e34360e01b815260040160405180910390fd5b5f610966836001600160a01b038416611748565b6115e96003826115ca565b61160657604051633477dd1760e01b815260040160405180910390fd5b6040516001600160a01b03821681527f28a4ca7134a3b3f9aff286e79ad3daadb4a06d1b43d037a3a98bdc074edd9b7a90602001610b2d565b5f81815260018301602052604081205461168457508154600181810184555f8481526020808220909301849055845484825282860190935260409020919091556105a5565b505f6105a5565b5f611694825490565b90505f5b818110156116dd57826001015f845f0183815481106116b9576116b9611bb0565b905f5260205f20015481526020019081526020015f205f9055806001019050611698565b50505f9055565b6001600160a01b0381166106475760405163f9d152fb60e01b815260040160405180910390fd5b5f61171582611832565b61172057505f919050565b611731826358d34ba960e11b611871565b806105a557506105a582632497d6cb60e01b611871565b5f8181526001830160205260408120548015611822575f61176a600183611d80565b85549091505f9061177d90600190611d80565b90508082146117dc575f865f01828154811061179b5761179b611bb0565b905f5260205f200154905080875f0184815481106117bb576117bb611bb0565b5f918252602080832090910192909255918252600188019052604090208390555b85548690806117ed576117ed611d9f565b600190038181905f5260205f20015f90559055856001015f8681526020019081526020015f205f9055600193505050506105a5565b5f9150506105a5565b5092915050565b5f611844826301ffc9a760e01b611871565b15610988575f8061185d846001600160e01b0319611892565b915091508180156107005750159392505050565b5f5f5f61187e8585611892565b9150915081801561094e5750949350505050565b6301ffc9a760e01b5f818152600483905290819060208260248188617530fa92505f511515601f3d11169150509250929050565b5f602082840312156118d6575f5ffd5b81356001600160e01b031981168114610966575f5ffd5b5f5f83601f8401126118fd575f5ffd5b50813567ffffffffffffffff811115611914575f5ffd5b6020830191508360208260051b850101111561192e575f5ffd5b9250929050565b5f5f60208385031215611946575f5ffd5b823567ffffffffffffffff81111561195c575f5ffd5b611968858286016118ed565b90969095509350505050565b6001600160a01b0381168114610647575f5ffd5b8015158114610647575f5ffd5b5f5f604083850312156119a6575f5ffd5b82356119b181611974565b915060208301356119c181611988565b809150509250929050565b5f602082840312156119dc575f5ffd5b5035919050565b5f5f5f5f608085870312156119f6575f5ffd5b8435611a0181611974565b93506020850135611a1181611974565b92506040850135611a2181611974565b9396929550929360600135925050565b5f60208284031215611a41575f5ffd5b813561096681611974565b602080825282518282018190525f918401906040840190835b81811015611a8c5783516001600160a01b0316835260209384019390920191600101611a65565b509095945050505050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b5f5f60408385031215611add575f5ffd5b8235611ae881611974565b946020939093013593505050565b60ff81168114610647575f5ffd5b5f60208284031215611b14575f5ffd5b813561096681611af6565b5f5f5f60608486031215611b31575f5ffd5b8335611b3c81611974565b92506020840135611b4c81611974565b929592945050506040919091013590565b5f5f5f60408486031215611b6f575f5ffd5b833567ffffffffffffffff811115611b85575f5ffd5b611b91868287016118ed565b9094509250506020840135611ba581611988565b809150509250925092565b634e487b7160e01b5f52603260045260245ffd5b604080825281018390525f8460608301825b86811015611c06578235611be981611974565b6001600160a01b0316825260209283019290910190600101611bd6565b5080925050508215156020830152949350505050565b5f60208284031215611c2c575f5ffd5b815161096681611988565b634e487b7160e01b5f52604160045260245ffd5b5f60208284031215611c5b575f5ffd5b815167ffffffffffffffff811115611c71575f5ffd5b8201601f81018413611c81575f5ffd5b805167ffffffffffffffff811115611c9b57611c9b611c37565b604051601f8201601f19908116603f0116810167ffffffffffffffff81118282101715611cca57611cca611c37565b604052818152828201602001861015611ce1575f5ffd5b8160208401602083015e5f91810160200191909152949350505050565b5f60208284031215611d0e575f5ffd5b815161096681611af6565b5f5f85851115611d27575f5ffd5b83861115611d33575f5ffd5b5050820193919092039150565b80356bffffffffffffffffffffffff19811690601484101561182b576bffffffffffffffffffffffff1960149490940360031b84901b1690921692915050565b818103818111156105a557634e487b7160e01b5f52601160045260245ffd5b634e487b7160e01b5f52603160045260245ffdfea2646970667358221220cf7f43426bd1dea199a8e9edd8c15a10196851fbf5e1bbf35f135975b6078e4464736f6c63430008250033", + "linkReferences": {}, + "deployedLinkReferences": {} +} diff --git a/doc/other/CMTAT/checkTransferred.png b/doc/other/CMTAT/checkTransferred.png deleted file mode 100644 index 317ff560..00000000 Binary files a/doc/other/CMTAT/checkTransferred.png and /dev/null differ diff --git a/doc/other/CMTAT/transferred.png b/doc/other/CMTAT/transferred.png deleted file mode 100644 index f378b430..00000000 Binary files a/doc/other/CMTAT/transferred.png and /dev/null differ diff --git a/doc/schema/cmtat_surya_inheritance_IRuleEngine.sol.png b/doc/schema/cmtat_surya_inheritance_IRuleEngine.sol.png deleted file mode 100644 index f7119f41..00000000 Binary files a/doc/schema/cmtat_surya_inheritance_IRuleEngine.sol.png and /dev/null differ diff --git a/doc/schema/sol2uml/ERC3643ComplianceExtendedModuleUML.png b/doc/schema/sol2uml/ERC3643ComplianceExtendedModuleUML.png index cf0332fe..32f3f128 100644 Binary files a/doc/schema/sol2uml/ERC3643ComplianceExtendedModuleUML.png and b/doc/schema/sol2uml/ERC3643ComplianceExtendedModuleUML.png differ diff --git a/doc/schema/sol2uml/ERC3643ComplianceModuleUML.png b/doc/schema/sol2uml/ERC3643ComplianceModuleUML.png index 011ebf5c..779c48eb 100644 Binary files a/doc/schema/sol2uml/ERC3643ComplianceModuleUML.png and b/doc/schema/sol2uml/ERC3643ComplianceModuleUML.png differ diff --git a/doc/schema/sol2uml/IERC1404ExtendUML.png b/doc/schema/sol2uml/IERC1404ExtendUML.png index 54e9045d..a510dfc8 100644 Binary files a/doc/schema/sol2uml/IERC1404ExtendUML.png and b/doc/schema/sol2uml/IERC1404ExtendUML.png differ diff --git a/doc/schema/sol2uml/IERC1404UML.png b/doc/schema/sol2uml/IERC1404UML.png index 9f089d80..256e4d55 100644 Binary files a/doc/schema/sol2uml/IERC1404UML.png and b/doc/schema/sol2uml/IERC1404UML.png differ diff --git a/doc/schema/sol2uml/IERC3643ComplianceReadUML.png b/doc/schema/sol2uml/IERC3643ComplianceReadUML.png index 04549802..558441ed 100644 Binary files a/doc/schema/sol2uml/IERC3643ComplianceReadUML.png and b/doc/schema/sol2uml/IERC3643ComplianceReadUML.png differ diff --git a/doc/schema/sol2uml/IERC3643IComplianceContractUML.png b/doc/schema/sol2uml/IERC3643IComplianceContractUML.png index 0acb7637..fd59b619 100644 Binary files a/doc/schema/sol2uml/IERC3643IComplianceContractUML.png and b/doc/schema/sol2uml/IERC3643IComplianceContractUML.png differ diff --git a/doc/schema/sol2uml/IERC7551ComplianceUML.png b/doc/schema/sol2uml/IERC7551ComplianceUML.png index 4f82a456..25c31077 100644 Binary files a/doc/schema/sol2uml/IERC7551ComplianceUML.png and b/doc/schema/sol2uml/IERC7551ComplianceUML.png differ diff --git a/doc/schema/sol2uml/IRuleEngineUML.png b/doc/schema/sol2uml/IRuleEngineUML.png index 756ffe6b..3488468f 100644 Binary files a/doc/schema/sol2uml/IRuleEngineUML.png and b/doc/schema/sol2uml/IRuleEngineUML.png differ diff --git a/doc/schema/sol2uml/IRuleUML.png b/doc/schema/sol2uml/IRuleUML.png new file mode 100644 index 00000000..08c6e934 Binary files /dev/null and b/doc/schema/sol2uml/IRuleUML.png differ diff --git a/doc/schema/sol2uml/RuleEngine2771UML.png b/doc/schema/sol2uml/RuleEngine2771UML.png new file mode 100644 index 00000000..d65215bc Binary files /dev/null and b/doc/schema/sol2uml/RuleEngine2771UML.png differ diff --git a/doc/schema/sol2uml/RuleEngineBaseUML.png b/doc/schema/sol2uml/RuleEngineBaseUML.png index d90b8bfd..88e7aa5d 100644 Binary files a/doc/schema/sol2uml/RuleEngineBaseUML.png and b/doc/schema/sol2uml/RuleEngineBaseUML.png differ diff --git a/doc/schema/sol2uml/RuleEngineOwnable2771UML.png b/doc/schema/sol2uml/RuleEngineOwnable2771UML.png new file mode 100644 index 00000000..1ebea927 Binary files /dev/null and b/doc/schema/sol2uml/RuleEngineOwnable2771UML.png differ diff --git a/doc/schema/sol2uml/RuleEngineOwnable2Step2771UML.png b/doc/schema/sol2uml/RuleEngineOwnable2Step2771UML.png new file mode 100644 index 00000000..187353d0 Binary files /dev/null and b/doc/schema/sol2uml/RuleEngineOwnable2Step2771UML.png differ diff --git a/doc/schema/sol2uml/RuleEngineOwnable2StepUML.png b/doc/schema/sol2uml/RuleEngineOwnable2StepUML.png index 21094aa6..218e634c 100644 Binary files a/doc/schema/sol2uml/RuleEngineOwnable2StepUML.png and b/doc/schema/sol2uml/RuleEngineOwnable2StepUML.png differ diff --git a/doc/schema/sol2uml/RuleEngineOwnableUML.png b/doc/schema/sol2uml/RuleEngineOwnableUML.png index c7edef08..06869ebc 100644 Binary files a/doc/schema/sol2uml/RuleEngineOwnableUML.png and b/doc/schema/sol2uml/RuleEngineOwnableUML.png differ diff --git a/doc/schema/sol2uml/RuleEngineUML.png b/doc/schema/sol2uml/RuleEngineUML.png index 79c497ef..8474cc78 100644 Binary files a/doc/schema/sol2uml/RuleEngineUML.png and b/doc/schema/sol2uml/RuleEngineUML.png differ diff --git a/doc/schema/sol2uml/RuleManagementModuleUML.png b/doc/schema/sol2uml/RuleManagementModuleUML.png index 1366bcdd..b28a3e97 100644 Binary files a/doc/schema/sol2uml/RuleManagementModuleUML.png and b/doc/schema/sol2uml/RuleManagementModuleUML.png differ diff --git a/doc/schema/sol2uml/TokenBindingExtendedModuleUML.png b/doc/schema/sol2uml/TokenBindingExtendedModuleUML.png index f276bd1d..68784958 100644 Binary files a/doc/schema/sol2uml/TokenBindingExtendedModuleUML.png and b/doc/schema/sol2uml/TokenBindingExtendedModuleUML.png differ diff --git a/doc/schema/sol2uml/TokenBindingModuleUML.png b/doc/schema/sol2uml/TokenBindingModuleUML.png index a90404c3..03a48530 100644 Binary files a/doc/schema/sol2uml/TokenBindingModuleUML.png and b/doc/schema/sol2uml/TokenBindingModuleUML.png differ diff --git a/doc/schema/sol2uml/VersionModuleUML.png b/doc/schema/sol2uml/VersionModuleUML.png index 295e778d..71001c8a 100644 Binary files a/doc/schema/sol2uml/VersionModuleUML.png and b/doc/schema/sol2uml/VersionModuleUML.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_ComplianceInterfaceId.sol.png b/doc/schema/surya/surya_graph/surya_graph_ComplianceInterfaceId.sol.png index 5b4fa6b1..c3d7cada 100644 Binary files a/doc/schema/surya/surya_graph/surya_graph_ComplianceInterfaceId.sol.png and b/doc/schema/surya/surya_graph/surya_graph_ComplianceInterfaceId.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_ERC1404InterfaceId.sol.png b/doc/schema/surya/surya_graph/surya_graph_ERC1404InterfaceId.sol.png index 5b4fa6b1..c3d7cada 100644 Binary files a/doc/schema/surya/surya_graph/surya_graph_ERC1404InterfaceId.sol.png and b/doc/schema/surya/surya_graph/surya_graph_ERC1404InterfaceId.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_ERC2771ModuleStandalone.sol.png b/doc/schema/surya/surya_graph/surya_graph_ERC2771ModuleStandalone.sol.png index 68940d42..e5d917ee 100644 Binary files a/doc/schema/surya/surya_graph/surya_graph_ERC2771ModuleStandalone.sol.png and b/doc/schema/surya/surya_graph/surya_graph_ERC2771ModuleStandalone.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_ERC3643ComplianceExtendedModule.sol.png b/doc/schema/surya/surya_graph/surya_graph_ERC3643ComplianceExtendedModule.sol.png index 5258af7b..6a25bee2 100644 Binary files a/doc/schema/surya/surya_graph/surya_graph_ERC3643ComplianceExtendedModule.sol.png and b/doc/schema/surya/surya_graph/surya_graph_ERC3643ComplianceExtendedModule.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_ERC3643ComplianceModule.sol.png b/doc/schema/surya/surya_graph/surya_graph_ERC3643ComplianceModule.sol.png index 44712fed..5a582144 100644 Binary files a/doc/schema/surya/surya_graph/surya_graph_ERC3643ComplianceModule.sol.png and b/doc/schema/surya/surya_graph/surya_graph_ERC3643ComplianceModule.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_ERC3643ComplianceRolesStorage.sol.png b/doc/schema/surya/surya_graph/surya_graph_ERC3643ComplianceRolesStorage.sol.png index 5b4fa6b1..c3d7cada 100644 Binary files a/doc/schema/surya/surya_graph/surya_graph_ERC3643ComplianceRolesStorage.sol.png and b/doc/schema/surya/surya_graph/surya_graph_ERC3643ComplianceRolesStorage.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_ERC3643TokenMock.sol.png b/doc/schema/surya/surya_graph/surya_graph_ERC3643TokenMock.sol.png index 2631d6a3..4d0ef2ba 100644 Binary files a/doc/schema/surya/surya_graph/surya_graph_ERC3643TokenMock.sol.png and b/doc/schema/surya/surya_graph/surya_graph_ERC3643TokenMock.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_ICompliance.sol.png b/doc/schema/surya/surya_graph/surya_graph_ICompliance.sol.png index aebb90e7..57d5ed6a 100644 Binary files a/doc/schema/surya/surya_graph/surya_graph_ICompliance.sol.png and b/doc/schema/surya/surya_graph/surya_graph_ICompliance.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_IERC1404Subset.sol.png b/doc/schema/surya/surya_graph/surya_graph_IERC1404Subset.sol.png index 41787531..16074559 100644 Binary files a/doc/schema/surya/surya_graph/surya_graph_IERC1404Subset.sol.png and b/doc/schema/surya/surya_graph/surya_graph_IERC1404Subset.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_IERC173Subset.sol.png b/doc/schema/surya/surya_graph/surya_graph_IERC173Subset.sol.png index 71c5b6c0..86613de6 100644 Binary files a/doc/schema/surya/surya_graph/surya_graph_IERC173Subset.sol.png and b/doc/schema/surya/surya_graph/surya_graph_IERC173Subset.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_IERC3643Compliance.sol.png b/doc/schema/surya/surya_graph/surya_graph_IERC3643Compliance.sol.png index 2a4a86de..d26c17ce 100644 Binary files a/doc/schema/surya/surya_graph/surya_graph_IERC3643Compliance.sol.png and b/doc/schema/surya/surya_graph/surya_graph_IERC3643Compliance.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_IERC3643ComplianceExtended.sol.png b/doc/schema/surya/surya_graph/surya_graph_IERC3643ComplianceExtended.sol.png index 5b4fa6b1..c3d7cada 100644 Binary files a/doc/schema/surya/surya_graph/surya_graph_IERC3643ComplianceExtended.sol.png and b/doc/schema/surya/surya_graph/surya_graph_IERC3643ComplianceExtended.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_IERC3643ComplianceExtendedSubset.sol.png b/doc/schema/surya/surya_graph/surya_graph_IERC3643ComplianceExtendedSubset.sol.png index bfb9162b..9439f2df 100644 Binary files a/doc/schema/surya/surya_graph/surya_graph_IERC3643ComplianceExtendedSubset.sol.png and b/doc/schema/surya/surya_graph/surya_graph_IERC3643ComplianceExtendedSubset.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_IERC7551ComplianceSubset.sol.png b/doc/schema/surya/surya_graph/surya_graph_IERC7551ComplianceSubset.sol.png index 3abc5c3b..fde359bf 100644 Binary files a/doc/schema/surya/surya_graph/surya_graph_IERC7551ComplianceSubset.sol.png and b/doc/schema/surya/surya_graph/surya_graph_IERC7551ComplianceSubset.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_IOwnable2StepSubset.sol.png b/doc/schema/surya/surya_graph/surya_graph_IOwnable2StepSubset.sol.png index c5350c57..f0c2bc6f 100644 Binary files a/doc/schema/surya/surya_graph/surya_graph_IOwnable2StepSubset.sol.png and b/doc/schema/surya/surya_graph/surya_graph_IOwnable2StepSubset.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_IRule.sol.png b/doc/schema/surya/surya_graph/surya_graph_IRule.sol.png index 4a57a550..6b668f00 100644 Binary files a/doc/schema/surya/surya_graph/surya_graph_IRule.sol.png and b/doc/schema/surya/surya_graph/surya_graph_IRule.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_IRuleInterfaceIdHelper.sol.png b/doc/schema/surya/surya_graph/surya_graph_IRuleInterfaceIdHelper.sol.png index 8f4d7621..d53a9878 100644 Binary files a/doc/schema/surya/surya_graph/surya_graph_IRuleInterfaceIdHelper.sol.png and b/doc/schema/surya/surya_graph/surya_graph_IRuleInterfaceIdHelper.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_IRulesManagementModule.sol.png b/doc/schema/surya/surya_graph/surya_graph_IRulesManagementModule.sol.png index 7f629fa4..96d07dfe 100644 Binary files a/doc/schema/surya/surya_graph/surya_graph_IRulesManagementModule.sol.png and b/doc/schema/surya/surya_graph/surya_graph_IRulesManagementModule.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_ITokenBinding.sol.png b/doc/schema/surya/surya_graph/surya_graph_ITokenBinding.sol.png index 00d1b1fd..0eefac30 100644 Binary files a/doc/schema/surya/surya_graph/surya_graph_ITokenBinding.sol.png and b/doc/schema/surya/surya_graph/surya_graph_ITokenBinding.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_ITokenBindingExtended.sol.png b/doc/schema/surya/surya_graph/surya_graph_ITokenBindingExtended.sol.png index 3c196097..5ee6006c 100644 Binary files a/doc/schema/surya/surya_graph/surya_graph_ITokenBindingExtended.sol.png and b/doc/schema/surya/surya_graph/surya_graph_ITokenBindingExtended.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_Ownable2StepInterfaceId.sol.png b/doc/schema/surya/surya_graph/surya_graph_Ownable2StepInterfaceId.sol.png index 5b4fa6b1..c3d7cada 100644 Binary files a/doc/schema/surya/surya_graph/surya_graph_Ownable2StepInterfaceId.sol.png and b/doc/schema/surya/surya_graph/surya_graph_Ownable2StepInterfaceId.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_OwnableInterfaceId.sol.png b/doc/schema/surya/surya_graph/surya_graph_OwnableInterfaceId.sol.png index 5b4fa6b1..c3d7cada 100644 Binary files a/doc/schema/surya/surya_graph/surya_graph_OwnableInterfaceId.sol.png and b/doc/schema/surya/surya_graph/surya_graph_OwnableInterfaceId.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_RuleAddressList.sol.png b/doc/schema/surya/surya_graph/surya_graph_RuleAddressList.sol.png index 928cc675..f032dc83 100644 Binary files a/doc/schema/surya/surya_graph/surya_graph_RuleAddressList.sol.png and b/doc/schema/surya/surya_graph/surya_graph_RuleAddressList.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_RuleAddressListInternal.sol.png b/doc/schema/surya/surya_graph/surya_graph_RuleAddressListInternal.sol.png index 073a3ae0..1f02f658 100644 Binary files a/doc/schema/surya/surya_graph/surya_graph_RuleAddressListInternal.sol.png and b/doc/schema/surya/surya_graph/surya_graph_RuleAddressListInternal.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_RuleAddressListInvariantStorage.sol.png b/doc/schema/surya/surya_graph/surya_graph_RuleAddressListInvariantStorage.sol.png index 5b4fa6b1..c3d7cada 100644 Binary files a/doc/schema/surya/surya_graph/surya_graph_RuleAddressListInvariantStorage.sol.png and b/doc/schema/surya/surya_graph/surya_graph_RuleAddressListInvariantStorage.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_RuleBlacklistInvariantStorage.sol.png b/doc/schema/surya/surya_graph/surya_graph_RuleBlacklistInvariantStorage.sol.png index 5b4fa6b1..c3d7cada 100644 Binary files a/doc/schema/surya/surya_graph/surya_graph_RuleBlacklistInvariantStorage.sol.png and b/doc/schema/surya/surya_graph/surya_graph_RuleBlacklistInvariantStorage.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_RuleCommonInvariantStorage.sol.png b/doc/schema/surya/surya_graph/surya_graph_RuleCommonInvariantStorage.sol.png index 5b4fa6b1..c3d7cada 100644 Binary files a/doc/schema/surya/surya_graph/surya_graph_RuleCommonInvariantStorage.sol.png and b/doc/schema/surya/surya_graph/surya_graph_RuleCommonInvariantStorage.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_RuleConditionalTransferLightInvariantStorage.sol.png b/doc/schema/surya/surya_graph/surya_graph_RuleConditionalTransferLightInvariantStorage.sol.png index 5b4fa6b1..c3d7cada 100644 Binary files a/doc/schema/surya/surya_graph/surya_graph_RuleConditionalTransferLightInvariantStorage.sol.png and b/doc/schema/surya/surya_graph/surya_graph_RuleConditionalTransferLightInvariantStorage.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_RuleConditionalTransferLightMock.sol.png b/doc/schema/surya/surya_graph/surya_graph_RuleConditionalTransferLightMock.sol.png index e68932be..1f14fba9 100644 Binary files a/doc/schema/surya/surya_graph/surya_graph_RuleConditionalTransferLightMock.sol.png and b/doc/schema/surya/surya_graph/surya_graph_RuleConditionalTransferLightMock.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_RuleEngine.sol.png b/doc/schema/surya/surya_graph/surya_graph_RuleEngine.sol.png index 144de8ae..16a8d844 100644 Binary files a/doc/schema/surya/surya_graph/surya_graph_RuleEngine.sol.png and b/doc/schema/surya/surya_graph/surya_graph_RuleEngine.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_RuleEngine2771.sol.png b/doc/schema/surya/surya_graph/surya_graph_RuleEngine2771.sol.png new file mode 100644 index 00000000..11bdcd1e Binary files /dev/null and b/doc/schema/surya/surya_graph/surya_graph_RuleEngine2771.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_RuleEngineBase.sol.png b/doc/schema/surya/surya_graph/surya_graph_RuleEngineBase.sol.png index c64cb77b..175d4fd2 100644 Binary files a/doc/schema/surya/surya_graph/surya_graph_RuleEngineBase.sol.png and b/doc/schema/surya/surya_graph/surya_graph_RuleEngineBase.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_RuleEngineExposed.sol.png b/doc/schema/surya/surya_graph/surya_graph_RuleEngineExposed.sol.png index 04d69c90..1a21120c 100644 Binary files a/doc/schema/surya/surya_graph/surya_graph_RuleEngineExposed.sol.png and b/doc/schema/surya/surya_graph/surya_graph_RuleEngineExposed.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_RuleEngineInvariantStorage.sol.png b/doc/schema/surya/surya_graph/surya_graph_RuleEngineInvariantStorage.sol.png index 5b4fa6b1..c3d7cada 100644 Binary files a/doc/schema/surya/surya_graph/surya_graph_RuleEngineInvariantStorage.sol.png and b/doc/schema/surya/surya_graph/surya_graph_RuleEngineInvariantStorage.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_RuleEngineOwnable.sol.png b/doc/schema/surya/surya_graph/surya_graph_RuleEngineOwnable.sol.png index a0f38c65..99c18852 100644 Binary files a/doc/schema/surya/surya_graph/surya_graph_RuleEngineOwnable.sol.png and b/doc/schema/surya/surya_graph/surya_graph_RuleEngineOwnable.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_RuleEngineOwnable2771.sol.png b/doc/schema/surya/surya_graph/surya_graph_RuleEngineOwnable2771.sol.png new file mode 100644 index 00000000..e2766599 Binary files /dev/null and b/doc/schema/surya/surya_graph/surya_graph_RuleEngineOwnable2771.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_RuleEngineOwnable2Step.sol.png b/doc/schema/surya/surya_graph/surya_graph_RuleEngineOwnable2Step.sol.png index ba604e63..ef6ebab8 100644 Binary files a/doc/schema/surya/surya_graph/surya_graph_RuleEngineOwnable2Step.sol.png and b/doc/schema/surya/surya_graph/surya_graph_RuleEngineOwnable2Step.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_RuleEngineOwnable2Step2771.sol.png b/doc/schema/surya/surya_graph/surya_graph_RuleEngineOwnable2Step2771.sol.png new file mode 100644 index 00000000..6bf76002 Binary files /dev/null and b/doc/schema/surya/surya_graph/surya_graph_RuleEngineOwnable2Step2771.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_RuleEngineOwnableShared.sol.png b/doc/schema/surya/surya_graph/surya_graph_RuleEngineOwnableShared.sol.png index 991844c1..a8326226 100644 Binary files a/doc/schema/surya/surya_graph/surya_graph_RuleEngineOwnableShared.sol.png and b/doc/schema/surya/surya_graph/surya_graph_RuleEngineOwnableShared.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_RuleInterfaceId.sol.png b/doc/schema/surya/surya_graph/surya_graph_RuleInterfaceId.sol.png index 5b4fa6b1..c3d7cada 100644 Binary files a/doc/schema/surya/surya_graph/surya_graph_RuleInterfaceId.sol.png and b/doc/schema/surya/surya_graph/surya_graph_RuleInterfaceId.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_RuleInvalidMock.sol.png b/doc/schema/surya/surya_graph/surya_graph_RuleInvalidMock.sol.png index 5b4fa6b1..c3d7cada 100644 Binary files a/doc/schema/surya/surya_graph/surya_graph_RuleInvalidMock.sol.png and b/doc/schema/surya/surya_graph/surya_graph_RuleInvalidMock.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_RuleMintAllowanceInvariantStorage.sol.png b/doc/schema/surya/surya_graph/surya_graph_RuleMintAllowanceInvariantStorage.sol.png index 5b4fa6b1..c3d7cada 100644 Binary files a/doc/schema/surya/surya_graph/surya_graph_RuleMintAllowanceInvariantStorage.sol.png and b/doc/schema/surya/surya_graph/surya_graph_RuleMintAllowanceInvariantStorage.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_RuleMintAllowanceMock.sol.png b/doc/schema/surya/surya_graph/surya_graph_RuleMintAllowanceMock.sol.png index 8869c66d..b0c8ff20 100644 Binary files a/doc/schema/surya/surya_graph/surya_graph_RuleMintAllowanceMock.sol.png and b/doc/schema/surya/surya_graph/surya_graph_RuleMintAllowanceMock.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_RuleOperationRevertMock.sol.png b/doc/schema/surya/surya_graph/surya_graph_RuleOperationRevertMock.sol.png index 27cfc1d4..d7841062 100644 Binary files a/doc/schema/surya/surya_graph/surya_graph_RuleOperationRevertMock.sol.png and b/doc/schema/surya/surya_graph/surya_graph_RuleOperationRevertMock.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_RuleWhitelistCommon.sol.png b/doc/schema/surya/surya_graph/surya_graph_RuleWhitelistCommon.sol.png index 302b3c88..d9c93ee9 100644 Binary files a/doc/schema/surya/surya_graph/surya_graph_RuleWhitelistCommon.sol.png and b/doc/schema/surya/surya_graph/surya_graph_RuleWhitelistCommon.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_RuleWhitelistInvariantStorage.sol.png b/doc/schema/surya/surya_graph/surya_graph_RuleWhitelistInvariantStorage.sol.png index 5b4fa6b1..c3d7cada 100644 Binary files a/doc/schema/surya/surya_graph/surya_graph_RuleWhitelistInvariantStorage.sol.png and b/doc/schema/surya/surya_graph/surya_graph_RuleWhitelistInvariantStorage.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_RuleWhitelistMock.sol.png b/doc/schema/surya/surya_graph/surya_graph_RuleWhitelistMock.sol.png index a13af5d1..fb0fa921 100644 Binary files a/doc/schema/surya/surya_graph/surya_graph_RuleWhitelistMock.sol.png and b/doc/schema/surya/surya_graph/surya_graph_RuleWhitelistMock.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_RulesManagementModule.sol.png b/doc/schema/surya/surya_graph/surya_graph_RulesManagementModule.sol.png index cdd8704a..a1a62650 100644 Binary files a/doc/schema/surya/surya_graph/surya_graph_RulesManagementModule.sol.png and b/doc/schema/surya/surya_graph/surya_graph_RulesManagementModule.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_RulesManagementModuleInvariantStorage.sol.png b/doc/schema/surya/surya_graph/surya_graph_RulesManagementModuleInvariantStorage.sol.png index 5b4fa6b1..c3d7cada 100644 Binary files a/doc/schema/surya/surya_graph/surya_graph_RulesManagementModuleInvariantStorage.sol.png and b/doc/schema/surya/surya_graph/surya_graph_RulesManagementModuleInvariantStorage.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_RulesManagementModuleRolesStorage.sol.png b/doc/schema/surya/surya_graph/surya_graph_RulesManagementModuleRolesStorage.sol.png index 5b4fa6b1..c3d7cada 100644 Binary files a/doc/schema/surya/surya_graph/surya_graph_RulesManagementModuleRolesStorage.sol.png and b/doc/schema/surya/surya_graph/surya_graph_RulesManagementModuleRolesStorage.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_TokenBindingExtendedModule.sol.png b/doc/schema/surya/surya_graph/surya_graph_TokenBindingExtendedModule.sol.png index c40b68ac..4062d971 100644 Binary files a/doc/schema/surya/surya_graph/surya_graph_TokenBindingExtendedModule.sol.png and b/doc/schema/surya/surya_graph/surya_graph_TokenBindingExtendedModule.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_TokenBindingModule.sol.png b/doc/schema/surya/surya_graph/surya_graph_TokenBindingModule.sol.png index c78e3e57..3a558ed5 100644 Binary files a/doc/schema/surya/surya_graph/surya_graph_TokenBindingModule.sol.png and b/doc/schema/surya/surya_graph/surya_graph_TokenBindingModule.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_TokenBindingModuleInvariantStorage.sol.png b/doc/schema/surya/surya_graph/surya_graph_TokenBindingModuleInvariantStorage.sol.png index 5b4fa6b1..c3d7cada 100644 Binary files a/doc/schema/surya/surya_graph/surya_graph_TokenBindingModuleInvariantStorage.sol.png and b/doc/schema/surya/surya_graph/surya_graph_TokenBindingModuleInvariantStorage.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_TokenBindingStandaloneMock.sol.png b/doc/schema/surya/surya_graph/surya_graph_TokenBindingStandaloneMock.sol.png index cfb5e80c..8b55a6cd 100644 Binary files a/doc/schema/surya/surya_graph/surya_graph_TokenBindingStandaloneMock.sol.png and b/doc/schema/surya/surya_graph/surya_graph_TokenBindingStandaloneMock.sol.png differ diff --git a/doc/schema/surya/surya_graph/surya_graph_VersionModule.sol.png b/doc/schema/surya/surya_graph/surya_graph_VersionModule.sol.png index bb072c93..5192f2d1 100644 Binary files a/doc/schema/surya/surya_graph/surya_graph_VersionModule.sol.png and b/doc/schema/surya/surya_graph/surya_graph_VersionModule.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_ComplianceInterfaceId.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_ComplianceInterfaceId.sol.png index b5cc4fb1..f9a49994 100644 Binary files a/doc/schema/surya/surya_inheritance/surya_inheritance_ComplianceInterfaceId.sol.png and b/doc/schema/surya/surya_inheritance/surya_inheritance_ComplianceInterfaceId.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_ERC1404InterfaceId.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_ERC1404InterfaceId.sol.png index 3f59ab06..eeea4553 100644 Binary files a/doc/schema/surya/surya_inheritance/surya_inheritance_ERC1404InterfaceId.sol.png and b/doc/schema/surya/surya_inheritance/surya_inheritance_ERC1404InterfaceId.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_ERC2771ModuleStandalone.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_ERC2771ModuleStandalone.sol.png index 1b05ef44..47ad9e3e 100644 Binary files a/doc/schema/surya/surya_inheritance/surya_inheritance_ERC2771ModuleStandalone.sol.png and b/doc/schema/surya/surya_inheritance/surya_inheritance_ERC2771ModuleStandalone.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_ERC3643ComplianceExtendedModule.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_ERC3643ComplianceExtendedModule.sol.png index 281bdb7c..c85dff8b 100644 Binary files a/doc/schema/surya/surya_inheritance/surya_inheritance_ERC3643ComplianceExtendedModule.sol.png and b/doc/schema/surya/surya_inheritance/surya_inheritance_ERC3643ComplianceExtendedModule.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_ERC3643ComplianceModule.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_ERC3643ComplianceModule.sol.png index f3336c5f..bf6832ec 100644 Binary files a/doc/schema/surya/surya_inheritance/surya_inheritance_ERC3643ComplianceModule.sol.png and b/doc/schema/surya/surya_inheritance/surya_inheritance_ERC3643ComplianceModule.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_ERC3643ComplianceRolesStorage.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_ERC3643ComplianceRolesStorage.sol.png index dca14147..391e28f3 100644 Binary files a/doc/schema/surya/surya_inheritance/surya_inheritance_ERC3643ComplianceRolesStorage.sol.png and b/doc/schema/surya/surya_inheritance/surya_inheritance_ERC3643ComplianceRolesStorage.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_ERC3643TokenMock.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_ERC3643TokenMock.sol.png index 76d95244..213d9c67 100644 Binary files a/doc/schema/surya/surya_inheritance/surya_inheritance_ERC3643TokenMock.sol.png and b/doc/schema/surya/surya_inheritance/surya_inheritance_ERC3643TokenMock.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_ICompliance.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_ICompliance.sol.png index 6ecad54d..c2996beb 100644 Binary files a/doc/schema/surya/surya_inheritance/surya_inheritance_ICompliance.sol.png and b/doc/schema/surya/surya_inheritance/surya_inheritance_ICompliance.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_IERC1404Subset.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_IERC1404Subset.sol.png index e9b2bdfe..eed9b9a7 100644 Binary files a/doc/schema/surya/surya_inheritance/surya_inheritance_IERC1404Subset.sol.png and b/doc/schema/surya/surya_inheritance/surya_inheritance_IERC1404Subset.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_IERC173Subset.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_IERC173Subset.sol.png index 8faf6ef0..c71e53ed 100644 Binary files a/doc/schema/surya/surya_inheritance/surya_inheritance_IERC173Subset.sol.png and b/doc/schema/surya/surya_inheritance/surya_inheritance_IERC173Subset.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_IERC3643Compliance.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_IERC3643Compliance.sol.png index f8bd342e..99e2f39e 100644 Binary files a/doc/schema/surya/surya_inheritance/surya_inheritance_IERC3643Compliance.sol.png and b/doc/schema/surya/surya_inheritance/surya_inheritance_IERC3643Compliance.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_IERC3643ComplianceExtended.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_IERC3643ComplianceExtended.sol.png index ad79d975..8b839f15 100644 Binary files a/doc/schema/surya/surya_inheritance/surya_inheritance_IERC3643ComplianceExtended.sol.png and b/doc/schema/surya/surya_inheritance/surya_inheritance_IERC3643ComplianceExtended.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_IERC3643ComplianceExtendedSubset.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_IERC3643ComplianceExtendedSubset.sol.png index 7d216eaa..4cd31898 100644 Binary files a/doc/schema/surya/surya_inheritance/surya_inheritance_IERC3643ComplianceExtendedSubset.sol.png and b/doc/schema/surya/surya_inheritance/surya_inheritance_IERC3643ComplianceExtendedSubset.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_IERC7551ComplianceSubset.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_IERC7551ComplianceSubset.sol.png index 960a3ad3..0b2a2fd9 100644 Binary files a/doc/schema/surya/surya_inheritance/surya_inheritance_IERC7551ComplianceSubset.sol.png and b/doc/schema/surya/surya_inheritance/surya_inheritance_IERC7551ComplianceSubset.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_IOwnable2StepSubset.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_IOwnable2StepSubset.sol.png index 3e93dcd7..b3499369 100644 Binary files a/doc/schema/surya/surya_inheritance/surya_inheritance_IOwnable2StepSubset.sol.png and b/doc/schema/surya/surya_inheritance/surya_inheritance_IOwnable2StepSubset.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_IRule.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_IRule.sol.png index 39d3070c..66d9f9e1 100644 Binary files a/doc/schema/surya/surya_inheritance/surya_inheritance_IRule.sol.png and b/doc/schema/surya/surya_inheritance/surya_inheritance_IRule.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_IRuleInterfaceIdHelper.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_IRuleInterfaceIdHelper.sol.png index d2af68ff..8ae5bd9b 100644 Binary files a/doc/schema/surya/surya_inheritance/surya_inheritance_IRuleInterfaceIdHelper.sol.png and b/doc/schema/surya/surya_inheritance/surya_inheritance_IRuleInterfaceIdHelper.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_IRulesManagementModule.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_IRulesManagementModule.sol.png index d27b5f3f..e981762f 100644 Binary files a/doc/schema/surya/surya_inheritance/surya_inheritance_IRulesManagementModule.sol.png and b/doc/schema/surya/surya_inheritance/surya_inheritance_IRulesManagementModule.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_ITokenBinding.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_ITokenBinding.sol.png index f9d8287b..c4c8182b 100644 Binary files a/doc/schema/surya/surya_inheritance/surya_inheritance_ITokenBinding.sol.png and b/doc/schema/surya/surya_inheritance/surya_inheritance_ITokenBinding.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_ITokenBindingExtended.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_ITokenBindingExtended.sol.png index 30ea103b..41c174d3 100644 Binary files a/doc/schema/surya/surya_inheritance/surya_inheritance_ITokenBindingExtended.sol.png and b/doc/schema/surya/surya_inheritance/surya_inheritance_ITokenBindingExtended.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_Ownable2StepInterfaceId.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_Ownable2StepInterfaceId.sol.png index f84cd40b..cdbefdde 100644 Binary files a/doc/schema/surya/surya_inheritance/surya_inheritance_Ownable2StepInterfaceId.sol.png and b/doc/schema/surya/surya_inheritance/surya_inheritance_Ownable2StepInterfaceId.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_OwnableInterfaceId.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_OwnableInterfaceId.sol.png index 6e3cf835..ab560277 100644 Binary files a/doc/schema/surya/surya_inheritance/surya_inheritance_OwnableInterfaceId.sol.png and b/doc/schema/surya/surya_inheritance/surya_inheritance_OwnableInterfaceId.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_RuleAddressList.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleAddressList.sol.png index 3895b71b..533e6d37 100644 Binary files a/doc/schema/surya/surya_inheritance/surya_inheritance_RuleAddressList.sol.png and b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleAddressList.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_RuleAddressListInternal.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleAddressListInternal.sol.png index f5fbec68..2596ec60 100644 Binary files a/doc/schema/surya/surya_inheritance/surya_inheritance_RuleAddressListInternal.sol.png and b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleAddressListInternal.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_RuleAddressListInvariantStorage.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleAddressListInvariantStorage.sol.png index 5e3e8ef4..55a5da8e 100644 Binary files a/doc/schema/surya/surya_inheritance/surya_inheritance_RuleAddressListInvariantStorage.sol.png and b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleAddressListInvariantStorage.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_RuleBlacklistInvariantStorage.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleBlacklistInvariantStorage.sol.png index 813852a1..c29767e8 100644 Binary files a/doc/schema/surya/surya_inheritance/surya_inheritance_RuleBlacklistInvariantStorage.sol.png and b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleBlacklistInvariantStorage.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_RuleCommonInvariantStorage.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleCommonInvariantStorage.sol.png index d521a635..19f2321b 100644 Binary files a/doc/schema/surya/surya_inheritance/surya_inheritance_RuleCommonInvariantStorage.sol.png and b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleCommonInvariantStorage.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_RuleConditionalTransferLightInvariantStorage.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleConditionalTransferLightInvariantStorage.sol.png index f54aa6cd..d4845a97 100644 Binary files a/doc/schema/surya/surya_inheritance/surya_inheritance_RuleConditionalTransferLightInvariantStorage.sol.png and b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleConditionalTransferLightInvariantStorage.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_RuleConditionalTransferLightMock.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleConditionalTransferLightMock.sol.png index 40224803..a4ba0c80 100644 Binary files a/doc/schema/surya/surya_inheritance/surya_inheritance_RuleConditionalTransferLightMock.sol.png and b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleConditionalTransferLightMock.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_RuleEngine.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleEngine.sol.png index 7c1f8ce4..0fe3c31f 100644 Binary files a/doc/schema/surya/surya_inheritance/surya_inheritance_RuleEngine.sol.png and b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleEngine.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_RuleEngine2771.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleEngine2771.sol.png new file mode 100644 index 00000000..12634d3b Binary files /dev/null and b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleEngine2771.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_RuleEngineBase.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleEngineBase.sol.png index ec37639c..acf6a784 100644 Binary files a/doc/schema/surya/surya_inheritance/surya_inheritance_RuleEngineBase.sol.png and b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleEngineBase.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_RuleEngineExposed.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleEngineExposed.sol.png index 3ceff42e..ac90f62c 100644 Binary files a/doc/schema/surya/surya_inheritance/surya_inheritance_RuleEngineExposed.sol.png and b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleEngineExposed.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_RuleEngineInvariantStorage.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleEngineInvariantStorage.sol.png index 30f62037..e2434037 100644 Binary files a/doc/schema/surya/surya_inheritance/surya_inheritance_RuleEngineInvariantStorage.sol.png and b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleEngineInvariantStorage.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_RuleEngineOwnable.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleEngineOwnable.sol.png index 0b74357a..1c9745da 100644 Binary files a/doc/schema/surya/surya_inheritance/surya_inheritance_RuleEngineOwnable.sol.png and b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleEngineOwnable.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_RuleEngineOwnable2771.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleEngineOwnable2771.sol.png new file mode 100644 index 00000000..c702af81 Binary files /dev/null and b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleEngineOwnable2771.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_RuleEngineOwnable2Step.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleEngineOwnable2Step.sol.png index ff3fd8ec..aeb03410 100644 Binary files a/doc/schema/surya/surya_inheritance/surya_inheritance_RuleEngineOwnable2Step.sol.png and b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleEngineOwnable2Step.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_RuleEngineOwnable2Step2771.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleEngineOwnable2Step2771.sol.png new file mode 100644 index 00000000..a737b0a3 Binary files /dev/null and b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleEngineOwnable2Step2771.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_RuleEngineOwnableShared.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleEngineOwnableShared.sol.png index 762f4fe3..0d55d602 100644 Binary files a/doc/schema/surya/surya_inheritance/surya_inheritance_RuleEngineOwnableShared.sol.png and b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleEngineOwnableShared.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_RuleInterfaceId.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleInterfaceId.sol.png index 19b40386..6bd26e1d 100644 Binary files a/doc/schema/surya/surya_inheritance/surya_inheritance_RuleInterfaceId.sol.png and b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleInterfaceId.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_RuleInvalidMock.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleInvalidMock.sol.png index 64fb4958..8efab6b7 100644 Binary files a/doc/schema/surya/surya_inheritance/surya_inheritance_RuleInvalidMock.sol.png and b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleInvalidMock.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_RuleMintAllowanceInvariantStorage.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleMintAllowanceInvariantStorage.sol.png index b97aff62..0da62bc9 100644 Binary files a/doc/schema/surya/surya_inheritance/surya_inheritance_RuleMintAllowanceInvariantStorage.sol.png and b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleMintAllowanceInvariantStorage.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_RuleMintAllowanceMock.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleMintAllowanceMock.sol.png index d7d82b48..d6ac1747 100644 Binary files a/doc/schema/surya/surya_inheritance/surya_inheritance_RuleMintAllowanceMock.sol.png and b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleMintAllowanceMock.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_RuleOperationRevertMock.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleOperationRevertMock.sol.png index 1ff48b47..0e8d26d9 100644 Binary files a/doc/schema/surya/surya_inheritance/surya_inheritance_RuleOperationRevertMock.sol.png and b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleOperationRevertMock.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_RuleWhitelistCommon.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleWhitelistCommon.sol.png index b4891faa..de205463 100644 Binary files a/doc/schema/surya/surya_inheritance/surya_inheritance_RuleWhitelistCommon.sol.png and b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleWhitelistCommon.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_RuleWhitelistInvariantStorage.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleWhitelistInvariantStorage.sol.png index 64630f82..ddd7a4ea 100644 Binary files a/doc/schema/surya/surya_inheritance/surya_inheritance_RuleWhitelistInvariantStorage.sol.png and b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleWhitelistInvariantStorage.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_RuleWhitelistMock.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleWhitelistMock.sol.png index 96885bf0..ac9a3ea0 100644 Binary files a/doc/schema/surya/surya_inheritance/surya_inheritance_RuleWhitelistMock.sol.png and b/doc/schema/surya/surya_inheritance/surya_inheritance_RuleWhitelistMock.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_RulesManagementModule.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_RulesManagementModule.sol.png index 617fdfbd..05e8ac41 100644 Binary files a/doc/schema/surya/surya_inheritance/surya_inheritance_RulesManagementModule.sol.png and b/doc/schema/surya/surya_inheritance/surya_inheritance_RulesManagementModule.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_RulesManagementModuleInvariantStorage.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_RulesManagementModuleInvariantStorage.sol.png index 3d5fb78d..632a20ec 100644 Binary files a/doc/schema/surya/surya_inheritance/surya_inheritance_RulesManagementModuleInvariantStorage.sol.png and b/doc/schema/surya/surya_inheritance/surya_inheritance_RulesManagementModuleInvariantStorage.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_RulesManagementModuleRolesStorage.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_RulesManagementModuleRolesStorage.sol.png index b00833ea..afdfdeb8 100644 Binary files a/doc/schema/surya/surya_inheritance/surya_inheritance_RulesManagementModuleRolesStorage.sol.png and b/doc/schema/surya/surya_inheritance/surya_inheritance_RulesManagementModuleRolesStorage.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_TokenBindingExtendedModule.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_TokenBindingExtendedModule.sol.png index 5816c88c..9130ace5 100644 Binary files a/doc/schema/surya/surya_inheritance/surya_inheritance_TokenBindingExtendedModule.sol.png and b/doc/schema/surya/surya_inheritance/surya_inheritance_TokenBindingExtendedModule.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_TokenBindingModule.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_TokenBindingModule.sol.png index 45900c2f..5d2f0a53 100644 Binary files a/doc/schema/surya/surya_inheritance/surya_inheritance_TokenBindingModule.sol.png and b/doc/schema/surya/surya_inheritance/surya_inheritance_TokenBindingModule.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_TokenBindingModuleInvariantStorage.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_TokenBindingModuleInvariantStorage.sol.png index b5a88c1d..76264b6e 100644 Binary files a/doc/schema/surya/surya_inheritance/surya_inheritance_TokenBindingModuleInvariantStorage.sol.png and b/doc/schema/surya/surya_inheritance/surya_inheritance_TokenBindingModuleInvariantStorage.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_TokenBindingStandaloneMock.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_TokenBindingStandaloneMock.sol.png index bf950347..adb4699a 100644 Binary files a/doc/schema/surya/surya_inheritance/surya_inheritance_TokenBindingStandaloneMock.sol.png and b/doc/schema/surya/surya_inheritance/surya_inheritance_TokenBindingStandaloneMock.sol.png differ diff --git a/doc/schema/surya/surya_inheritance/surya_inheritance_VersionModule.sol.png b/doc/schema/surya/surya_inheritance/surya_inheritance_VersionModule.sol.png index a0dbc869..f9fb0556 100644 Binary files a/doc/schema/surya/surya_inheritance/surya_inheritance_VersionModule.sol.png and b/doc/schema/surya/surya_inheritance/surya_inheritance_VersionModule.sol.png differ diff --git a/doc/schema/surya/surya_report/surya_report_ComplianceInterfaceId.sol.md b/doc/schema/surya/surya_report/surya_report_ComplianceInterfaceId.sol.md index 2ad1c8c3..5477b12f 100644 --- a/doc/schema/surya/surya_report/surya_report_ComplianceInterfaceId.sol.md +++ b/doc/schema/surya/surya_report/surya_report_ComplianceInterfaceId.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./modules/library/ComplianceInterfaceId.sol | 1d2e44d2adb90df418028c279d4c2c52b49d4219 | +| ./modules/library/ComplianceInterfaceId.sol | 71d4f6ca0e6c89119e63973fa4a6fd6e56c03ea2 | ### Contracts Description Table diff --git a/doc/schema/surya/surya_report/surya_report_ERC1404InterfaceId.sol.md b/doc/schema/surya/surya_report/surya_report_ERC1404InterfaceId.sol.md index 58f389e7..aacd6beb 100644 --- a/doc/schema/surya/surya_report/surya_report_ERC1404InterfaceId.sol.md +++ b/doc/schema/surya/surya_report/surya_report_ERC1404InterfaceId.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./modules/library/ERC1404InterfaceId.sol | a33a85519a39a7dc75bd9ed7bcb88a51ec6dd4b5 | +| ./modules/library/ERC1404InterfaceId.sol | fcdd6b316e5a554c19350fd56f9b2641b4cace64 | ### Contracts Description Table diff --git a/doc/schema/surya/surya_report/surya_report_ERC2771ModuleStandalone.sol.md b/doc/schema/surya/surya_report/surya_report_ERC2771ModuleStandalone.sol.md index c80bf070..9225b29a 100644 --- a/doc/schema/surya/surya_report/surya_report_ERC2771ModuleStandalone.sol.md +++ b/doc/schema/surya/surya_report/surya_report_ERC2771ModuleStandalone.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./modules/ERC2771ModuleStandalone.sol | ca20e6f6f7f28ab2e5d90be759f773456dae36fb | +| ./modules/ERC2771ModuleStandalone.sol | c02c92b754990e8e04045fb29006b4a2be3e0504 | ### Contracts Description Table diff --git a/doc/schema/surya/surya_report/surya_report_ERC3643ComplianceExtendedModule.sol.md b/doc/schema/surya/surya_report/surya_report_ERC3643ComplianceExtendedModule.sol.md index 142b322f..fc92f82e 100644 --- a/doc/schema/surya/surya_report/surya_report_ERC3643ComplianceExtendedModule.sol.md +++ b/doc/schema/surya/surya_report/surya_report_ERC3643ComplianceExtendedModule.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./modules/ERC3643ComplianceExtendedModule.sol | 889c64f0f42969f3ddbf09e19b350058bc8cc955 | +| ./modules/ERC3643ComplianceExtendedModule.sol | 5e6a5a23033972191c090c478a29a672141b3c72 | ### Contracts Description Table @@ -17,6 +17,7 @@ |||||| | **ERC3643ComplianceExtendedModule** | Implementation | TokenBindingExtendedModule, ERC3643ComplianceModule, IERC3643ComplianceExtended ||| | └ | _authorizeTokenBindingChange | Internal 🔒 | 🛑 | | +| └ | _unbindToken | Internal 🔒 | 🛑 | | ### Legend diff --git a/doc/schema/surya/surya_report/surya_report_ERC3643ComplianceModule.sol.md b/doc/schema/surya/surya_report/surya_report_ERC3643ComplianceModule.sol.md index 484eeba3..d83c54b2 100644 --- a/doc/schema/surya/surya_report/surya_report_ERC3643ComplianceModule.sol.md +++ b/doc/schema/surya/surya_report/surya_report_ERC3643ComplianceModule.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./modules/ERC3643ComplianceModule.sol | 85c740155a17502a2f306f82eaa7335e186dc40a | +| ./modules/ERC3643ComplianceModule.sol | d1c9786b0d271b8fef56ef889a58e3904557d54b | ### Contracts Description Table diff --git a/doc/schema/surya/surya_report/surya_report_ERC3643ComplianceRolesStorage.sol.md b/doc/schema/surya/surya_report/surya_report_ERC3643ComplianceRolesStorage.sol.md index 24fed78f..fb8f78e7 100644 --- a/doc/schema/surya/surya_report/surya_report_ERC3643ComplianceRolesStorage.sol.md +++ b/doc/schema/surya/surya_report/surya_report_ERC3643ComplianceRolesStorage.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./modules/library/ERC3643ComplianceRolesStorage.sol | 0554655baf30dbb890e6975a632b059ee909643f | +| ./modules/library/ERC3643ComplianceRolesStorage.sol | 3c407e5969546a3c7d6ba61adb32414fe17cc0d2 | ### Contracts Description Table diff --git a/doc/schema/surya/surya_report/surya_report_ERC3643TokenMock.sol.md b/doc/schema/surya/surya_report/surya_report_ERC3643TokenMock.sol.md index f5ff9e6d..c8367e59 100644 --- a/doc/schema/surya/surya_report/surya_report_ERC3643TokenMock.sol.md +++ b/doc/schema/surya/surya_report/surya_report_ERC3643TokenMock.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./mocks/ERC3643TokenMock.sol | a3db1884accf6ce3397c3f7e65e576fc46983a0b | +| ./mocks/ERC3643TokenMock.sol | a4a5ad6b76c3b00efe7c72157b862fecb571188a | ### Contracts Description Table diff --git a/doc/schema/surya/surya_report/surya_report_ICompliance.sol.md b/doc/schema/surya/surya_report/surya_report_ICompliance.sol.md index aafef79e..90e619b3 100644 --- a/doc/schema/surya/surya_report/surya_report_ICompliance.sol.md +++ b/doc/schema/surya/surya_report/surya_report_ICompliance.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./mocks/ICompliance.sol | d60ed00e5ca3214d76ec4a3611920400a135368e | +| ./mocks/ICompliance.sol | 9a38bb55b45e91f8b7ac9018491a1d6d6a5214a2 | ### Contracts Description Table diff --git a/doc/schema/surya/surya_report/surya_report_IERC1404Subset.sol.md b/doc/schema/surya/surya_report/surya_report_IERC1404Subset.sol.md index d5328510..1b633b1f 100644 --- a/doc/schema/surya/surya_report/surya_report_IERC1404Subset.sol.md +++ b/doc/schema/surya/surya_report/surya_report_IERC1404Subset.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./mocks/IERC1404Subset.sol | cc27c24b8ab0b350a1d802ce9dec1b26b4a9369d | +| ./mocks/IERC1404Subset.sol | b5e01059a0859a5dd112030a2ed23a4b1ed76f48 | ### Contracts Description Table diff --git a/doc/schema/surya/surya_report/surya_report_IERC173Subset.sol.md b/doc/schema/surya/surya_report/surya_report_IERC173Subset.sol.md index 54696204..2c15c5eb 100644 --- a/doc/schema/surya/surya_report/surya_report_IERC173Subset.sol.md +++ b/doc/schema/surya/surya_report/surya_report_IERC173Subset.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./mocks/IERC173Subset.sol | c15447b4467ff1054817bf3296f95a26283975de | +| ./mocks/IERC173Subset.sol | 9bca487468b2eea1143a4836ec0b095839dc76e9 | ### Contracts Description Table diff --git a/doc/schema/surya/surya_report/surya_report_IERC3643Compliance.sol.md b/doc/schema/surya/surya_report/surya_report_IERC3643Compliance.sol.md index 83bcd805..163ead75 100644 --- a/doc/schema/surya/surya_report/surya_report_IERC3643Compliance.sol.md +++ b/doc/schema/surya/surya_report/surya_report_IERC3643Compliance.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./interfaces/IERC3643Compliance.sol | c7bae1e0e5bd1e565e9c2fb3177577618f0cb9b6 | +| ./interfaces/IERC3643Compliance.sol | 8f54544a0e29a19827cc189798daeb6dd00066cf | ### Contracts Description Table diff --git a/doc/schema/surya/surya_report/surya_report_IERC3643ComplianceExtended.sol.md b/doc/schema/surya/surya_report/surya_report_IERC3643ComplianceExtended.sol.md index 42633cc8..186dba7a 100644 --- a/doc/schema/surya/surya_report/surya_report_IERC3643ComplianceExtended.sol.md +++ b/doc/schema/surya/surya_report/surya_report_IERC3643ComplianceExtended.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./interfaces/IERC3643ComplianceExtended.sol | a7e8ff1a670e67b5a8704ffb8f35fba446502c11 | +| ./interfaces/IERC3643ComplianceExtended.sol | 958724a556daf3c70839610f4ca0cee317d6f4d8 | ### Contracts Description Table diff --git a/doc/schema/surya/surya_report/surya_report_IERC3643ComplianceExtendedSubset.sol.md b/doc/schema/surya/surya_report/surya_report_IERC3643ComplianceExtendedSubset.sol.md index 4a0494d7..6eed3fb9 100644 --- a/doc/schema/surya/surya_report/surya_report_IERC3643ComplianceExtendedSubset.sol.md +++ b/doc/schema/surya/surya_report/surya_report_IERC3643ComplianceExtendedSubset.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./mocks/IERC3643ComplianceExtendedSubset.sol | db85332ba8f3327e2dff2a0f3da509cbc270be03 | +| ./mocks/IERC3643ComplianceExtendedSubset.sol | 8a1eedee27ce3913e14390dc6b356efab6a65111 | ### Contracts Description Table diff --git a/doc/schema/surya/surya_report/surya_report_IERC7551ComplianceSubset.sol.md b/doc/schema/surya/surya_report/surya_report_IERC7551ComplianceSubset.sol.md index eed90b2b..e0ec56ea 100644 --- a/doc/schema/surya/surya_report/surya_report_IERC7551ComplianceSubset.sol.md +++ b/doc/schema/surya/surya_report/surya_report_IERC7551ComplianceSubset.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./mocks/IERC7551ComplianceSubset.sol | 25d02e6850beac18aa40340a7e9617ff39bbe64a | +| ./mocks/IERC7551ComplianceSubset.sol | 675cf7bf59b680c52775104404d2a9618f16ddd7 | ### Contracts Description Table diff --git a/doc/schema/surya/surya_report/surya_report_IOwnable2StepSubset.sol.md b/doc/schema/surya/surya_report/surya_report_IOwnable2StepSubset.sol.md index 3257326b..70c97806 100644 --- a/doc/schema/surya/surya_report/surya_report_IOwnable2StepSubset.sol.md +++ b/doc/schema/surya/surya_report/surya_report_IOwnable2StepSubset.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./mocks/IOwnable2StepSubset.sol | 2c0b4a4eccfda2aa49f81039a5f5ae8f826dbe50 | +| ./mocks/IOwnable2StepSubset.sol | cc0b916aba040644eba928510e510d206acc2d9c | ### Contracts Description Table diff --git a/doc/schema/surya/surya_report/surya_report_IRule.sol.md b/doc/schema/surya/surya_report/surya_report_IRule.sol.md index cd7cc487..e3c85970 100644 --- a/doc/schema/surya/surya_report/surya_report_IRule.sol.md +++ b/doc/schema/surya/surya_report/surya_report_IRule.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./interfaces/IRule.sol | b4e0be299f2fe29785a03b1427992c6da26e2c5d | +| ./interfaces/IRule.sol | f07328ac6f54dcc331e382085c513719a572b4ef | ### Contracts Description Table @@ -15,7 +15,8 @@ |:----------:|:-------------------:|:----------------:|:----------------:|:---------------:| | └ | **Function Name** | **Visibility** | **Mutability** | **Modifiers** | |||||| -| **IRule** | Interface | IRuleEngineERC1404 ||| +| **IRule** | Interface | IERC1404Extend, IERC3643IComplianceContract, IERC165 ||| +| └ | transferred | External ❗️ | 🛑 |NO❗️ | | └ | canReturnTransferRestrictionCode | External ❗️ | |NO❗️ | diff --git a/doc/schema/surya/surya_report/surya_report_IRuleInterfaceIdHelper.sol.md b/doc/schema/surya/surya_report/surya_report_IRuleInterfaceIdHelper.sol.md index 1e7b8f28..ce50deda 100644 --- a/doc/schema/surya/surya_report/surya_report_IRuleInterfaceIdHelper.sol.md +++ b/doc/schema/surya/surya_report/surya_report_IRuleInterfaceIdHelper.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./mocks/IRuleInterfaceIdHelper.sol | 70fc82ab0f668a5d9ce3e3696a87de3618a5a630 | +| ./mocks/IRuleInterfaceIdHelper.sol | 114878710f41bcf1831b2d302365b70a0762a1ba | ### Contracts Description Table @@ -22,8 +22,6 @@ | └ | detectTransferRestriction | External ❗️ | |NO❗️ | | └ | messageForTransferRestriction | External ❗️ | |NO❗️ | | └ | detectTransferRestrictionFrom | External ❗️ | |NO❗️ | -| └ | canTransfer | External ❗️ | |NO❗️ | -| └ | canTransferFrom | External ❗️ | |NO❗️ | | └ | supportsInterface | External ❗️ | |NO❗️ | |||||| | **IRuleInterfaceIdHelper** | Implementation | ||| diff --git a/doc/schema/surya/surya_report/surya_report_IRulesManagementModule.sol.md b/doc/schema/surya/surya_report/surya_report_IRulesManagementModule.sol.md index d53bcb07..b4c02cfa 100644 --- a/doc/schema/surya/surya_report/surya_report_IRulesManagementModule.sol.md +++ b/doc/schema/surya/surya_report/surya_report_IRulesManagementModule.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./interfaces/IRulesManagementModule.sol | 19be4f04f6f4a4d36f36f3a7b0e4304b14c8a4b6 | +| ./interfaces/IRulesManagementModule.sol | a959734e162212b999c59d9a7199db0c85fac567 | ### Contracts Description Table diff --git a/doc/schema/surya/surya_report/surya_report_ITokenBinding.sol.md b/doc/schema/surya/surya_report/surya_report_ITokenBinding.sol.md index 2fd66d1a..c1d607bb 100644 --- a/doc/schema/surya/surya_report/surya_report_ITokenBinding.sol.md +++ b/doc/schema/surya/surya_report/surya_report_ITokenBinding.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./interfaces/ITokenBinding.sol | 3517eb93c9b988780a306eee58afeeaae1097505 | +| ./interfaces/ITokenBinding.sol | 7c1a1c3678372298dcee9111167db0416813dc33 | ### Contracts Description Table diff --git a/doc/schema/surya/surya_report/surya_report_ITokenBindingExtended.sol.md b/doc/schema/surya/surya_report/surya_report_ITokenBindingExtended.sol.md index 3d80d9c6..e747824b 100644 --- a/doc/schema/surya/surya_report/surya_report_ITokenBindingExtended.sol.md +++ b/doc/schema/surya/surya_report/surya_report_ITokenBindingExtended.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./interfaces/ITokenBindingExtended.sol | 07d4c02721bfac635a599088a2966730295d2570 | +| ./interfaces/ITokenBindingExtended.sol | 62b0c3b010c8497dbb743dca983288d4802ac857 | ### Contracts Description Table diff --git a/doc/schema/surya/surya_report/surya_report_Ownable2StepInterfaceId.sol.md b/doc/schema/surya/surya_report/surya_report_Ownable2StepInterfaceId.sol.md index cae8a412..30a5f2fa 100644 --- a/doc/schema/surya/surya_report/surya_report_Ownable2StepInterfaceId.sol.md +++ b/doc/schema/surya/surya_report/surya_report_Ownable2StepInterfaceId.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./modules/library/Ownable2StepInterfaceId.sol | a716d6c074ff158d21f882a5295f9c7b0bcefd38 | +| ./modules/library/Ownable2StepInterfaceId.sol | 044bb22fe9fd0ac850e804e8acbf8b332af6ba33 | ### Contracts Description Table diff --git a/doc/schema/surya/surya_report/surya_report_OwnableInterfaceId.sol.md b/doc/schema/surya/surya_report/surya_report_OwnableInterfaceId.sol.md index 84725f2f..eaf00f96 100644 --- a/doc/schema/surya/surya_report/surya_report_OwnableInterfaceId.sol.md +++ b/doc/schema/surya/surya_report/surya_report_OwnableInterfaceId.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./modules/library/OwnableInterfaceId.sol | edfa6252f8fc5c531679d92691f96b675b9cf6d8 | +| ./modules/library/OwnableInterfaceId.sol | 0a62e72b68ada1726a0a411bc31270729ba3a7a6 | ### Contracts Description Table diff --git a/doc/schema/surya/surya_report/surya_report_RuleAddressList.sol.md b/doc/schema/surya/surya_report/surya_report_RuleAddressList.sol.md index 86267cee..2ff065ce 100644 --- a/doc/schema/surya/surya_report/surya_report_RuleAddressList.sol.md +++ b/doc/schema/surya/surya_report/surya_report_RuleAddressList.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./mocks/rules/validation/abstract/RuleAddressList/RuleAddressList.sol | 5799cfc64c654417d2dc429ab3ff09a947858799 | +| ./mocks/rules/validation/abstract/RuleAddressList/RuleAddressList.sol | d79f80292cef8935e4773093dd9915684bb201fb | ### Contracts Description Table diff --git a/doc/schema/surya/surya_report/surya_report_RuleAddressListInternal.sol.md b/doc/schema/surya/surya_report/surya_report_RuleAddressListInternal.sol.md index 2d3e16da..8af1aafe 100644 --- a/doc/schema/surya/surya_report/surya_report_RuleAddressListInternal.sol.md +++ b/doc/schema/surya/surya_report/surya_report_RuleAddressListInternal.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./mocks/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol | 9d54010f5ae36e448576bd24a4c6e2ed71299ae9 | +| ./mocks/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol | 67133430b8916366bf8d6cce621a76fc06ff15f9 | ### Contracts Description Table diff --git a/doc/schema/surya/surya_report/surya_report_RuleAddressListInvariantStorage.sol.md b/doc/schema/surya/surya_report/surya_report_RuleAddressListInvariantStorage.sol.md index afb7b8a2..e18d7dea 100644 --- a/doc/schema/surya/surya_report/surya_report_RuleAddressListInvariantStorage.sol.md +++ b/doc/schema/surya/surya_report/surya_report_RuleAddressListInvariantStorage.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./mocks/rules/validation/abstract/RuleAddressList/invariantStorage/RuleAddressListInvariantStorage.sol | 0ea8e4e57796c8381d1f9cc530720684adcf5cbb | +| ./mocks/rules/validation/abstract/RuleAddressList/invariantStorage/RuleAddressListInvariantStorage.sol | f6290dab0a5474f36b10134749babd9ef656a859 | ### Contracts Description Table diff --git a/doc/schema/surya/surya_report/surya_report_RuleBlacklistInvariantStorage.sol.md b/doc/schema/surya/surya_report/surya_report_RuleBlacklistInvariantStorage.sol.md index ac35c6bd..0589b017 100644 --- a/doc/schema/surya/surya_report/surya_report_RuleBlacklistInvariantStorage.sol.md +++ b/doc/schema/surya/surya_report/surya_report_RuleBlacklistInvariantStorage.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./mocks/rules/validation/abstract/RuleAddressList/invariantStorage/RuleBlacklistInvariantStorage.sol | 61187193a501b8fe26b39ef326373bfe6425c907 | +| ./mocks/rules/validation/abstract/RuleAddressList/invariantStorage/RuleBlacklistInvariantStorage.sol | e9cefe89679a33a0dc72e5a631066fb39f5e1a6f | ### Contracts Description Table diff --git a/doc/schema/surya/surya_report/surya_report_RuleCommonInvariantStorage.sol.md b/doc/schema/surya/surya_report/surya_report_RuleCommonInvariantStorage.sol.md index 08f4f538..551e7ed1 100644 --- a/doc/schema/surya/surya_report/surya_report_RuleCommonInvariantStorage.sol.md +++ b/doc/schema/surya/surya_report/surya_report_RuleCommonInvariantStorage.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./mocks/rules/validation/abstract/RuleCommonInvariantStorage.sol | 94ed8593f8ee0f93864661ada681b83ca0a8c7e0 | +| ./mocks/rules/validation/abstract/RuleCommonInvariantStorage.sol | 5cb1001feebceaf4d1360dc663e8a14b82ffe3cc | ### Contracts Description Table diff --git a/doc/schema/surya/surya_report/surya_report_RuleConditionalTransferLightInvariantStorage.sol.md b/doc/schema/surya/surya_report/surya_report_RuleConditionalTransferLightInvariantStorage.sol.md index 8a5bf248..931ac599 100644 --- a/doc/schema/surya/surya_report/surya_report_RuleConditionalTransferLightInvariantStorage.sol.md +++ b/doc/schema/surya/surya_report/surya_report_RuleConditionalTransferLightInvariantStorage.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./mocks/rules/operation/abstract/RuleConditionalTransferLightInvariantStorage.sol | 4219a1d62f201226260a2598de2f4313e5257049 | +| ./mocks/rules/operation/abstract/RuleConditionalTransferLightInvariantStorage.sol | e27bdd811e577def6acc8ed5f55863c81591ef64 | ### Contracts Description Table diff --git a/doc/schema/surya/surya_report/surya_report_RuleConditionalTransferLightMock.sol.md b/doc/schema/surya/surya_report/surya_report_RuleConditionalTransferLightMock.sol.md index 78a2328f..d7c380c3 100644 --- a/doc/schema/surya/surya_report/surya_report_RuleConditionalTransferLightMock.sol.md +++ b/doc/schema/surya/surya_report/surya_report_RuleConditionalTransferLightMock.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./mocks/rules/operation/RuleConditionalTransferLightMock.sol | 1d6b8e8765e6de04eaa66f46b9f753f58e9a11de | +| ./mocks/rules/operation/RuleConditionalTransferLightMock.sol | 24061f4b8c7a78e6ea457fa036d79ad4d130bfaf | ### Contracts Description Table @@ -15,7 +15,7 @@ |:----------:|:-------------------:|:----------------:|:----------------:|:---------------:| | └ | **Function Name** | **Visibility** | **Mutability** | **Modifiers** | |||||| -| **RuleConditionalTransferLightMock** | Implementation | AccessControl, RuleConditionalTransferLightInvariantStorage, IRule ||| +| **RuleConditionalTransferLightMock** | Implementation | AccessControl, RuleConditionalTransferLightInvariantStorage, IRule, IRuleEngineERC1404 ||| | └ | | Public ❗️ | 🛑 |NO❗️ | | └ | canReturnTransferRestrictionCode | External ❗️ | |NO❗️ | | └ | messageForTransferRestriction | External ❗️ | |NO❗️ | diff --git a/doc/schema/surya/surya_report/surya_report_RuleEngine.sol.md b/doc/schema/surya/surya_report/surya_report_RuleEngine.sol.md index 77f6e2c9..c84457a4 100644 --- a/doc/schema/surya/surya_report/surya_report_RuleEngine.sol.md +++ b/doc/schema/surya/surya_report/surya_report_RuleEngine.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./deployment/RuleEngine.sol | 369509e7c8c3020b8898a8620a09cbeeddbc0aed | +| ./deployment/accessControl/RuleEngine.sol | 473eace2772720a5cf37a39e4d18fc0d2c71ac27 | ### Contracts Description Table @@ -15,17 +15,14 @@ |:----------:|:-------------------:|:----------------:|:----------------:|:---------------:| | └ | **Function Name** | **Visibility** | **Mutability** | **Modifiers** | |||||| -| **RuleEngine** | Implementation | ERC2771ModuleStandalone, RuleEngineBase, AccessControlEnumerable, ERC3643ComplianceRolesStorage, RulesManagementModuleRolesStorage ||| -| └ | | Public ❗️ | 🛑 | ERC2771ModuleStandalone | +| **RuleEngine** | Implementation | RuleEngineBase, AccessControlEnumerable, ERC3643ComplianceRolesStorage, RulesManagementModuleRolesStorage ||| +| └ | | Public ❗️ | 🛑 |NO❗️ | | └ | grantRole | Public ❗️ | 🛑 |NO❗️ | | └ | hasRole | Public ❗️ | |NO❗️ | | └ | supportsInterface | Public ❗️ | |NO❗️ | | └ | _onlyComplianceManager | Internal 🔒 | 🛑 | onlyRole | | └ | _onlyRulesManager | Internal 🔒 | 🛑 | onlyRole | | └ | _onlyRulesLimitManager | Internal 🔒 | 🛑 | onlyRole | -| └ | _msgSender | Internal 🔒 | | | -| └ | _msgData | Internal 🔒 | | | -| └ | _contextSuffixLength | Internal 🔒 | | | ### Legend diff --git a/doc/schema/surya/surya_report/surya_report_RuleEngine2771.sol.md b/doc/schema/surya/surya_report/surya_report_RuleEngine2771.sol.md new file mode 100644 index 00000000..414e8367 --- /dev/null +++ b/doc/schema/surya/surya_report/surya_report_RuleEngine2771.sol.md @@ -0,0 +1,30 @@ +## Sūrya's Description Report + +### Files Description Table + + +| File Name | SHA-1 Hash | +|-------------|--------------| +| ./deployment/accessControl/RuleEngine2771.sol | 4aecab6173fb0c2ba8bcdcf380433d39fed59124 | + + +### Contracts Description Table + + +| Contract | Type | Bases | | | +|:----------:|:-------------------:|:----------------:|:----------------:|:---------------:| +| └ | **Function Name** | **Visibility** | **Mutability** | **Modifiers** | +|||||| +| **RuleEngine2771** | Implementation | ERC2771ModuleStandalone, RuleEngine ||| +| └ | | Public ❗️ | 🛑 | ERC2771ModuleStandalone RuleEngine | +| └ | _msgSender | Internal 🔒 | | | +| └ | _msgData | Internal 🔒 | | | +| └ | _contextSuffixLength | Internal 🔒 | | | + + +### Legend + +| Symbol | Meaning | +|:--------:|-----------| +| 🛑 | Function can modify state | +| 💵 | Function is payable | diff --git a/doc/schema/surya/surya_report/surya_report_RuleEngineBase.sol.md b/doc/schema/surya/surya_report/surya_report_RuleEngineBase.sol.md index cd5e9dd3..fd840445 100644 --- a/doc/schema/surya/surya_report/surya_report_RuleEngineBase.sol.md +++ b/doc/schema/surya/surya_report/surya_report_RuleEngineBase.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./RuleEngineBase.sol | 47009acf96c5bff2b7eac02322c70fb8b3bfa8b3 | +| ./RuleEngineBase.sol | b3e23e67108b67eec5504c9d0eac81d10a43f669 | ### Contracts Description Table @@ -29,6 +29,8 @@ | └ | _detectTransferRestrictionFrom | Internal 🔒 | | | | └ | _messageForTransferRestriction | Internal 🔒 | | | | └ | _checkRule | Internal 🔒 | | | +| └ | _checkBindingTarget | Internal 🔒 | | | +| └ | _supportsRuleInterface | Internal 🔒 | | | | └ | _supportsRuleEngineBaseInterface | Internal 🔒 | | | diff --git a/doc/schema/surya/surya_report/surya_report_RuleEngineExposed.sol.md b/doc/schema/surya/surya_report/surya_report_RuleEngineExposed.sol.md index 312249cd..a24d8f95 100644 --- a/doc/schema/surya/surya_report/surya_report_RuleEngineExposed.sol.md +++ b/doc/schema/surya/surya_report/surya_report_RuleEngineExposed.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./mocks/RuleEngineExposed.sol | cd5640f094c401bbba4c560b21f9ac9c8644f281 | +| ./mocks/RuleEngineExposed.sol | 92b192621d7399c222d27d864752dc2b9cdb2754 | ### Contracts Description Table @@ -15,16 +15,16 @@ |:----------:|:-------------------:|:----------------:|:----------------:|:---------------:| | └ | **Function Name** | **Visibility** | **Mutability** | **Modifiers** | |||||| -| **RuleEngineExposed** | Implementation | RuleEngine ||| -| └ | | Public ❗️ | 🛑 | RuleEngine | +| **RuleEngine2771Exposed** | Implementation | RuleEngine2771 ||| +| └ | | Public ❗️ | 🛑 | RuleEngine2771 | | └ | exposedMsgData | External ❗️ | |NO❗️ | |||||| -| **RuleEngineOwnableExposed** | Implementation | RuleEngineOwnable ||| -| └ | | Public ❗️ | 🛑 | RuleEngineOwnable | +| **RuleEngineOwnable2771Exposed** | Implementation | RuleEngineOwnable2771 ||| +| └ | | Public ❗️ | 🛑 | RuleEngineOwnable2771 | | └ | exposedMsgData | External ❗️ | |NO❗️ | |||||| -| **RuleEngineOwnable2StepExposed** | Implementation | RuleEngineOwnable2Step ||| -| └ | | Public ❗️ | 🛑 | RuleEngineOwnable2Step | +| **RuleEngineOwnable2Step2771Exposed** | Implementation | RuleEngineOwnable2Step2771 ||| +| └ | | Public ❗️ | 🛑 | RuleEngineOwnable2Step2771 | | └ | exposedMsgData | External ❗️ | |NO❗️ | diff --git a/doc/schema/surya/surya_report/surya_report_RuleEngineInvariantStorage.sol.md b/doc/schema/surya/surya_report/surya_report_RuleEngineInvariantStorage.sol.md index 41b1b2cf..dd5895be 100644 --- a/doc/schema/surya/surya_report/surya_report_RuleEngineInvariantStorage.sol.md +++ b/doc/schema/surya/surya_report/surya_report_RuleEngineInvariantStorage.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./modules/library/RuleEngineInvariantStorage.sol | 7763d6c1b2dbfe6a1827e4c124e35e4ff3fbc874 | +| ./modules/library/RuleEngineInvariantStorage.sol | f5ff447a04a7948fefd0256ccb83429fb5871036 | ### Contracts Description Table diff --git a/doc/schema/surya/surya_report/surya_report_RuleEngineOwnable.sol.md b/doc/schema/surya/surya_report/surya_report_RuleEngineOwnable.sol.md index 9c16e0ce..94172875 100644 --- a/doc/schema/surya/surya_report/surya_report_RuleEngineOwnable.sol.md +++ b/doc/schema/surya/surya_report/surya_report_RuleEngineOwnable.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./deployment/RuleEngineOwnable.sol | 0aefac400a5da4ebf228f8b9b788cb1d820be5c9 | +| ./deployment/ownable/RuleEngineOwnable.sol | 444e6f19579bc44b24dc32bdad4476c0f7bfa4cc | ### Contracts Description Table @@ -21,9 +21,6 @@ | └ | _onlyRulesManager | Internal 🔒 | 🛑 | onlyOwner | | └ | _onlyRulesLimitManager | Internal 🔒 | 🛑 | onlyOwner | | └ | _onlyComplianceManager | Internal 🔒 | 🛑 | onlyOwner | -| └ | _msgSender | Internal 🔒 | | | -| └ | _msgData | Internal 🔒 | | | -| └ | _contextSuffixLength | Internal 🔒 | | | ### Legend diff --git a/doc/schema/surya/surya_report/surya_report_RuleEngineOwnable2771.sol.md b/doc/schema/surya/surya_report/surya_report_RuleEngineOwnable2771.sol.md new file mode 100644 index 00000000..c40714f6 --- /dev/null +++ b/doc/schema/surya/surya_report/surya_report_RuleEngineOwnable2771.sol.md @@ -0,0 +1,30 @@ +## Sūrya's Description Report + +### Files Description Table + + +| File Name | SHA-1 Hash | +|-------------|--------------| +| ./deployment/ownable/RuleEngineOwnable2771.sol | 6d4d60005fffc89fbb99cc920324385ac7c2bcb5 | + + +### Contracts Description Table + + +| Contract | Type | Bases | | | +|:----------:|:-------------------:|:----------------:|:----------------:|:---------------:| +| └ | **Function Name** | **Visibility** | **Mutability** | **Modifiers** | +|||||| +| **RuleEngineOwnable2771** | Implementation | ERC2771ModuleStandalone, RuleEngineOwnable ||| +| └ | | Public ❗️ | 🛑 | ERC2771ModuleStandalone RuleEngineOwnable | +| └ | _msgSender | Internal 🔒 | | | +| └ | _msgData | Internal 🔒 | | | +| └ | _contextSuffixLength | Internal 🔒 | | | + + +### Legend + +| Symbol | Meaning | +|:--------:|-----------| +| 🛑 | Function can modify state | +| 💵 | Function is payable | diff --git a/doc/schema/surya/surya_report/surya_report_RuleEngineOwnable2Step.sol.md b/doc/schema/surya/surya_report/surya_report_RuleEngineOwnable2Step.sol.md index 5499b0aa..0391714d 100644 --- a/doc/schema/surya/surya_report/surya_report_RuleEngineOwnable2Step.sol.md +++ b/doc/schema/surya/surya_report/surya_report_RuleEngineOwnable2Step.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./deployment/RuleEngineOwnable2Step.sol | f4789549d0abc15201d8503c2295f13de54ff336 | +| ./deployment/ownable/RuleEngineOwnable2Step.sol | 82975ed5f799da2ddd0071c884ca09d8458a86b4 | ### Contracts Description Table @@ -18,13 +18,11 @@ | **RuleEngineOwnable2Step** | Implementation | RuleEngineOwnableShared, Ownable2Step ||| | └ | | Public ❗️ | 🛑 | RuleEngineOwnableShared Ownable | | └ | transferOwnership | Public ❗️ | 🛑 | onlyOwner | +| └ | acceptOwnership | Public ❗️ | 🛑 |NO❗️ | | └ | supportsInterface | Public ❗️ | |NO❗️ | | └ | _onlyRulesManager | Internal 🔒 | 🛑 | onlyOwner | | └ | _onlyRulesLimitManager | Internal 🔒 | 🛑 | onlyOwner | | └ | _onlyComplianceManager | Internal 🔒 | 🛑 | onlyOwner | -| └ | _msgSender | Internal 🔒 | | | -| └ | _msgData | Internal 🔒 | | | -| └ | _contextSuffixLength | Internal 🔒 | | | ### Legend diff --git a/doc/schema/surya/surya_report/surya_report_RuleEngineOwnable2Step2771.sol.md b/doc/schema/surya/surya_report/surya_report_RuleEngineOwnable2Step2771.sol.md new file mode 100644 index 00000000..be272a94 --- /dev/null +++ b/doc/schema/surya/surya_report/surya_report_RuleEngineOwnable2Step2771.sol.md @@ -0,0 +1,30 @@ +## Sūrya's Description Report + +### Files Description Table + + +| File Name | SHA-1 Hash | +|-------------|--------------| +| ./deployment/ownable/RuleEngineOwnable2Step2771.sol | 3db536eaa5fd2eb3c53386b22fc2cf1fe931655b | + + +### Contracts Description Table + + +| Contract | Type | Bases | | | +|:----------:|:-------------------:|:----------------:|:----------------:|:---------------:| +| └ | **Function Name** | **Visibility** | **Mutability** | **Modifiers** | +|||||| +| **RuleEngineOwnable2Step2771** | Implementation | ERC2771ModuleStandalone, RuleEngineOwnable2Step ||| +| └ | | Public ❗️ | 🛑 | ERC2771ModuleStandalone RuleEngineOwnable2Step | +| └ | _msgSender | Internal 🔒 | | | +| └ | _msgData | Internal 🔒 | | | +| └ | _contextSuffixLength | Internal 🔒 | | | + + +### Legend + +| Symbol | Meaning | +|:--------:|-----------| +| 🛑 | Function can modify state | +| 💵 | Function is payable | diff --git a/doc/schema/surya/surya_report/surya_report_RuleEngineOwnableShared.sol.md b/doc/schema/surya/surya_report/surya_report_RuleEngineOwnableShared.sol.md index 7fa29144..a20e1df6 100644 --- a/doc/schema/surya/surya_report/surya_report_RuleEngineOwnableShared.sol.md +++ b/doc/schema/surya/surya_report/surya_report_RuleEngineOwnableShared.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./RuleEngineOwnableShared.sol | e2711fe0ef1478ab3155ae38e940b315f66d61ae | +| ./RuleEngineOwnableShared.sol | fc33c31c88e181401567157bcd994351a11a54a6 | ### Contracts Description Table @@ -15,13 +15,10 @@ |:----------:|:-------------------:|:----------------:|:----------------:|:---------------:| | └ | **Function Name** | **Visibility** | **Mutability** | **Modifiers** | |||||| -| **RuleEngineOwnableShared** | Implementation | ERC2771ModuleStandalone, RuleEngineBase, ERC165 ||| -| └ | | Public ❗️ | 🛑 | ERC2771ModuleStandalone | +| **RuleEngineOwnableShared** | Implementation | RuleEngineBase, ERC165 ||| +| └ | | Public ❗️ | 🛑 |NO❗️ | | └ | supportsInterface | Public ❗️ | |NO❗️ | | └ | _checkOwnershipTransferTarget | Internal 🔒 | | | -| └ | _msgSender | Internal 🔒 | | | -| └ | _msgData | Internal 🔒 | | | -| └ | _contextSuffixLength | Internal 🔒 | | | ### Legend diff --git a/doc/schema/surya/surya_report/surya_report_RuleInterfaceId.sol.md b/doc/schema/surya/surya_report/surya_report_RuleInterfaceId.sol.md index d410ddff..365ccf05 100644 --- a/doc/schema/surya/surya_report/surya_report_RuleInterfaceId.sol.md +++ b/doc/schema/surya/surya_report/surya_report_RuleInterfaceId.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./modules/library/RuleInterfaceId.sol | 65c302818900904547afb065eb4fb5fb6a13d5af | +| ./modules/library/RuleInterfaceId.sol | a5b057d414d0a2c838d7a759a4aedeb75947761e | ### Contracts Description Table diff --git a/doc/schema/surya/surya_report/surya_report_RuleInvalidMock.sol.md b/doc/schema/surya/surya_report/surya_report_RuleInvalidMock.sol.md index 6d46baa2..d3d93c19 100644 --- a/doc/schema/surya/surya_report/surya_report_RuleInvalidMock.sol.md +++ b/doc/schema/surya/surya_report/surya_report_RuleInvalidMock.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./mocks/RuleInvalidMock.sol | 7889ad3225dd52ba620d695d5ef33a1fb3b6fd8a | +| ./mocks/RuleInvalidMock.sol | 33afde0964da8f4ba964b1316ee62349313bac39 | ### Contracts Description Table diff --git a/doc/schema/surya/surya_report/surya_report_RuleMintAllowanceInvariantStorage.sol.md b/doc/schema/surya/surya_report/surya_report_RuleMintAllowanceInvariantStorage.sol.md index dab20334..bab9c642 100644 --- a/doc/schema/surya/surya_report/surya_report_RuleMintAllowanceInvariantStorage.sol.md +++ b/doc/schema/surya/surya_report/surya_report_RuleMintAllowanceInvariantStorage.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./mocks/rules/operation/abstract/RuleMintAllowanceInvariantStorage.sol | 0f5aa4e3b36ede206ea44ee8aa13158e24d5a792 | +| ./mocks/rules/operation/abstract/RuleMintAllowanceInvariantStorage.sol | bdfdd252f3082a463a418f4828966f226466364e | ### Contracts Description Table diff --git a/doc/schema/surya/surya_report/surya_report_RuleMintAllowanceMock.sol.md b/doc/schema/surya/surya_report/surya_report_RuleMintAllowanceMock.sol.md index 4773d8d7..ebd63589 100644 --- a/doc/schema/surya/surya_report/surya_report_RuleMintAllowanceMock.sol.md +++ b/doc/schema/surya/surya_report/surya_report_RuleMintAllowanceMock.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./mocks/rules/operation/RuleMintAllowanceMock.sol | 8624614de65b7b571307995c38ac3911f2355e2f | +| ./mocks/rules/operation/RuleMintAllowanceMock.sol | cda8a7b400c1f35e7aaa804fe235dcdc9e8f3707 | ### Contracts Description Table @@ -15,7 +15,7 @@ |:----------:|:-------------------:|:----------------:|:----------------:|:---------------:| | └ | **Function Name** | **Visibility** | **Mutability** | **Modifiers** | |||||| -| **RuleMintAllowanceMock** | Implementation | AccessControl, RuleMintAllowanceInvariantStorage, IRule ||| +| **RuleMintAllowanceMock** | Implementation | AccessControl, RuleMintAllowanceInvariantStorage, IRule, IRuleEngineERC1404 ||| | └ | | Public ❗️ | 🛑 |NO❗️ | | └ | setMintAllowance | External ❗️ | 🛑 | onlyRole | | └ | canReturnTransferRestrictionCode | External ❗️ | |NO❗️ | diff --git a/doc/schema/surya/surya_report/surya_report_RuleOperationRevertMock.sol.md b/doc/schema/surya/surya_report/surya_report_RuleOperationRevertMock.sol.md index 7ea25b7c..b56749d1 100644 --- a/doc/schema/surya/surya_report/surya_report_RuleOperationRevertMock.sol.md +++ b/doc/schema/surya/surya_report/surya_report_RuleOperationRevertMock.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./mocks/rules/operation/RuleOperationRevertMock.sol | 9ad9b2b293ec7c02b687f2d76565a22b47c90c0d | +| ./mocks/rules/operation/RuleOperationRevertMock.sol | 29ecd636a3fff32f5db1116571e8233e312e0ee1 | ### Contracts Description Table @@ -15,7 +15,7 @@ |:----------:|:-------------------:|:----------------:|:----------------:|:---------------:| | └ | **Function Name** | **Visibility** | **Mutability** | **Modifiers** | |||||| -| **RuleOperationRevertMock** | Implementation | AccessControl, IRule, RuleCommonInvariantStorage ||| +| **RuleOperationRevertMock** | Implementation | AccessControl, IRule, IRuleEngineERC1404, RuleCommonInvariantStorage ||| | └ | canReturnTransferRestrictionCode | External ❗️ | |NO❗️ | | └ | messageForTransferRestriction | External ❗️ | |NO❗️ | | └ | supportsInterface | Public ❗️ | |NO❗️ | diff --git a/doc/schema/surya/surya_report/surya_report_RuleWhitelistCommon.sol.md b/doc/schema/surya/surya_report/surya_report_RuleWhitelistCommon.sol.md index be16b0dc..9ba5777a 100644 --- a/doc/schema/surya/surya_report/surya_report_RuleWhitelistCommon.sol.md +++ b/doc/schema/surya/surya_report/surya_report_RuleWhitelistCommon.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./mocks/rules/validation/abstract/RuleWhitelistCommon.sol | 87e2063dfdebd9dfa686ee271223b9c42983c7f0 | +| ./mocks/rules/validation/abstract/RuleWhitelistCommon.sol | a1f6693b4bc67b41801e583c86dd6fd21f3e5222 | ### Contracts Description Table diff --git a/doc/schema/surya/surya_report/surya_report_RuleWhitelistInvariantStorage.sol.md b/doc/schema/surya/surya_report/surya_report_RuleWhitelistInvariantStorage.sol.md index e63935a2..faf2f10c 100644 --- a/doc/schema/surya/surya_report/surya_report_RuleWhitelistInvariantStorage.sol.md +++ b/doc/schema/surya/surya_report/surya_report_RuleWhitelistInvariantStorage.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./mocks/rules/validation/abstract/RuleAddressList/invariantStorage/RuleWhitelistInvariantStorage.sol | 7a738ca2d11b8167a281c97a606db4269c64dcdb | +| ./mocks/rules/validation/abstract/RuleAddressList/invariantStorage/RuleWhitelistInvariantStorage.sol | 3019acfec585fd2ab8ffb8f7177b17c49837208f | ### Contracts Description Table diff --git a/doc/schema/surya/surya_report/surya_report_RuleWhitelistMock.sol.md b/doc/schema/surya/surya_report/surya_report_RuleWhitelistMock.sol.md index 907dc834..f7f09518 100644 --- a/doc/schema/surya/surya_report/surya_report_RuleWhitelistMock.sol.md +++ b/doc/schema/surya/surya_report/surya_report_RuleWhitelistMock.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./mocks/rules/validation/RuleWhitelistMock.sol | 269a711aa637cfd9640a7cbb83a5d34c963c1d17 | +| ./mocks/rules/validation/RuleWhitelistMock.sol | 5fcab0ff3605e97ef5212f320b0d138902a97e62 | ### Contracts Description Table @@ -15,7 +15,7 @@ |:----------:|:-------------------:|:----------------:|:----------------:|:---------------:| | └ | **Function Name** | **Visibility** | **Mutability** | **Modifiers** | |||||| -| **RuleWhitelistMock** | Implementation | RuleAddressList, RuleWhitelistCommon ||| +| **RuleWhitelistMock** | Implementation | RuleAddressList, RuleWhitelistCommon, IRuleEngineERC1404 ||| | └ | | Public ❗️ | 🛑 | RuleAddressList | | └ | transferred | Public ❗️ | 🛑 |NO❗️ | | └ | transferred | Public ❗️ | 🛑 |NO❗️ | diff --git a/doc/schema/surya/surya_report/surya_report_RulesManagementModule.sol.md b/doc/schema/surya/surya_report/surya_report_RulesManagementModule.sol.md index 155be60a..6a1ae628 100644 --- a/doc/schema/surya/surya_report/surya_report_RulesManagementModule.sol.md +++ b/doc/schema/surya/surya_report/surya_report_RulesManagementModule.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./modules/RulesManagementModule.sol | f382772b9cd31d5d61f03a4f3e6804cd4896e9c5 | +| ./modules/RulesManagementModule.sol | f17ba929cb0fc0cb1dfeccdd93b4ee412dce4050 | ### Contracts Description Table diff --git a/doc/schema/surya/surya_report/surya_report_RulesManagementModuleInvariantStorage.sol.md b/doc/schema/surya/surya_report/surya_report_RulesManagementModuleInvariantStorage.sol.md index 272be3fb..9c05719d 100644 --- a/doc/schema/surya/surya_report/surya_report_RulesManagementModuleInvariantStorage.sol.md +++ b/doc/schema/surya/surya_report/surya_report_RulesManagementModuleInvariantStorage.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./modules/library/RulesManagementModuleInvariantStorage.sol | 6c314c21aaecc7e2bbbaec978f622774364d65c0 | +| ./modules/library/RulesManagementModuleInvariantStorage.sol | 7ba38edd22df8ab642508f15c89ac3fe5a0796c0 | ### Contracts Description Table diff --git a/doc/schema/surya/surya_report/surya_report_RulesManagementModuleRolesStorage.sol.md b/doc/schema/surya/surya_report/surya_report_RulesManagementModuleRolesStorage.sol.md index d1459144..8ca1956b 100644 --- a/doc/schema/surya/surya_report/surya_report_RulesManagementModuleRolesStorage.sol.md +++ b/doc/schema/surya/surya_report/surya_report_RulesManagementModuleRolesStorage.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./modules/library/RulesManagementModuleRolesStorage.sol | d60ca17bf8fd97d6904966f713e4613ce4d8e3c5 | +| ./modules/library/RulesManagementModuleRolesStorage.sol | 087ccf16873a55d830bb4fde7296620b92f4cf73 | ### Contracts Description Table diff --git a/doc/schema/surya/surya_report/surya_report_TokenBindingExtendedModule.sol.md b/doc/schema/surya/surya_report/surya_report_TokenBindingExtendedModule.sol.md index f8385a18..d819276b 100644 --- a/doc/schema/surya/surya_report/surya_report_TokenBindingExtendedModule.sol.md +++ b/doc/schema/surya/surya_report/surya_report_TokenBindingExtendedModule.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./modules/TokenBindingExtendedModule.sol | d04d9b119b3a34f264d56830a6f41e57d9bc11de | +| ./modules/TokenBindingExtendedModule.sol | c0f9b420d08f54a7fc4c133f7e3a5d336b991710 | ### Contracts Description Table @@ -22,6 +22,8 @@ | └ | setTokenSelfBindingApprovalBatch | Public ❗️ | 🛑 | onlyTokenBindingManager | | └ | isTokenSelfBindingApproved | Public ❗️ | |NO❗️ | | └ | getTokenBounds | Public ❗️ | |NO❗️ | +| └ | _unbindToken | Internal 🔒 | 🛑 | | +| └ | _setTokenSelfBindingApproval | Internal 🔒 | 🛑 | | | └ | _authorizeTokenBindingChange | Internal 🔒 | 🛑 | | diff --git a/doc/schema/surya/surya_report/surya_report_TokenBindingModule.sol.md b/doc/schema/surya/surya_report/surya_report_TokenBindingModule.sol.md index 5745f0a7..549b19bd 100644 --- a/doc/schema/surya/surya_report/surya_report_TokenBindingModule.sol.md +++ b/doc/schema/surya/surya_report/surya_report_TokenBindingModule.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./modules/TokenBindingModule.sol | db8a2e23dc811ccc424861b398b305fb425b3e6c | +| ./modules/TokenBindingModule.sol | 290217014db5b97af70da677d27a410d8bff13a8 | ### Contracts Description Table @@ -20,6 +20,7 @@ | └ | unbindToken | Public ❗️ | 🛑 |NO❗️ | | └ | isTokenBound | Public ❗️ | |NO❗️ | | └ | _bindToken | Internal 🔒 | 🛑 | | +| └ | _checkBindingTarget | Internal 🔒 | | | | └ | _unbindToken | Internal 🔒 | 🛑 | | | └ | _authorizeTokenBindingChange | Internal 🔒 | 🛑 | | | └ | _onlyTokenBindingManager | Internal 🔒 | 🛑 | | diff --git a/doc/schema/surya/surya_report/surya_report_TokenBindingModuleInvariantStorage.sol.md b/doc/schema/surya/surya_report/surya_report_TokenBindingModuleInvariantStorage.sol.md index 1688fd9c..2e354298 100644 --- a/doc/schema/surya/surya_report/surya_report_TokenBindingModuleInvariantStorage.sol.md +++ b/doc/schema/surya/surya_report/surya_report_TokenBindingModuleInvariantStorage.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./modules/library/TokenBindingModuleInvariantStorage.sol | c1ae50c8c8acc84cdf06c1ef436e4d1bf03b554b | +| ./modules/library/TokenBindingModuleInvariantStorage.sol | 28e95d396b938d49126505ee8ee1bfcff1920c13 | ### Contracts Description Table diff --git a/doc/schema/surya/surya_report/surya_report_TokenBindingStandaloneMock.sol.md b/doc/schema/surya/surya_report/surya_report_TokenBindingStandaloneMock.sol.md index d293e288..f6aa1466 100644 --- a/doc/schema/surya/surya_report/surya_report_TokenBindingStandaloneMock.sol.md +++ b/doc/schema/surya/surya_report/surya_report_TokenBindingStandaloneMock.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./mocks/TokenBindingStandaloneMock.sol | 69481db2ed47a2c69e7263f690fc92c9aa442070 | +| ./mocks/TokenBindingStandaloneMock.sol | d3110a7d2011eb51de3c7b3dcc8d7b89af563e29 | ### Contracts Description Table diff --git a/doc/schema/surya/surya_report/surya_report_VersionModule.sol.md b/doc/schema/surya/surya_report/surya_report_VersionModule.sol.md index c649011d..fc912882 100644 --- a/doc/schema/surya/surya_report/surya_report_VersionModule.sol.md +++ b/doc/schema/surya/surya_report/surya_report_VersionModule.sol.md @@ -5,7 +5,7 @@ | File Name | SHA-1 Hash | |-------------|--------------| -| ./modules/VersionModule.sol | 1929b5ea873610ac4e76786ed6339e0e601a5e64 | +| ./modules/VersionModule.sol | 4b563bd6fb3a910a9a9da60e35ecb001080f3d35 | ### Contracts Description Table diff --git a/doc/script/convert_links_for_pdf.sh b/doc/script/convert_links_for_pdf.sh index 48655d79..24ac8dca 100755 --- a/doc/script/convert_links_for_pdf.sh +++ b/doc/script/convert_links_for_pdf.sh @@ -8,28 +8,79 @@ set -e if [ -z "$1" ]; then echo "Usage: $0 [input-file] [output-file]" echo "" + echo "The release link may point at the repository root or at the input file's" + echo "own directory; the missing part is derived from where the file sits." + echo "The output defaults to README_UPDATE.md beside the input file, so the" + echo "image links it keeps relative still resolve." + echo "" echo "Example:" echo " $0 https://github.com/CMTA/CMTAT/blob/v3.0.0" - echo " $0 https://github.com/CMTA/CMTAT/blob/v3.0.0 README.md README_UPDATE.md" + echo " $0 https://github.com/CMTA/CMTAT/blob/v3.0.0/doc" + echo " $0 https://github.com/CMTA/CMTAT/blob/v3.0.0 ../README.md README_UPDATE.md" exit 1 fi GITHUB_LINK="${1%/}" # Remove trailing slash if present -# Defaults to the full documentation (doc/README.md), not the short root overview. -INPUT_FILE="${2:-../README.md}" -OUTPUT_FILE="${3:-README_UPDATE.md}" + +INPUT_FILE="${2:-../README.md}" # doc/README.md, the full reference (the root README is a short summary) if [ ! -f "$INPUT_FILE" ]; then echo "Error: Input file '$INPUT_FILE' not found" exit 1 fi +# The links in the input file are relative to the file, so the base URL has to be +# too. Accept either form -- the repository root (".../blob/") or the file's +# own directory (".../blob//doc") -- and derive whichever half is missing +# from the file's path inside the repository. Passing the root form used to +# rewrite every "./" link one directory too high, silently: doc/README.md's +# "./technical/x.md" became ".../blob//technical/x.md", a 404 in the PDF. +INPUT_DIR=$(cd "$(dirname "$INPUT_FILE")" && pwd) +REPO_ROOT=$(git -C "$INPUT_DIR" rev-parse --show-toplevel 2>/dev/null || true) +REL_DIR="" +if [ -n "$REPO_ROOT" ]; then + REL_DIR="${INPUT_DIR#"$REPO_ROOT"}" + REL_DIR="${REL_DIR#/}" # "doc", or "" when the input file is at the root +fi + +if [ -n "$REL_DIR" ] && [ "${GITHUB_LINK%/$REL_DIR}" = "$GITHUB_LINK" ]; then + GITHUB_LINK="$GITHUB_LINK/$REL_DIR" +fi + +# Base URL for the parent of the input file's directory, used by Step 0 to +# rewrite "../path" links -- how doc/README.md must reference repository-root +# siblings such as test/ and src/. Empty when the input file is itself at the +# root, where "../" points outside the repository and cannot be expressed. +GITHUB_LINK_PARENT="" +if [ -n "$REL_DIR" ]; then + GITHUB_LINK_PARENT="${GITHUB_LINK%/*}" +fi + +# Default the output to the input file's own directory, not the caller's working +# directory. The conversion leaves image links relative on purpose, so the +# converted file only renders correctly from where the original sits: written +# anywhere else, doc/README.md's "./schema/x.png" points at nothing. +OUTPUT_FILE="${3:-$INPUT_DIR/README_UPDATE.md}" + # Create a temporary file TMP_FILE=$(mktemp) cp "$INPUT_FILE" "$TMP_FILE" # Use a placeholder to avoid sed escaping issues PLACEHOLDER="__GITHUB_LINK__" +PLACEHOLDER_PARENT="__GITHUB_LINK_PARENT__" + +# Step 0: convert parent-relative links [text](../...) before Step 1, which only +# recognizes the "./" form and would leave these relative and dead in the PDF. +if grep -qE '\]\(\.\./[^)]+\)' "$TMP_FILE"; then + if [ -z "$GITHUB_LINK_PARENT" ]; then + echo "Error: '$INPUT_FILE' contains '../' links, which point outside the repository from this location." >&2 + echo "Rewrite them as absolute URLs, or generate the PDF from a file in a subdirectory such as doc/." >&2 + rm -f "$TMP_FILE" + exit 1 + fi + sed -i -E "s|\[([^]]+)\]\(\.\./([^)]+)\)|[\1]($PLACEHOLDER_PARENT/\2)|g" "$TMP_FILE" +fi # Step 1: Convert ALL relative links [text](./...) to placeholder sed -i -E "s|\[([^]]+)\]\(\./([^)]+)\)|[\1]($PLACEHOLDER/\2)|g" "$TMP_FILE" @@ -37,9 +88,11 @@ sed -i -E "s|\[([^]]+)\]\(\./([^)]+)\)|[\1]($PLACEHOLDER/\2)|g" "$TMP_FILE" # Step 2: Restore image links back to relative (images render inline in PDF) for ext in png jpg jpeg gif svg ico webp bmp tiff; do sed -i -E "s|\[([^]]+)\]\($PLACEHOLDER/([^)]+\.$ext)\)|[\1](./\2)|gi" "$TMP_FILE" + sed -i -E "s|\[([^]]+)\]\($PLACEHOLDER_PARENT/([^)]+\.$ext)\)|[\1](../\2)|gi" "$TMP_FILE" done -# Step 3: Replace placeholder with actual GitHub link +# Step 3: Replace placeholders with actual GitHub links (parent first) +sed -i "s|$PLACEHOLDER_PARENT|$GITHUB_LINK_PARENT|g" "$TMP_FILE" sed -i "s|$PLACEHOLDER|$GITHUB_LINK|g" "$TMP_FILE" mv "$TMP_FILE" "$OUTPUT_FILE" diff --git a/doc/script/convert_links_for_pdf_root.sh b/doc/script/convert_links_for_pdf_root.sh new file mode 100755 index 00000000..9bd89aad --- /dev/null +++ b/doc/script/convert_links_for_pdf_root.sh @@ -0,0 +1,34 @@ +#!/bin/bash + +# Same conversion as convert_links_for_pdf.sh, applied to the root README.md +# (the short summary) instead of doc/README.md (the full reference). +# +# It differs only in its default input, so it delegates rather than duplicating: +# - input : the repository's root README.md +# The output follows the input's directory, which the other script already does, +# so it needs no default here. Link rewriting, image handling and the base-URL +# derivation all stay there too; change behaviour there and both entry points +# follow. + +set -e + +SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)" +CONVERT="$SCRIPT_DIR/convert_links_for_pdf.sh" +REPO_ROOT="$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null || (cd "$SCRIPT_DIR/../.." && pwd))" + +if [ -z "$1" ]; then + echo "Usage: $0 [input-file] [output-file]" + echo "" + echo "Converts the root README.md. For doc/README.md use convert_links_for_pdf.sh." + echo "" + echo "Example:" + echo " $0 https://github.com/CMTA/Rules/blob/v0.6.0" + exit 1 +fi + +if [ ! -x "$CONVERT" ]; then + echo "Error: '$CONVERT' not found or not executable" + exit 1 +fi + +exec "$CONVERT" "$1" "${2:-$REPO_ROOT/README.md}" "${3:-}" diff --git a/doc/script/script_sol2uml.sh b/doc/script/script_sol2uml.sh index cf3f924f..740678a5 100755 --- a/doc/script/script_sol2uml.sh +++ b/doc/script/script_sol2uml.sh @@ -11,12 +11,18 @@ set -euo pipefail cd "$(dirname "$0")/../../" DIR_OUT="doc/schema/sol2uml" mkdir -p "$DIR_OUT" +TMP_DIR="$(mktemp -d)" +trap 'rm -rf "$TMP_DIR"' EXIT +command -v dot >/dev/null || { echo "Graphviz dot is required" >&2; exit 1; } # "||" DIAGRAMS=( - "RuleEngineUML|src/deployment/RuleEngine.sol|RuleEngine" - "RuleEngineOwnableUML|src/deployment/RuleEngineOwnable.sol|RuleEngineOwnable" - "RuleEngineOwnable2StepUML|src/deployment/RuleEngineOwnable2Step.sol|RuleEngineOwnable2Step" + "RuleEngineUML|src/deployment/accessControl/RuleEngine.sol|RuleEngine" + "RuleEngineOwnableUML|src/deployment/ownable/RuleEngineOwnable.sol|RuleEngineOwnable" + "RuleEngineOwnable2StepUML|src/deployment/ownable/RuleEngineOwnable2Step.sol|RuleEngineOwnable2Step" + "RuleEngine2771UML|src/deployment/accessControl/RuleEngine2771.sol|RuleEngine2771" + "RuleEngineOwnable2771UML|src/deployment/ownable/RuleEngineOwnable2771.sol|RuleEngineOwnable2771" + "RuleEngineOwnable2Step2771UML|src/deployment/ownable/RuleEngineOwnable2Step2771.sol|RuleEngineOwnable2Step2771" "RuleEngineBaseUML|src/RuleEngineBase.sol|RuleEngineBase" "VersionModuleUML|src/modules/VersionModule.sol|VersionModule" "RuleManagementModuleUML|src/modules/RulesManagementModule.sol|RulesManagementModule" @@ -24,6 +30,7 @@ DIAGRAMS=( "TokenBindingExtendedModuleUML|src/modules/TokenBindingExtendedModule.sol|TokenBindingExtendedModule" "ERC3643ComplianceModuleUML|src/modules/ERC3643ComplianceModule.sol|ERC3643ComplianceModule" "ERC3643ComplianceExtendedModuleUML|src/modules/ERC3643ComplianceExtendedModule.sol|ERC3643ComplianceExtendedModule" + "IRuleUML|src/interfaces/IRule.sol|IRule" "IRuleEngineUML|lib/CMTAT/contracts/interfaces/engine/IRuleEngine.sol|IRuleEngine" "IERC1404UML|lib/CMTAT/contracts/interfaces/tokenization/draft-IERC1404.sol|IERC1404" "IERC1404ExtendUML|lib/CMTAT/contracts/interfaces/tokenization/draft-IERC1404.sol|IERC1404Extend" @@ -38,5 +45,9 @@ for entry in "${DIAGRAMS[@]}"; do echo "Missing source: $source (submodule not initialized?)" >&2 exit 1 fi - npx sol2uml class "$source" -b "$contract" -d 0 -f png -o "${DIR_OUT}/${image}.png" + # sol2uml renders PNG through a headless Chrome (puppeteer), which cannot start where unprivileged user + # namespaces are disabled (Ubuntu 23.10+ AppArmor: "No usable sandbox"). Emit Graphviz dot instead and + # render it with dot, the same engine sol2uml uses; 96 dpi matches sol2uml's own PNG scale. + npx sol2uml class "$source" -b "$contract" -d 0 -f dot -o "${TMP_DIR}/${image}.dot" + dot -Tpng -Gdpi=96 "${TMP_DIR}/${image}.dot" -o "${DIR_OUT}/${image}.png" done diff --git a/doc/security/audits/AUDIT_OVERVIEW.md b/doc/security/audits/AUDIT_OVERVIEW.md index dfb7cfa9..c7e76211 100644 --- a/doc/security/audits/AUDIT_OVERVIEW.md +++ b/doc/security/audits/AUDIT_OVERVIEW.md @@ -7,8 +7,8 @@ This is an *overview of analyses*. For vulnerability reporting, see | | | |---|---| -| **Current version** | v3.0.0-rc6 | -| **Compiler** | solc 0.8.36, EVM Prague, optimizer on (200 runs) | +| **Current version** | v3.0.0-rc7 | +| **Compiler** | solc 0.8.37, EVM Osaka, optimizer on (200 runs) | | **Audited?** | **No.** v1.0.2 was audited by ABDK in March 2022; the 3.0.0 line has not been audited. | ## Scope @@ -25,6 +25,9 @@ concern a mock are labelled as such and do not apply to production deployments. | Analysis | Version | Report | Assessment | |---|---|---|---| +| Slither | v3.0.0-rc7 | [slither-report.md](./tools/v3.0.0-rc7/slither-report.md) | [feedback](./tools/v3.0.0-rc7/slither-report-feedback.md) | +| Aderyn | v3.0.0-rc7 | [aderyn-report.md](./tools/v3.0.0-rc7/aderyn-report.md) | [feedback](./tools/v3.0.0-rc7/aderyn-report-feedback.md) | +| Code-quality review (incl. tests, two passes) | v3.0.0-rc7 | [CLAUDE_ANALYSIS.md](./tools/v3.0.0-rc7/CLAUDE_ANALYSIS.md) | — | | Slither | v3.0.0-rc6 | [slither-report.md](./tools/v3.0.0-rc6/slither-report.md) | [feedback](./tools/v3.0.0-rc6/slither-report-feedback.md) | | Aderyn | v3.0.0-rc6 | [aderyn-report.md](./tools/v3.0.0-rc6/aderyn-report.md) | [feedback](./tools/v3.0.0-rc6/aderyn-report-feedback.md) | | Code-quality review | v3.0.0-rc6 | [CLAUDE_ANALYSIS.md](./tools/v3.0.0-rc6/CLAUDE_ANALYSIS.md) | — | @@ -37,12 +40,12 @@ concern a mock are labelled as such and do not apply to production deployments. | Nethermind AuditAgent | v3.0.0-rc1 | [report](./tools/nethermind-audit-agent/v3.0.0-rc1/audit_agent_report_1_v3.0.0-rc1.pdf) | [feedback](./tools/nethermind-audit-agent/v3.0.0-rc1/audit_agent_report_1_v3.0.0-rc1-feedback.md) | | ABDK (external audit) | v1.0.1 -> v1.0.2 | [ABDK report (CMTAT repo)](https://github.com/CMTA/CMTAT/blob/master/doc/audits/ABDK_CMTA_CMTATRuleEngine_v_1_0/ABDK_CMTA_CMTATRuleEngine_v_1_0.pdf) | — | -## Static analysis results — v3.0.0-rc6 +## Static analysis results — v3.0.0-rc7 | Tool | High | Medium | Low | Info | Relevant to fix? | |---|---|---|---|---|---| | Slither 0.11.5 | 0 | 0 | 10 | 2 | **No** | -| Aderyn 0.6.5 | 0 | — | 8 (84 instances) | — | **No** | +| Aderyn 0.6.5 | 0 | — | 8 (91 instances) | — | **No** (one improvement made: `L-2`, pragma corrected to `^0.8.27`) | Every finding is by design, cosmetic, or a verified false positive. Highlights: @@ -52,9 +55,23 @@ Every finding is by design, cosmetic, or a verified false positive. Highlights: match the ERC-3643 reference interface, which declares them unindexed. Conformance, not an oversight. - **`L-8 Unchecked Return` (Aderyn, 1)** — `_grantRole` in a constructor cannot return `false`. False positive. -Slither: no change in counts from v3.0.0-rc5. Aderyn: same 8 findings, 76 -> 84 instances, entirely from the -file count — the token binding split added a net four files, and the two per-file detectors (`L-2` pragma, -`L-3` PUSH0) each moved by exactly four. No new finding came from the refactor. +- **`L-2 Unspecific Solidity Pragma` (Aderyn, 26)** — the floating pragma is kept for integrators, but the + range it stated was false: the code needs solc 0.8.27 (`require` with a custom error). Every `src/` and + `script/` file now declares `^0.8.27`. + +**Same findings as v3.0.0-rc6** in both tools, on the final rc7 code (`29556e5`: six deployables, after the +code-quality review and security review fixes). Slither: same 12 results, 108 -> 111 contracts. Aderyn: same 8 +findings, 84 -> 91 instances: the two per-file detectors (`L-2`, `L-3`) on the three new `*2771` deployables, and +one `L-5` empty block, the default `_checkBindingTarget` hook added by the security review fix F-3; nSLOC +683 -> 716. The run before the security review fixes (`3055fe2`) gave the same Slither output and 90 Aderyn +instances / 694 nSLOC. An intermediate rc7 run (`850976f` + pragma) counted 112 contracts / 92 instances / 707 nSLOC, with +the abstract `RuleEngineAccessControlShared` since folded into `RuleEngine` (`D-2`). Under `src/`, rc7 changes the `VERSION` string, the +ERC-2771 token-identity fix, ERC-2771 made opt-in (six deployables) and the pragma; build updates (solc 0.8.37, +EVM Osaka, CMTAT v3.3.0-rc4, forge-std v1.17.0) produced no finding. Earlier rc7 runs (`a91ca9a`, `4946c87`) gave +the same findings. + +v3.0.0-rc6 versus rc5: Slither unchanged. Aderyn: same 8 findings, 76 -> 84 instances, entirely from the file +count: the token binding split added a net four files, and the two per-file detectors moved by exactly four. ## Substantive findings that were fixed diff --git a/doc/security/audits/tools/v3.0.0-rc7/CLAUDE_ANALYSIS.md b/doc/security/audits/tools/v3.0.0-rc7/CLAUDE_ANALYSIS.md new file mode 100644 index 00000000..33239034 --- /dev/null +++ b/doc/security/audits/tools/v3.0.0-rc7/CLAUDE_ANALYSIS.md @@ -0,0 +1,1214 @@ +# RuleEngine — Code Quality Review (v3.0.0-rc7) + +| | | +|---|---| +| **Scope** | `src/` (production contracts, mocks excluded except where named) and the **test suite** (`test/`) | +| **Commit** | `3b94564` — final rc7 code: six deployables, `pragma ^0.8.27` (second pass) | +| **First pass** | `4946c87` — rc7 with the ERC-2771 token-identity fix, before the deployable split | +| **Compiler** | solc 0.8.37, `evm_version = osaka`, optimizer on, 200 runs | +| **Date** | 2026-10-15 | +| **Produced with** | Claude Code | + +## This is not a security audit + +Nothing in this report is a vulnerability. No finding below lets an unauthorized party move value, bypass a +transfer restriction, or brick a contract. The one rc7 security change, the ERC-2771 token-identity fix, was +re-checked on the final code (`H-2`) and holds for all six deployables. + +## Two passes + +This report was produced twice during rc7, and both are kept so a reader can see what each changed: + +- **First pass, `4946c87`.** Reviewed the rc6 -> rc7 changes, re-checked the carried findings, and added a full + review of the **tests** (check K). It wrote 25 tests (370 -> 395) and recorded the open decisions. +- **Second pass, `3b94564` (this revision).** Between the passes, rc7 made ERC-2771 opt-in: each access-control + model now has a deployable without a forwarder (`RuleEngine`, `RuleEngineOwnable`, `RuleEngineOwnable2Step`) and + a `*2771` deployable with one, and the pragma moved to `^0.8.27` (`F-1`). Every finding was re-verified against + the final code, every gas number re-measured, coverage re-run, the modularity probe re-run (`J-2`), and 17 new + mutants applied to the code that moved or is new (`K-3`). Where a first-pass number changed, both are shown. + +Method, so the reader can calibrate: + +- **Gas numbers were measured**, on the real contracts, by toggling each change in place and re-running the same + `gasleft()` harness (one test per path, so each measurement is its own transaction with cold storage). The + harness was deleted afterwards and the source restored. +- **Compile claims are compile results**: `F-1` built the production contracts with solc 0.8.20, 0.8.24, 0.8.26 + and 0.8.27; `J-2` built a downstream host against the current and the pre-split code. +- **Mutation testing was run, not estimated**: 33 mutants in the first pass and 17 in the second, each applied + to `src/`, the full suite run, the file restored. +- **Coverage comes from `forge coverage`**, not from the test count. + +Test count: 370 at the first pass, 395 after it, **438** at the second pass (the split added the shared +ERC-2771 / no-forwarder suites; see the CHANGELOG). No benchmark or probe file is left behind. + +## Disposition summary + +| ID | Finding | Outcome | +|----|---------|---------| +| A-1 | Loop increment form and `unchecked` | ⬜ no finding — `++i` on 0.8.37, `unchecked` would buy nothing | +| A-2 | Unbounded iteration over caller-supplied arrays | ⬜ left as is — admin-gated, carried from rc5/rc6 | +| A-3 | View loops call the public `rule(i)`, re-checking the bound on every iteration | ✅ fixed after the second pass — −682 gas per detect call with 3 rules; paid on-chain by ERC-3643 tokens | +| B-1 | `messageForTransferRestriction` resolves `rule(i)` twice, across an external call | ✅ fixed after the second pass — −375 gas per call on top of `A-3` | +| B-2 | `contains()` before `add()` / `remove()` leaves two unreachable branches | ✅ fixed after the second pass — −271 / −268 gas, branch coverage 40/40; the old form added no security (assessed) | +| C-1 | Every event has exactly one emit site | ⬜ verified — 8/8, unchanged by the split | +| C-2 | Batch self-binding approval emits the input, not the effect | ✅ closed after the second pass — event API kept, inaccurate NatSpec fixed and both events documented; `TokenBound` / `TokenUnbound` stay non-indexed (ERC-3643 spec) | +| C-3 | Empty batches succeed silently, while `setRules([])` reverts | ✅ decided after the second pass — binding batches stay atomic, documented in NatSpec and `TokenBinding-module.md`; rollback and empty-batch no-op pinned | +| D-1 | ERC-2771 `Context` overrides repeated per deployable | ⬜ no finding — 3 copies, one per `*2771` contract (4 before the split), compiler-mandated | +| D-2 | The RBAC and ownable families implement the ERC-2771 split two different ways | ✅ fixed after the second pass — `RuleEngineAccessControlShared` folded into `RuleEngine`; deployables grouped in `accessControl/` and `ownable/` | +| E-1 | `virtual` on every internal function | ⬜ no finding — 0 missing, including the new contracts | +| E-2 | `if (...) revert X()` sites against the project's `require(cond, X())` convention | ✅ fixed after the second pass — 8 production + 4 mock sites converted, 0 conditional `revert` left | +| F-1 | `pragma solidity ^0.8.20` was false: the code does not compile below 0.8.27 | ✅ fixed — `^0.8.27` everywhere (`3b94564`) | +| F-2 | Advertised ERC-165 ids unchanged by rc7, and identical between each pair | ⬜ verified — pinned by `IRuleInterfaceId.t.sol` and `ERC2771VariantTestBase` | +| G-1 | NatSpec length and documentation pointers | ⬜ no finding — median 5 lines, max 19, zero `.md` pointers | +| G-2 | Stale or wrong NatSpec in production contracts | ✅ fixed after the second pass — all 10 sites corrected (1 with `B-2`, 9 after), plus 5 typos in the mocks | +| G-3 | `ERC3643TokenMock` header and a test header describe the pre-rc7 ERC-3643 setup | ✅ fixed — test header at the first pass, mock header after the second pass | +| G-4 | CHANGELOG rc7 said the `version()` string was "the only change under `src/`" | ✅ fixed | +| G-5 | `RuleEngine-with-CMTAT.md` §4.7 said every deployable inherits `ERC2771Context` | ✅ fixed — new in the second pass | +| H-1 | View approves a mint that enforcement rejects | ⬜ documented — carried, unchanged | +| H-2 | Sender resolution after the ERC-2771 fix and the split | ⬜ verified — two identity sites, both `msg.sender`; no-forwarder variants ignore any suffix | +| H-3 | A `*2771` deployable accepts `address(0)` as its forwarder | ⚠️ decide — new in the second pass | +| I-1 | `IRule` demands two functions the engine never calls | ✅ fixed after the second pass — `IRule` narrowed, ID `0xb1a69752`; the legacy ID `0x2497d6cb` is still accepted | +| I-2 | Standalone-rule configuration advertised but untested | ✅ fixed after the second pass (option 1) — 9 integration tests, CMTAT guide §4.8, mocks import CMTAT's ids; mock `transferred` left unguarded, documented | +| I-3 | Engine should call `canTransfer` on rules? | ⬜ no — carried from rc6 | +| J-1 | Binding registry embeddable in a foreign host | ⬜ re-verified by example — two hosts compile (no `5005`); size depends on the host's CMTAT deployment version | +| J-2 | ERC-2771 in the shared ownable layer blocked a host with its own forwarder | ✅ fixed by the split — verified by compile probe | +| K-1 | Two tests used a bare `vm.expectRevert()` | ✅ fixed — both name their error; 0 left | +| K-2 | Coverage | ⬜ 100% lines / statements / functions; branches 41/43 at the second pass (2 dead, `B-2`), **49/49** on the final code | +| K-3 | Mutation testing | ✅ first pass: 4 of 32 survived, all 33 killed after new tests; second pass: see `K-3` | +| K-4 | CI never runs the `erc3643` profile | ✅ fixed after the second pass — new CI step | +| K-5 | No fuzz and no invariant test | ✅ fixed — 2 fuzz properties and 4 handler-based invariants, on all six deployables | +| K-6 | `TokenSelfBindingApprovalSet` was never asserted | ✅ fixed — asserted in the three access-control models | + +**Counted: 33 rows — 20 fixed (✅), 12 no-finding / verified / left as is (⬜), 1 open decision (⚠️, `H-3`).** + +## Outstanding + +| ID | Item | Why it is still open | +|----|------|----------------------| +| H-3 | Reject a zero forwarder in the `*2771` constructors | Changes the tests that use a zero forwarder; needs a new error | +| H-1 | View/enforcement divergence | Inherent to the ERC-1404 3-argument signature | + +--- + +## A. Loops and iteration + +### A-1. Increment form — no finding + +Every loop uses `++i`, none uses `unchecked`. On solc 0.8.37 (and the `^0.8.27` floor) the overflow check on a +bounded loop counter is already elided (since 0.8.22). + +### A-2. Unbounded iteration over caller-supplied arrays — left as is + +`setRules`, `bindTokens`, `unbindTokens` and `setTokenSelfBindingApprovalBatch` are gated on a manager role, so +only the operator can pass an oversized array and only their own transaction runs out of gas. Carried from rc5 +`A-3` / rc6 `A-2`. + +### A-3. The view loops go through the public `rule(i)` getter — fixed + +`RuleEngineBase.sol:169`, `:193` and `:217-218`: + +```solidity +uint256 rulesLength = rulesCount(); +for (uint256 i = 0; i < rulesLength; ++i) { + uint8 restriction = IRule(rule(i)).detectTransferRestriction(from, to, value); +``` + +`rule(i)` is the public getter. It re-reads `_rules.length()` and checks `ruleId < length` on every iteration, +a check the loop bound already guarantees. The enforcement loops in `RulesManagementModule._transferred` use +`_rules.pos(i)` directly, so the two paths over the same set are written differently. + +**Measured** (3 rules, toggled in place on the real `RuleEngine`): + +| Path | First pass (`4946c87`) | Second pass (`3b94564`) | +|---|---|---| +| `detectTransferRestriction` | 24,619 -> 23,937 (**−682**) | 24,597 -> 23,949 (**−648**, −216 per rule) | +| `detectTransferRestrictionFrom` | 25,567 -> 24,885 (**−682**) | 25,545 -> 24,897 (**−648**) | + +The baselines moved by about 20 gas between the passes because the plain `RuleEngine` lost the ERC-2771 +functions, which changes the selector dispatch; the saving moved with them. Both measurements are kept rather +than overwritten. + +**Why it is more than cosmetic:** a T-REX token calls `canTransfer` on-chain **before every transfer and mint** +(`test/ERC3643Real/` pins this with `expectCall`), so for an ERC-3643 deployment this is about 216 gas per rule on +every token operation, paid by users. CMTAT does not call the view on its transfer path. + +**Fix:** `IRule(_rules.pos(i))` in the three view loops, and `using EnumerableSet for EnumerableSet.AddressSet;` in +`RuleEngineBase`. With this change the full suite passed, 438/438. **Verdict: implement.** + +**Implemented after the second pass.** The three loops in `RuleEngineBase` (`_detectTransferRestriction`, +`_detectTransferRestrictionFrom`, `_messageForTransferRestriction`) now read `_rules.length()` once and call +`IRule(_rules.pos(i))`, the same form as the enforcement loops in `RulesManagementModule._transferred`. The bound +also moved from the public `rulesCount()` to `_rules.length()`, which the measurements above did not include. +Measured on the final edit with a throwaway probe (3 whitelist rules, all allowing, cold calls from a test; the +absolute numbers include cold-access costs and are not comparable with the table above, only the differences are): + +| Path | Before | After | Difference | +|---|---|---|---| +| `detectTransferRestriction` | 40,269 | 39,587 | **−682** (−227 per rule) | +| `detectTransferRestrictionFrom` | 9,915 | 9,233 | **−682** | +| `messageForTransferRestriction` (code claimed by the first rule) | 5,262 | 4,794 | **−468** | + +Full suite 438/438. The message loop still resolved the rule twice when a rule claimed the code; that is `B-1`, +implemented next. + +## B. Storage reads + +### B-1. `messageForTransferRestriction` resolves the rule twice — fixed + +`RuleEngineBase.sol:217-218`: + +```solidity +if (IRule(rule(i)).canReturnTransferRestrictionCode(restrictionCode)) { + return IRule(rule(i)).messageForTransferRestriction(restrictionCode); +``` + +The second `rule(i)` re-reads the length and the set slot after an external call, which the optimizer cannot +forward across. Caching it (`IRule rule_ = IRule(_rules.pos(i));`) together with `A-3` measured **30,340 -> 29,077 +(−1,263)** at the first pass and **30,318 -> 29,089 (−1,229)** at the second, with the claiming rule third of three. +View-only, so it only matters for an on-chain caller. **Verdict: implement with `A-3`**; it is the same edit. + +**After `A-3`:** the two calls now read `IRule(_rules.pos(i))`, so what remains is one extra `pos(i)` storage read +after the external call. + +**Implemented after `A-3`.** The loop body now reads: + +```solidity +IRule rule_ = IRule(_rules.pos(i)); +if (rule_.canReturnTransferRestrictionCode(restrictionCode)) { + return rule_.messageForTransferRestriction(restrictionCode); +``` + +Measured with a throwaway probe (3 `RuleCodeProbe` rules claiming codes 50, 51 and 52; `A-3` already applied on +both sides): + +| Claiming rule | Before | After | Difference | +|---|---|---|---| +| First of three | 18,362 | 17,987 | **−375** | +| Third of three | 18,992 | 18,631 | **−361** | + +The saving does not grow with the position of the claiming rule: only the claiming iteration made the second +read. Full suite 438/438. + +### B-2. A `contains()` check before the mutation leaves two branches no test can reach — fixed + +`RulesManagementModule.sol:97` checks membership before `_removeRule` removes at `:194`; `_addRule` does the same +through `_checkRule` (`:255`, then `_rules.add` at `:181`). The second check is unreachable both times, and +`forge coverage` confirms these are **the only two uncovered branches in `src/`** (`K-2`). +`RuleEngine_RulesManagementModule_OperationNotSuccessful` is the only custom error no test can trigger. + +The token binding already uses the return value (`require(_boundTokens.add(token), ...)`, the rc5 `B-1` fix). + +**Fix:** + +```solidity +// removeRule: drop the contains() line; in _removeRule: +require(_rules.remove(address(rule_)), RuleEngine_RulesManagementModule_RuleDoNotMatch()); +// _checkRule: drop the duplicate check; in _addRule: +require(_rules.add(address(rule_)), RuleEngine_RulesManagementModule_RuleAlreadyExists()); +``` + +**Measured:** `removeRule` −268 and `addRule` −271 at the second pass (27,072 -> 26,804 and 68,856 -> 68,585), +the same savings as the first pass. Full suite 438/438 with the change. Adding a duplicate now performs the +ERC-165 call before reverting with the same `RuleAlreadyExists`; only the revert path is affected. +`OperationNotSuccessful` then becomes unused; removing it is an ABI change. **Verdict: implement**, with `A-3`. + +**Does the current form add a check, or any security?** No. Assessed point by point against the code: + +- **No-duplicate invariant.** It is held by the `EnumerableSet` itself together with the + `require(_rules.add(...))` in `_addRule` (`:181`), which is present in both the current and the proposed form. + The `_checkRule` duplicate test (`:255`) only runs first. If a subclass overrode `_checkRule` without calling + the parent, the current code would still reject the duplicate (with `OperationNotSuccessful`), and so would the + proposed code (with `RuleAlreadyExists`). The redundant test adds no layer. +- **Removal.** `_rules.remove` returns `false` exactly when `contains` would, and the function has no external + call or other state change before it, so `require(_rules.remove(...), RuleDoNotMatch())` rejects the same calls + with the same error. Same for an override of `removeRule` that skipped the `contains()`: today it is caught by + `OperationNotSuccessful` in `_removeRule`, after the fix by `RuleDoNotMatch`. +- **Order against the external call.** This is the only real difference: today a duplicate is rejected before + `ERC165Checker.supportsInterface`, after the fix it is rejected after it. That call is a `staticcall` limited + to 30,000 gas (OpenZeppelin `ERC165Checker.sol:135`), so the rule cannot change state or re-enter, and the rule + is already in the set, so it is already trusted. Checks-effects-interactions is not at stake: the call + is a read, and the revert discards everything. +- **Access.** Both paths stay behind `onlyRulesManager`; nothing changes who can reach them. + +What the current form does buy, none of it security: a duplicate `addRule` fails before the ERC-165 call (cheaper +revert path); and the error is always `RuleAlreadyExists` for a duplicate, even when a mutable rule that is +already in the set has since stopped advertising `IRule` (after the fix that case reports +`RuleInvalidInterface`, because `_checkRule` runs first). `_checkRule` also stays a complete, standalone +validation hook for a subclass that calls it on its own; no contract in this repository does. The case for the +change remains gas (−271 / −268 on the success paths) and coverage (the only two dead branches in `src/`). + +**Implemented after the second pass.** `removeRule` no longer calls `contains()`; `_removeRule` reverts with +`RuleDoNotMatch` when `_rules.remove` returns `false`. `_checkRule` keeps only the zero-address check; `_addRule` +reverts with `RuleAlreadyExists` when `_rules.add` returns `false`, which also covers a duplicate inside one +`setRules` batch. `RuleEngine_RulesManagementModule_OperationNotSuccessful` is removed (one error less in the ABI; +the same was done for `RuleEngine_ERC3643Compliance_OperationNotSuccessful` in rc6). The stale `_removeRule` +NatSpec ("specified index", `G-2`) is rewritten in the same edit. + +Measured with a throwaway probe (`RuleEngine`, `RuleCodeProbe` rules, 2 rules present): + +| Call | Before | After | Difference | +|---|---|---|---| +| `addRule` (success) | 68,327 | 68,056 | **−271** | +| `removeRule` (success) | 16,560 | 16,292 | **−268** | +| `addRule` of a rule already present (revert) | 6,088 | 11,042 | +4,954, the ERC-165 `staticcall` now runs first | +| `removeRule` of a rule not present (revert) | 1,698 | 1,778 | +80 | + +Full suite 438/438. Each new `require` was mutated (the return value ignored): dropping the `add` check fails 6 +tests, dropping the `remove` check fails 3. Branch coverage of `src/` is now **100% (40/40)**. + +## C. Events + +### C-1. One emit site per event — verified + +``` +AddRule 1 RemoveRule 1 ClearRules 1 SetMaxRules 1 +TokenBound 1 TokenUnbound 1 TokenSelfBindingApprovalSet 1 TokenSelfBindingApprovalBatchSet 1 +``` + +Unchanged by the split: the constructors of `RuleEngineAccessControlShared` and `RuleEngineOwnableShared` call +`_setMaxRules` and `_bindToken`, so every deployable emits the initial `SetMaxRules`, pinned for all six by +`RuleEngineMaxRulesEvent.t.sol`. All eight events are asserted by a test (`K-6`). + +### C-2. The batch approval event reports the input — kept, documented + +Carried from rc5 `C-2` / rc6 `C-2`, unchanged by rc7. Restated in full and re-verified on the final rc7 code, with +the options measured. + +**The code.** The single and batch setters write the same mapping but emit different events +(`TokenBindingExtendedModule.sol:50-71`, events in `ITokenBindingExtended.sol:21` and `:28`): + +```solidity +function setTokenSelfBindingApproval(address token, bool approved) ... { + require(token != address(0), TokenBinding_InvalidTokenAddress()); + _tokenSelfBindingApproval[token] = approved; + emit TokenSelfBindingApprovalSet(token, approved); // event TokenSelfBindingApprovalSet(address indexed token, bool approved) +} + +function setTokenSelfBindingApprovalBatch(address[] calldata tokens, bool approved) ... { + for (uint256 i = 0; i < tokens.length; ++i) { + require(tokens[i] != address(0), TokenBinding_InvalidTokenAddress()); + _tokenSelfBindingApproval[tokens[i]] = approved; + } + emit TokenSelfBindingApprovalBatchSet(tokens, approved); // event TokenSelfBindingApprovalBatchSet(address[] tokens, bool approved) +} +``` + +**What goes wrong for a consumer:** + +- **Two shapes for one state change.** Approving token `T` emits `TokenSelfBindingApprovalSet(T, true)` through + the single setter and `TokenSelfBindingApprovalBatchSet([.., T, ..], true)` through the batch. An indexer that + rebuilds the approval map must subscribe to both and decode both. +- **A filter on the token misses every batch update.** `token` is `indexed` in the single event, so the natural + query is `eth_getLogs` with `topics[1] = T`. The batch event has no indexed field (an `address[]` cannot be + usefully indexed; it would be stored as a hash), so that query never returns a batch approval of `T`. A + monitoring rule "alert when token T gains self-binding rights", the security-relevant one, since self-binding + lets a token unbind itself, is silently blind to the batch path. +- **The event reports the input, not the effect.** The array is echoed as given: tokens already at the + requested value, and duplicates (`[T, T]` is accepted and listed twice), appear as if they changed. The + NatSpec of the event says "The token addresses whose self-binding permission changed", which is therefore + inaccurate. An empty batch emits `TokenSelfBindingApprovalBatchSet([], b)`, an event that records nothing + (`C-3`). +- **Inconsistent with the sibling batch functions.** `bindTokens` / `unbindTokens` go through + `_bindToken` / `_unbindToken` and emit one `TokenBound` / `TokenUnbound` per token, so binding has a single + event shape whichever entry point is used. Only the approval batch has a separate event. + +What it is **not**: a state or security defect. The mapping is written correctly, the reads +(`isTokenSelfBindingApproved`) are authoritative, and the batch is guarded by the same +`onlyTokenBindingManager` as the single setter. The issue is only what the event log says. + +**Pinned today** by `testSetTokenSelfBindingApprovalBatchEmitsSingleBatchEvent` in the three access-control +models (`test/RuleEngine/ERC3643Compliance.t.sol:313`, `test/RuleEngineOwnable/ERC3643Compliance.t.sol:262`, +`test/RuleEngineOwnable2Step/RuleEngineOwnable2Step.t.sol:260`), which assert exactly one log with the batch +topic. Any option below changes those tests. + +**Options, measured** (throwaway probe on `RuleEngine`, each variant patched into +`TokenBindingExtendedModule` and reverted; "unchanged" re-sends the same 10 tokens with the same value): + +| Option | Batch of 1 | Batch of 10 (new) | Batch of 10 (unchanged) | Event stream | +|---|---|---|---|---| +| **Current**: one batch event with the input | 33,080 | 233,956 | 14,938 | two shapes; input, not effect | +| **A.** Per-token `TokenSelfBindingApprovalSet`, drop the batch event | 32,384 (−696) | 242,440 (+8,484) | 23,422 (+8,484) | one shape, indexed; still reports no-ops | +| **B.** Per-token events **and** the batch event | 34,529 (+1,449) | 248,446 (+14,490) | 29,428 (+14,490) | both shapes; old consumers keep working | +| **C.** Per-token event **only when the value changes** | 32,611 (−469) | 244,710 (+10,754) | 8,086 (−6,852) | one shape, indexed, reports the effect | + +The per-token cost is about 850 gas per event (A) and about 1,075 per token for the change check plus the event +(C). This is an administrative function, called rarely and by an operator, so the absolute cost is minor; +the difference in what consumers can rely on is not. + +**Trade-offs:** + +- **A** is the minimal fix for consistency and filtering, and the closest to `bindTokens`. It removes an event + from the ABI. +- **B** is the only option that breaks no existing consumer, at the highest gas cost, and it keeps the two + shapes alive: it postpones the cleanup rather than doing it. +- **C** makes the log match the effect and is the cheapest when nothing changes, but it also changes the single + setter's contract if applied there (today `setTokenSelfBindingApproval(T, true)` emits even when `T` is already + approved). To stay consistent, both setters would get the change check. It is the convention `RuleAddressList` + already uses for its batches: skip elements already in the target state (`C-3`). +- In every option, the NatSpec of the batch function and of the remaining event must say what is emitted. + +**Related, noticed while re-verifying:** `TokenBound(address token)` and `TokenUnbound(address token)` +(`ITokenBinding.sol:20`, `:26`) do **not** index `token`, unlike `TokenSelfBindingApprovalSet`. A consumer filtering +binding changes by token has the same problem as above, on every binding path. Indexing them changes the event +topics (`topics[1]` becomes the token, the data becomes empty), so it is also an ABI-visible change for indexers; +it would be cheapest to decide together with C-2. + +**Correction (maintainer):** these two events are **not** this project's to change. They are defined by +ERC-3643 itself, without `indexed`: `event TokenBound(address _token); event TokenUnbound(address _token);` +(`doc/ERCSpecification/erc-3643.md:295-296`, and T-REX `lib/ERC-3643/contracts/ERC-3643/IERC3643Compliance.sol:45`, +`:49`). `indexed` does not change the event signature (`topic0` is the same), but it moves `token` from the data +to `topics[1]`, so a consumer decoding with the standard ERC-3643 ABI would read an empty data field. The project +would prefer an indexed token, but conformance to the standard wins: **keep them non-indexed**. The NatSpec of +both events in `ITokenBinding.sol` now says so, so they are not "fixed" later. This does not affect the +recommendation for `TokenSelfBindingApprovalSet` / the batch event, which are this project's own events. + +**Verdict: decide** — a product call on the event API, not a correctness fix. Recommended: **C**, applied to both +setters, while the project is still in release candidates and the event API is not yet frozen. (`indexed` on +`TokenBound` / `TokenUnbound` was also recommended here at first; withdrawn, see the correction above.) If existing indexers must keep working unchanged, **B** for one release, then A or C. + +**Closed after the second pass: kept, documented.** The maintainer chose to keep the event API: the approvals +are stored correctly, `isTokenSelfBindingApproved` is authoritative, the function is an administrative call +used a few times per deployment, and changing the emitted events costs consumers and three pinned tests. +Recommendation C above is therefore not implemented; the measured options stay here for whoever revisits it. +What was inaccurate is fixed, in comments and docs only (no behaviour or ABI change): + +- **`ITokenBindingExtended` NatSpec.** `TokenSelfBindingApprovalBatchSet` said `tokens` were the addresses + "whose self-binding permission changed"; it now says the array is the input as passed (tokens already at the + value, duplicates, empty for an empty batch), that no per-token event is emitted so a filter on the indexed + `token` misses batches, and why `tokens` is not indexed (an indexed array is stored as a hash). The single + event says it is emitted on every call, also for a no-op, and points to the batch event and to + `isTokenSelfBindingApproved`. `setTokenSelfBindingApprovalBatch` states which event it emits. +- **`doc/technical/TokenBinding-module.md` §4** has a new warning, "Self-binding approvals have two events; + indexers must handle both", including the monitoring case (a token gaining self-binding rights can unbind + itself). + +### C-3. Empty batches are accepted, inconsistently with `setRules` — decided + +`setRules([])` reverts (`RuleEngine_RulesManagementModule_ArrayIsEmpty`). `bindTokens([])`, `unbindTokens([])` +and `setTokenSelfBindingApprovalBatch([], b)` succeed as no-ops, and the last one emits +`TokenSelfBindingApprovalBatchSet([], b)`, an event that records nothing. Two conventions for the same input on +sibling admin functions. **Verdict: decide**; no test was written because the expected value is the question. + +**Revised after the second pass, against the project's single-versus-batch convention.** The project already +separates a single call from a batch call by whether a no-op reverts, for gas reasons. The reference rule +`RuleAddressList` states it in its NatSpec (`RuleAddressList.sol:41-75`): + +- **single call** (`addAddressToTheList`, `removeAddressFromTheList`): an element that is already in the target + state reverts, "to save gas": the operator's mistake is reported and the transaction costs almost nothing; +- **batch call** (`addAddressesToTheList`, `removeAddressesFromTheList`): an element already in the target state + is skipped and "the transaction remains valid (no revert)", so one stale entry does not throw away the gas of + the whole batch. + +Read against that convention, the original finding compared the wrong things: + +- **Empty batches succeeding is consistent.** An empty batch is the extreme case of a batch where no element + changes anything, and under the batch rule a no-op does not revert. Making `bindTokens([])` revert would be the + inconsistency. +- **`setRules([])` reverting is not a batch rule, and is not about gas.** `setRules` replaces the whole set, so + `[]` would mean "remove every rule" and leave a bound token with no enforcement. The revert is a safety guard + that sends the operator to the explicit `clearRules()`; it was reviewed by Nethermind (best practice 7 in + `doc/README.md`) and kept by design. The two behaviours do not conflict: they answer different questions. +- **The real deviation is elsewhere: `bindTokens` / `unbindTokens` follow the single-call rule inside a batch.** + Each element goes through `_bindToken` / `_unbindToken`, which `require` the `EnumerableSet` mutation to succeed + (`TokenBindingModule.sol:104` and `:115`). One token that is already bound (or not bound, for `unbindTokens`) + reverts the whole batch, and all the gas spent on the earlier elements is lost + (`testCannotBindTokensBatchWithDuplicateToken` pins this for a duplicate). This is the opposite of the + `RuleAddressList` batch rule. The Slither `L-6` triage records it as deliberate ("atomic batch operations", + `doc/README.md`), but the reason is not written next to the functions, and the two conventions sit in the same + repository. +- **`setTokenSelfBindingApprovalBatch` is consistent.** Setting a flag to the value it already has is not an + error in the single call either, so neither form reverts on a no-op. Only the empty event remains, and it + belongs to `C-2` (the event reports the input, not the effect). + +**Verdict: revised.** Keep empty batches as no-ops and keep `setRules([])` reverting; both are now pinned to a +reason. The open decision moves to the binding batches: + +- **keep them atomic**, and state in the `bindTokens` / `unbindTokens` NatSpec and in + `doc/technical/TokenBinding-module.md` that they deliberately depart from the batch rule: a binding change is + security-relevant, and an operator who lists a token that is already bound has probably made a mistake that + should stop the whole operation; or +- **skip already-applied tokens**, like `RuleAddressList`: emit `TokenBound` / `TokenUnbound` only for tokens + that changed, keep the zero-address check as a revert, and update the test above. + Not measured; the cost of an atomic batch that reverts is the gas spent up to the failing element. + +Either way, a test for the empty batches can now be written, since the expected value (no-op, no revert) is no +longer the question. Not written in this pass. + +**Decided after the second pass: keep them atomic.** The maintainer chose the first option. Implemented as +documentation and tests, with no behaviour change: + +- **NatSpec** of `bindTokens` / `unbindTokens` (`ITokenBindingExtended.sol`) states that the call is atomic, + that this deliberately departs from the skip-if-already-done batch convention, why (a binding change is + security-relevant, and an already-bound token in the list is most likely an operator mistake that should stop + the operation), and that an empty array is a no-op. +- **`doc/technical/TokenBinding-module.md` §4** has a new warning, "The batch functions are atomic, on purpose", + with the same reasoning and the contrast with `RuleAddressList`. +- **Tests**, in the three access-control families (`test/RuleEngine/ERC3643Compliance.t.sol`, + `test/RuleEngineOwnable/ERC3643Compliance.t.sol`, `test/RuleEngineOwnable2Step/RuleEngineOwnable2Step.t.sol`): + `testCannotBindTokensBatchWithAlreadyBoundToken` now lists the new token **before** the already-bound one and + asserts it is rolled back (before, the failing token came first, so nothing was bound before the revert and + atomicity was not observed); `testCannotUnbindTokensBatchWithTokenNotBound` asserts the token unbound before + the failure stays bound; new `testEmptyBindAndUnbindBatchesAreNoOps` asserts no revert, no event and no state + change. Full suite 463/463. + +`setRules([])` keeps reverting (safety guard, not a batch rule), and the empty approval batch still emits an +empty `TokenSelfBindingApprovalBatchSet`, which belongs to `C-2`. + +## D. Duplication + +### D-1. ERC-2771 overrides — no finding + +The `_msgSender` / `_msgData` / `_contextSuffixLength` trio now appears once in each `*2771` contract: 3 copies, +down from 4 at the first pass (when `RuleEngine`, `RuleEngineOwnableShared` and both ownable deployables carried +it). It is compiler-mandated: each contract must name its bases in `override(...)`. + +### D-2. The two families implement the same split two ways — fixed + +| Family | Without forwarder | With forwarder | +|---|---|---| +| RBAC | `RuleEngine is RuleEngineAccessControlShared` (constructor only, 5 nSLOC) | `RuleEngine2771 is ERC2771ModuleStandalone, RuleEngineAccessControlShared` | +| Ownable | `RuleEngineOwnable is RuleEngineOwnableShared, Ownable` | `RuleEngineOwnable2771 is ERC2771ModuleStandalone, RuleEngineOwnable` | + +The ownable `*2771` contracts extend their deployable counterpart, while `RuleEngine2771` extends the abstract base +`RuleEngine` is built on. Both are correct and compile to the same behaviour; the difference is only in how a +reader navigates. Making the RBAC family match the ownable one (`RuleEngine2771 is ERC2771ModuleStandalone, +RuleEngine`) would let `RuleEngineAccessControlShared` be folded into `RuleEngine`; the reverse is not possible for +the ownable family, where the deployables hold the `Ownable` / `Ownable2Step` choice. **Verdict: decide** — a +consistency improvement with no runtime effect; leaving it is defensible because `RuleEngineAccessControlShared` +mirrors `RuleEngineOwnableShared` by name. + +**Which option is better, for duplication and readability.** Analysed after the second pass, on request. + +*Duplication: almost no difference.* + +- The three ERC-2771 overrides (`_msgSender`, `_msgData`, `_contextSuffixLength`) stay in each of the three + `*2771` contracts whichever way the RBAC family is built, because the compiler requires them in every contract + that combines `ERC2771Context` with `Context` (`D-1`). +- The fold deletes `RuleEngineAccessControlShared.sol` (116 lines including NatSpec), but its code moves into + `RuleEngine`. The net saving is about 20 lines: the current 20-line `RuleEngine` wrapper and one duplicated + constructor parameter list. The argument for the change is readability, not duplication. + +*Readability: the fold is clearly better.* + +1. **One rule for all six deployables.** Each `X2771` would be `X` plus `ERC2771ModuleStandalone` plus the three + overrides. Today a reader has to learn two layouts: `RuleEngine2771` does not extend `RuleEngine`, while + `RuleEngineOwnable2771` extends `RuleEngineOwnable`. +2. **The ownable shared base earns its place; the RBAC one does not.** `RuleEngineOwnableShared` holds code used + by two different deployables, `RuleEngineOwnable` and `RuleEngineOwnable2Step`. + `RuleEngineAccessControlShared` exists only so that `RuleEngine2771` can avoid inheriting `RuleEngine`. After + the fold it would have a single child: a layer of indirection with nothing to share. +3. **`RuleEngine` becomes readable on its own.** Today the deployable people open first is a 20-line wrapper, and + the roles, the `hasRole` override and `supportsInterface` live one file away. +4. **The inheritance chain gets one level shorter** for both RBAC contracts. + +*What argues for leaving it as is:* + +- **Naming symmetry.** `RuleEngineAccessControlShared` mirrors `RuleEngineOwnableShared`. That is the only real + argument, and it is cosmetic: the two names would look parallel while doing different jobs. +- **Abstract bases versus deployables.** Some teams prefer that a deployable never inherits another deployable. + The ownable family already does it, so that rule does not hold in this project anyway. + +*Cost of the fold:* + +- **Code:** `src/deployment/RuleEngine.sol`, `src/deployment/RuleEngine2771.sol`, and deleting + `src/RuleEngineAccessControlShared.sol`. No test or script references the shared base, so + `RuleEngine2771Exposed` and the test suites stay as they are. +- **Docs:** `README.md`, `doc/README.md`, `CLAUDE.md` / `AGENTS.md` (inheritance tree and the "override the hooks + in ..." instructions), `CHANGELOG.md`, the Surya schema, and this entry. +- **Behaviour:** none. Constructors, ABI, ERC-165 answers and roles are unchanged; only the bytecode layout + changes, and the contracts are not upgradeable. The ownable family already compiles with this exact pattern, + so no linearization conflict is expected. **Assumed, not checked: the RBAC version has not been compiled.** + +**Recommendation:** fold `RuleEngineAccessControlShared` into `RuleEngine` and declare +`RuleEngine2771 is ERC2771ModuleStandalone, RuleEngine`. Not implemented. + +**Implemented after the analysis.** `src/RuleEngineAccessControlShared.sol` is deleted and its content (constructor +checks, initial `SetMaxRules`, `grantRole` rule guard, `hasRole`, `supportsInterface`, the three access-control +hooks) now lives in `RuleEngine`, which extends `RuleEngineBase`, `AccessControlEnumerable` and the two role +storages directly. `RuleEngine2771 is ERC2771ModuleStandalone, RuleEngine`, so all six deployables follow the same +rule. On request, the deployables are also grouped by access-control model: + +``` +src/deployment/ +├── accessControl/ RuleEngine, RuleEngine2771 +└── ownable/ RuleEngineOwnable, RuleEngineOwnable2771, RuleEngineOwnable2Step, RuleEngineOwnable2Step2771 +``` + +The abstract bases (`RuleEngineBase`, `RuleEngineOwnableShared`) stay in `src/`, since they are not deployable. +Verified: `forge build` without conflict (the "not compiled" assumption above is now checked), full suite +438/438, `FOUNDRY_PROFILE=erc3643 forge test` 13/13. The ERC-165 answers are pinned by `testSupportsInterfaces` and, +for each pair, by `ERC2771VariantTestBase`. The ABIs were **not** diffed against the previous commit (the +temporary worktree was not permitted); since the moved code is unchanged, no difference is expected. Import paths +in the scripts, tests, mocks, `package.json`, `doc/TOOLCHAIN.md` and `doc/script/script_sol2uml.sh` are updated, +and the Surya schema is regenerated. The second-pass coverage table in `K-2` predates the fold and still lists +`RuleEngineAccessControlShared.sol`; `K-2` now also has a table measured on the final code. + +## E. `virtual` and style conventions + +### E-1. `virtual` coverage — no finding + +Zero `internal` functions in `src/` (mocks excluded) lack `virtual`, including the four contracts added by the +split. + +### E-2. Error style split 9 / 10 against the project's own rule — fixed + +`CLAUDE.md`: "Use `require(condition, CustomError(...))`." `src/` now has **10** `require` and **9** +`if (...) { revert ... }`: + +``` +RulesManagementModule.sol:54, :57, :81, :165, :253, :256 TokenBindingModule.sol:150 +RuleEngineBase.sol:231 RuleEngineOwnableShared.sol:49 +``` + +The two `RuleEngine.sol` sites of the first pass became `require` when they moved to +`RuleEngineAccessControlShared`. Convention only, no runtime difference measured or claimed. With the pragma at +`^0.8.27` (`F-1`), `require` with a custom error is available to every supported compiler, so the conversion has +no remaining obstacle. **Verdict: decide.** + +**Implemented after the second pass.** `B-2` had already removed one site (the duplicate check in `_checkRule`), +leaving 8 in production code, all converted: `RulesManagementModule` `setRules` (x2), `addRule`, `_setMaxRules`, +`_checkRule`; `RuleEngineBase._checkRule`; `RuleEngineOwnableShared._checkOwnershipTransferTarget`; +`TokenBindingModule._checkBoundToken`. The 4 conditional sites in the mocks were converted too +(`RuleMintAllowanceMock.transferred`, the `RuleAddressList` constructor, `_addAddressToThelist`, +`_removeAddressFromThelist`). The only `revert` statements left in `src/` are the two unconditional ones of +`RuleOperationRevertMock`, which has no condition to express. + +**Correction: "no runtime difference" was not true for one site.** `require(cond, Error(args))` evaluates the +error's arguments **before** the check, even when it passes. `addRule` reports the cap +(`MaxRulesExceeded(_maxRules)`), so the straight conversion read `_maxRules` from storage twice: measured +**68,056 -> 68,164 (+108)**. Caching the cap in a local (`uint256 maxRules_ = _maxRules;`) brings it to +**68,069 (+13)**. Per-function probe, before -> after: + +| Call | Before | After | +|---|---|---| +| `addRule` | 68,056 | 68,069 (+13, with the cached cap; +108 without) | +| `setRules` (2 rules) | 50,734 | 50,739 (+5; caching made it +10, so not cached) | +| `setMaxRules` | 5,257 | 5,257 | +| `transferred` (bound-token gate, hot path) | 10,553 | 10,553 | +| `transferOwnership` (ownable rule guard) | 14,753 | 14,753 | + +Full suite 447/447; production coverage 100% lines / statements / functions / branches (48/48). The convention +note in `CLAUDE.md` / `AGENTS.md` now records the eager-argument cost. + +## F. Specification and compiler conformance + +### F-1. The pragma promised a range the code could not compile in — fixed + +Every `src/` file declared `^0.8.20`. Built with each compiler (`forge build --use src/deployment`): + +| solc | Result with `^0.8.20` | +|---|---| +| 0.8.20 | fails — CMTAT's `ERC1404ExtendInterfaceId.sol` requires `^0.8.24` | +| 0.8.24 | fails — `Error (9322)`: no `require(bool, error)` overload | +| 0.8.26 | fails — "Require with a custom error is only available using the via-ir pipeline" | +| **0.8.27** | **compiles** | + +**Fixed in `3b94564`:** all 58 files under `src/` and `script/` declare `^0.8.27`. Re-checked: 0.8.27 builds, and +0.8.26 is now refused by the pragma itself ("no solc version exists that matches") instead of failing inside a +`require`. `README.md`, `CLAUDE.md` / `AGENTS.md`, `RuleEngine-with-ERC3643.md` and the Aderyn `L-2` feedback +were updated. Tests keep `^0.8.20`: they are not distributed, and the `erc3643` profile pins 0.8.30. + +### F-2. Interface ids unchanged by rc7 — verified + +`testInterfaceIdConstantsMatchTheirWireValues` pins all five values (`0x2497d6cb`, `0x3144991c`, `0x646ba2be`, +`0x7157797f`, `0xab84a5c8`). The split adds a second guarantee: `ERC2771VariantTestBase` asserts, over 13 +interface ids, that each `*2771` contract answers `supportsInterface` exactly like its counterpart without a +forwarder (ERC-2771 has no ERC-165 id). + +## G. Code / documentation mismatch + +### G-1. NatSpec proportion and documentation pointers — no finding + +158 NatSpec blocks in `src/` (mocks excluded): median **5** lines, 90th percentile **9**, maximum **19** +(`ERC3643ComplianceModule` header). Zero `.md` / `doc/` pointers in production comments. + +### G-2. Stale or wrong NatSpec in production contracts — fixed + +**Fixed by the split:** the 12 "This surcharge is not necessary if you do not use the MetaTxModule" comments +(there is no `MetaTxModule`, and the overrides are not optional) and the misplaced `ERC-2771` section header of +`RuleEngine.sol`. The `*2771` contracts carry accurate NatSpec on their overrides. + +**Still open (10 sites at the second pass; 9 after `B-2` fixed `_removeRule`):** + +| Site | Text | Problem | +|---|---|---| +| `RulesManagementModule.sol:186-188` (`_removeRule`) | "Revert if the rule found at the specified index does not match the rule in argument" | There is no index; describes a removed API — **fixed with `B-2`** | +| `RulesManagementModule.sol:201`, `:219` (`_transferred`) | "Go through all the rule to know if a restriction exists on the transfer" | These functions **enforce** (call `transferred`), they do not detect. The same sentence is correct on `detectTransferRestriction` (`RuleEngineBase.sol:87`) | +| `RulesManagementModule.sol:13` | `@title RuleEngine - part` | Placeholder title | +| `RuleEngineBase.sol:59` | `// Apply on RuleEngine` | Placeholder comment | +| `RuleEngineBase.sol:91` | "restricion" | Typo | +| `TokenBindingModule.sol:57`, `TokenBindingExtendedModule.sol:28`, `ERC3643ComplianceModule.sol:36` | `PUBLIC/public FUNCTIONS` | Should read `PUBLIC/EXTERNAL` like the other modules | +| `VersionModule.sol:20` | `/* ============ Events ============ */` | Empty section | + +**Verdict: implement** (comment-only). + +**Implemented after the second pass.** The 9 remaining sites, rewritten to say what the code does: + +| Site | Now reads | +|---|---| +| `RulesManagementModule` title | `@title RulesManagementModule`, with a one-line `@notice` on what the module holds | +| `RulesManagementModule._transferred` (x2) | "Applies every rule, in order, to an operation without / with a spender; reverts as soon as one rule rejects it" (enforcement, not detection) | +| `RuleEngineBase.transferred` (4-arg) | `// Every rule is applied; the first one that rejects the operation reverts it` | +| `RuleEngineBase.detectTransferRestriction` | "Queries every rule, in order, and returns the first restriction code that is not zero"; "restricion" -> "restriction" | +| `TokenBindingModule`, `TokenBindingExtendedModule`, `ERC3643ComplianceModule` | section header `PUBLIC/EXTERNAL FUNCTIONS`, like the other modules | +| `VersionModule` | empty `Events` section header removed | + +The same "restricion" typo was also fixed at 5 places in the mock rules (`RuleConditionalTransferLightMock` x2, +`RuleOperationRevertMock` x2, `RuleWhitelistMock`). Comment-only: no bytecode-relevant change; full suite +481/481, `forge fmt --check` clean. A final grep for the stale phrases in `src/` returns nothing. + +### G-3. The ERC-3643 mock still describes the pre-rc7 setup — fixed + +The test header was fixed at the first pass. `src/mocks/ERC3643TokenMock.sol:13-22` still says the reference is +"tag 4.1.3", that the real token "cannot be compiled into this test suite", that it pins 0.8.17 while "this +project compiles with 0.8.36", and that it depends on OpenZeppelin 4.8.x. All four claims are false since rc7: +T-REX 4.2.0-beta1 uses OpenZeppelin 5, pins 0.8.30, and **is** compiled by the `erc3643` profile. + +**Fixed after the second pass.** The header now names T-REX 4.2.0-beta1, says the real token is tested in +`test/ERC3643Real/` under the `erc3643` profile (solc 0.8.30, `onchain-id` stubs), and why the mock stays: it +runs in the default profile with no identity registry. The call sequence it describes (`setCompliance` unbind +then bind, `transfer` and `mint` checking `canTransfer` before `transferred` / `created`, `burn` calling +`destroyed`) was re-checked against `lib/ERC-3643/contracts/token/Token.sol` and still holds. Correction made +while writing it: a first draft said the mock did not reproduce T-REX's order of balance update and +notification; it does (balances first, then `created` / `destroyed`), and the header says so. A second slip, +caught by the compiler: writing the package name with its leading `@` in NatSpec is parsed as a tag +(`Error (6546)`), so the header names it `onchain-id/solidity`, as the original did. + +### G-4. CHANGELOG rc7 claimed the version string was the only `src/` change — fixed + +Removed at the first pass. + +### G-5. `RuleEngine-with-CMTAT.md` §4.7 still described every deployable as ERC-2771 — fixed + +Found in the second pass: §4.7 opened with "Every deployable inherits `ERC2771Context`" and told the reader to use +"`address(0)` if gasless administration is not needed". Both were true at the first pass and false after the +split. It now names the three `*2771` deployables and says to deploy the contract without the suffix when gasless +administration is not needed. The other forwarder passages (`doc/README.md`, `RuleEngine-with-ERC3643.md` §4.5, +`TokenBinding-module.md` §4) were checked and are consistent. + +## H. Weird behaviour + +### H-1. The view/enforcement divergence — carried, unchanged + +See the rc5 report. + +### H-2. Sender resolution after the ERC-2771 fix and the split — verified + +| Site | Resolves | Purpose | +|---|---|---| +| `TokenBindingModule.sol:149` (`_checkBoundToken`) | `msg.sender` | token identity | +| `TokenBindingExtendedModule.sol:99` (self-binding) | `msg.sender` | token identity | +| `onlyRole` / `onlyOwner` | `_msgSender()` | operators | + +In the three deployables without a forwarder, `_msgSender()` is OpenZeppelin `Context`, i.e. `msg.sender`; in the +three `*2771` contracts it unwraps the forwarder's suffix. `NoForwarderTestBase` checks, for the three +contracts without a forwarder, that a sender appended to the calldata is ignored and that `isTrustedForwarder` / +`trustedForwarder` do not exist. `ERC2771TokenGateTestBase` still runs on all three `*2771` contracts. + +### H-3. A `*2771` deployable accepts `address(0)` as its forwarder — decide + +`RuleEngine2771`, `RuleEngineOwnable2771` and `RuleEngineOwnable2Step2771` pass the forwarder straight to +`ERC2771ModuleStandalone` with no check. Before the split, a zero forwarder was the documented way to disable +ERC-2771. Now each access-control model has a dedicated contract without a forwarder, so a `*2771` deployed with +`address(0)` is always a misconfiguration: it carries the ERC-2771 surface and bytecode and relays nothing. Not +harmful (`isTrustedForwarder(address(0))` can never match a real caller). + +If adopted, the check belongs in the three `*2771` constructors, **not** in `ERC2771ModuleStandalone`: the mock +rules (`RuleAddressList`) use the module with a zero forwarder. The suites deploy `*2771` contracts with +`address(0)` in the aggregation and max-rules tests, which would move to a dummy forwarder. **Verdict: decide.** + +## I. Interface granularity + +`I-1`, `I-2` and `I-3` are carried from the rc6 report. rc7 changed none of the interfaces, so the conclusions +stand; `I-1` and `I-2` are restated below in full and re-verified against the final rc7 code (after `A-3`, `B-1`, +`B-2` and `D-2`), so this report can be read without the rc6 one. `I-3` (the engine should not call a rule's +`canTransfer` instead of `detectTransferRestriction`) is unchanged: the restriction code is the stronger primitive, +the engine owes the token a code, and calling both would let a rule contradict itself. + +### I-1. `IRule` demands two functions the engine never calls — fixed + +**What the gate requires.** `RuleEngineBase._checkRule` accepts a rule only if +`ERC165Checker.supportsInterface(rule, IRULE_INTERFACE_ID)` is true. `IRule` declares a single function of its +own (`canReturnTransferRestrictionCode`) and inherits everything else from CMTAT's `IRuleEngineERC1404`, so +`IRULE_INTERFACE_ID` (`RuleInterfaceId.sol:37`) is the XOR of the whole tree: `IRule`, `IRuleEngine`, +`IERC7551Compliance`, `IERC3643ComplianceRead`, `IERC3643IComplianceContract`, `IERC1404`, `IERC1404Extend` and +`IERC165`. Its value is `0x2497d6cb`, pinned by `test/RuleEngine/IRuleInterfaceId.t.sol:80`. + +**What the engine uses.** Of the eight functional selectors in that tree, the engine calls six: + +| Selector | Called by the engine? | Call site (final rc7 code) | +|---|---|---| +| `transferred(address,address,uint256)` | yes | `RulesManagementModule.sol:211` | +| `transferred(address,address,address,uint256)` | yes | `RulesManagementModule.sol:230` | +| `detectTransferRestriction(address,address,uint256)` | yes | `RuleEngineBase.sol:172` | +| `detectTransferRestrictionFrom(address,address,address,uint256)` | yes | `RuleEngineBase.sol:196` | +| `canReturnTransferRestrictionCode(uint8)` | yes | `RuleEngineBase.sol:221` | +| `messageForTransferRestriction(uint8)` | yes | `RuleEngineBase.sol:222` | +| `canTransfer(address,address,uint256)` (`0xe46638e6`) | **no** | — | +| `canTransferFrom(address,address,address,uint256)` (`0x7157797f`) | **no** | — | + +The two unused ones arrive through `IERC3643ComplianceRead` and `IERC7551Compliance` (the selector of +`canTransferFrom` is also the whole `IERC7551Compliance` id, `0x7157797f`, since that interface declares only this +function). The engine never asks a rule either question: its own `canTransfer` / `canTransferFrom` are computed +from its `detectTransferRestriction*` loops (`== TRANSFER_OK`). + +**Why it matters, in the order it bites:** + +- **Every rule author writes two views nothing in the engine path calls.** All four reference rules in + `src/mocks/rules/` implement them, and so must every rule in [CMTA/Rules](https://github.com/CMTA/Rules). +- **Least privilege.** A rule that only answers "is this restricted, and why" must also expose the + compliance-read surface of ERC-3643 and ERC-7551 to pass the gate. +- **It invites stubs, and stubs can disagree.** Nothing forces a rule's `canTransfer` to match its + `detectTransferRestriction`. A rule that returns `true` from a stubbed `canTransfer` passes the engine and + behaves correctly behind it, but advertises an answer that an integrator calling the rule directly would + trust (see `I-2` for when that happens). + +**The fix.** Declare in `IRule` the six selectors the engine consumes, and gate on that id: + +| Interface | Selectors | ID | +|---|---|---| +| Current `IRULE_INTERFACE_ID` | 8 functional + ERC-165 | `0x2497d6cb` | +| Narrowed `IRule` | 6 functional + ERC-165 | **`0xb1a69752`** | + +Recomputed in this pass: `0x2497d6cb ^ 0xe46638e6 ^ 0x7157797f = 0xb1a69752` (selectors from `cast sig`), the +same value the rc6 report obtained by computing the candidate interface directly. + +**Migration, which is what makes it a coordinated release rather than a local edit:** + +1. `IRule` stops inheriting `IRuleEngineERC1404` and declares the six functions itself (`transferred` x2, + `detectTransferRestriction`, `detectTransferRestrictionFrom`, `canReturnTransferRestrictionCode`, + `messageForTransferRestriction`), plus `IERC165`. This is this project's interface, not a published standard, + so narrowing it is legitimate; ERC-3643 and ERC-7551 themselves are untouched. +2. `IRULE_INTERFACE_ID` becomes `type(IRule).interfaceId ^ type(IERC165).interfaceId`, and + `IRuleInterfaceId.t.sol` pins `0xb1a69752`. +3. **Every rule in CMTA/Rules must advertise the new id before an engine running the new code accepts it.** + An engine on the new id rejects a rule that advertises only `0x2497d6cb` with `RuleEngine_RuleInvalidInterface`, + which would block `addRule` / `setRules` for every existing rule. A transition is possible: rules advertise + both ids for one release, so they work with old and new engines. +4. Rules that also want the standalone role (`I-2`) keep implementing `canTransfer` / `canTransferFrom` and keep + advertising `RULE_ENGINE_INTERFACE_ID`. Narrowing the engine's gate takes nothing away from them. + +**Limit.** ERC-165 expresses shape, never semantics: the narrowed id still cannot tell an allow-list from a +deny-list. That stays configuration discipline, and the change must not be presented as closing it. + +**Verdict: decide**, at a release where CMTA/Rules moves in step. Not a defect: the current gate is sound, +only broader than the engine needs. Not worth doing alone if the answer to `I-2` is "rules are meant to be +usable standalone", since every rule would then implement the two functions anyway; it is then documentation +value only. + +**Implemented after the second pass**, after `I-2` was resolved by supporting the standalone role. Narrowing still +pays off with that answer: the role is opt-in, so an engine-only rule no longer has to implement two views +nothing calls. + +- **Interface.** `IRule is IERC1404Extend, IERC3643IComplianceContract, IERC165` and declares the 4-argument + `transferred` and `canReturnTransferRestrictionCode` itself. The 4-argument `transferred` is declared rather + than inherited because its CMTAT home, `IRuleEngine`, also brings `IERC7551Compliance` (`canTransferFrom`). + `IERC1404Extend` keeps the `REJECTED_CODE_BASE` enum available to rules. +- **ID.** `IRULE_INTERFACE_ID = type(IRule).interfaceId ^ IERC3643IComplianceContract ^ IERC1404 ^ + IERC1404Extend ^ IERC165 = 0xb1a69752`, the value specified above. Pinned by + `testInterfaceIdConstantsMatchTheirWireValues`; `testIRuleIdExcludesTheComplianceReads` checks that the old + value is exactly the new one XOR `canTransfer` (`0xe46638e6`) and `canTransferFrom` (`0x7157797f`). +- **Migration: strict, by decision of the maintainer.** The engine accepts only `0xb1a69752`. A fallback + accepting `0x2497d6cb` as well was considered (the old interface is a superset, so it would be safe) and + declined. Consequence: **every rule from CMTA/Rules must advertise the new ID before an rc7 engine accepts + it**; a rule advertising both works with old and new engines. Pinned on all six deployables by + `testRuleAdvertisingOnlyTheLegacyIdIsRejected` (`test/utils/LegacyIRuleIdProbe.sol`); checked that the test + can fail: an engine that also accepts the old ID fails it six times. +- **Reference rules** implement `IRuleEngineERC1404` on top of `IRule` to keep the standalone role of `I-2`; + the 4-argument `transferred` then appears in both `IRule` and `IRuleEngine` and needs + `override(IRule, IRuleEngine)`. **Test probes** `RuleCodeProbe` and `SupplyCapProbeRule` implement only + `IRule`, without `canTransfer*`, and are accepted on all six deployables + (`testEngineOnlyRuleWithoutComplianceReadsIsAccepted`, and every rule-aggregation and real-T-REX test). +- **Verified:** full suite 460/460, `FOUNDRY_PROFILE=erc3643 forge test` 13/13, production coverage 100% (lines, + statements, branches 48/48, functions). + +**Revised: the legacy ID is accepted after all (maintainer decision).** The strict gate above was reversed so +that rules built before rc7 keep working without a coordinated release. The bullet "Migration: strict" is +superseded; the rest stands. + +- **Gate.** `RuleEngineBase._checkRule` now calls a new `internal view virtual` hook, + `_supportsRuleInterface(rule)`: it checks ERC-165 support once (`ERC165Checker.supportsERC165`, which also + rejects a contract answering `true` to `0xffffffff`), then `IRULE_INTERFACE_ID`, then, only if that fails, + `IRULE_LEGACY_INTERFACE_ID`. Accepting the legacy ID is safe: it describes a superset of the current interface + (the same six functions plus `canTransfer` / `canTransferFrom`), and the engine calls only the six. +- **Constant.** `RuleInterfaceId.IRULE_LEGACY_INTERFACE_ID = IRULE_INTERFACE_ID ^ IERC3643ComplianceRead ^ + IERC7551Compliance = 0x2497d6cb`, computed like the others and pinned by + `testIRuleIdExcludesTheComplianceReads`. +- **Tests, on all six deployables** (`RuleAggregationTestBase`): `testRuleAdvertisingOnlyTheLegacyIdIsAccepted` + (was `...IsRejected`), and three negative tests: `testRuleAdvertisingNoRuleIdIsRejected`, + `testRuleClaimingEveryInterfaceIsRejected`, `testRuleWithoutErc165IsRejected` (an EOA). Checked that they can + fail: removing the legacy fallback fails 6 tests, removing the ERC-165 pre-check fails 6 (the + claim-everything case; the EOA case alone would not catch it, since a call to an EOA returns no data and + reads as `false`). +- **Gas.** `addRule` with a current-ID rule: 68,069 -> 68,005 (−64), since ERC-165 support and the ID are now + queried in one pass. A legacy rule pays one more `staticcall` (not isolated). +- **Verified:** full suite 481/481, `FOUNDRY_PROFILE=erc3643 forge test` 13/13, production coverage 100% (lines, + statements, branches 49/49, functions). + +The limit stated above still holds: the narrowed ID describes shape, not semantics. + +### I-2. Rules advertise the standalone engine role, but nothing tests or documents it — fixed + +**What is advertised.** All four reference rules answer `true` to `supportsInterface(RULE_ENGINE_INTERFACE_ID)` +(`RuleWhitelistMock.sol:62`, `RuleConditionalTransferLightMock.sol:130`, `RuleMintAllowanceMock.sol:125`, +`RuleOperationRevertMock.sol:64`). Because `IRule is IRuleEngineERC1404`, a rule also has the whole engine-facing +surface. So a single rule can be given to a CMTAT token **as its rule engine**, with no RuleEngine in between. + +**Why nothing stops it.** CMTAT's `setRuleEngine(IRuleEngine)` (`ValidationModuleRuleEngine.sol:48`) checks only +that the value changes, then stores it (`ValidationModuleRuleEngineInternal._setRuleEngine`); it performs **no +ERC-165 check**. The token then calls the rule directly: `canTransfer` / `canTransferFrom` from +`_canTransferWithRuleEngine` / `_canTransferFrom` (`:129`, `:117`) and `transferred` from +`_callRuleEngineTransferred` (`:182`). This is the one configuration in which `canTransfer` and +`canTransferFrom` (`I-1`) are actually called on a rule. + +**What is missing, checked in this pass:** + +- **No test.** The three `setRuleEngine` calls in the suite (`test/RuleWhitelist/CMTATIntegrationBase.sol:47`, + `test/RuleEngine/RulesManagementModuleTest/CMTATIntegrationBase.sol:41`, + `RuleEngineOperationRevertBase.sol:32`) all pass a `RuleEngine`, never a rule. +- **No documentation.** Neither `README.md`, `doc/README.md`, `RuleEngine-with-CMTAT.md` nor + `RuleEngine-with-ERC3643.md` describes a rule used without an engine. + + **Correction (found while implementing):** this bullet is wrong for `doc/README.md`. Its §Available Rules + already says rules can be used "Directly on CMTAT (single-rule setup, no RuleEngine orchestration)", and warns + that `RuleConditionalTransferLightMultiToken` must be set directly on each token, so the role is used by a + production rule. The search behind the bullet used phrasings ("standalone rule", "without an engine") that did + not match. What was missing was the technical guide (what a rule must do to play the role) and a test, not any + mention at all. +- **The id is hardcoded.** Each mock declares its own `RULE_ENGINE_INTERFACE_ID = 0x20c49ce7` literal instead + of importing `CMTAT/library/RuleEngineInterfaceId.sol`. The value matches CMTAT today, but it is the hardcoded + pattern `F-2` removed elsewhere in rc6: a CMTAT interface change would leave the mocks advertising a stale id + with no test failing. +- **Not checked:** whether the production rules in CMTA/Rules advertise `RULE_ENGINE_INTERFACE_ID`. + +**What the missing test would have to establish**, because the standalone role differs from the engine role: + +- **Who calls `transferred`.** Behind an engine, only a bound token reaches the engine, and the engine calls + the rule. Standalone, the token calls the rule directly. The rule must accept that caller. +- **There is no `onlyBoundToken` in front of the rule.** The engine's bound-token gate does not exist + standalone, and the stateful reference rules have no caller check of their own: + `RuleConditionalTransferLightMock.transferred` (`:94`) and `RuleMintAllowanceMock.transferred` (`:98`) are + `public` with no restriction. **Any account can call them directly** and consume a transfer approval or a + minter's allowance, blocking the real operation. This is true **with or without an engine**, because a direct + call to the rule never goes through the engine at all. These are reference mocks, not production rules + (`CLAUDE.md`, invariant 8), so it is recorded here rather than as a security finding; the obligation for a + production stateful rule is to restrict `transferred` to its engine (or, standalone, its token). Whether the + CMTA/Rules rules do so was not checked. +- **Codes and messages reach the token.** The token's `detectTransferRestriction` / + `messageForTransferRestriction` must return the rule's own code and message. +- **ERC-3643 is a different case.** An ERC-3643 token calls `created` / `destroyed` and binding functions that a + rule does not implement, so a rule cannot stand in for the engine there. The standalone role is CMTAT-only. + +**Options:** + +1. **Support it deliberately:** one CMTAT integration test per reference rule (`setRuleEngine(rule)`, then a + transfer, a refused transfer with its code and message, and for the stateful rules a mint or approved + transfer), a paragraph in `RuleEngine-with-CMTAT.md` stating what a rule must do to be used standalone + (caller restriction on `transferred`, `canTransfer` consistent with `detectTransferRestriction`), and the + mocks importing `RuleEngineInterfaceId`. +2. **Withdraw it:** rules stop advertising `RULE_ENGINE_INTERFACE_ID`, and the docs state that a rule is used + only behind a RuleEngine. This does not stop a determined integrator (`setRuleEngine` checks nothing), but + the rule no longer claims the role. Combined with `I-1`, rules then also drop `canTransfer` / + `canTransferFrom`. + +**Verdict: decide**, together with `I-1`, since they are the same question seen from two sides: is a rule +only an engine plug-in, or also a minimal engine? Option 1 matches what the code advertises today and is the +smaller change in this repository; option 2 is the cleaner interface, and needs CMTA/Rules to move in step. + +**Implemented after the second pass: option 1.** Chosen because it matches what the rules already advertise and +because a production rule (`RuleConditionalTransferLightMultiToken`) already depends on the role. + +- **Tests:** `test/RuleStandalone/RuleStandaloneCMTAT.t.sol`, 9 tests on a real `CMTATStandardStandalone` with a + reference rule passed to `setRuleEngine` and no RuleEngine: all four rules advertise + `RULE_ENGINE_INTERFACE_ID`; whitelist transfer allowed, refused with code 22 and its message through the + token's `detectTransferRestriction` / `messageForTransferRestriction` / `canTransfer`, and `transferFrom` + refused on the spender (code 23, 4-argument `transferred`); conditional transfer refused with code 71, then + approved, executed once and refused again (the approval is consumed by the token's call); mint allowance + consumed by `mint` (minter as spender) and refused past the allowance, transfers unaffected; reverting rule + blocking the transfer with its own error. Checked that the suite can fail: removing + `RULE_ENGINE_INTERFACE_ID` from `RuleWhitelistMock.supportsInterface` fails one test, and making its + `canTransfer` return `true` fails another. Full suite 447/447 (438 + 9). +- **Documentation:** new `RuleEngine-with-CMTAT.md` §4.8 "A single rule can be the token's rule engine": what + the token calls, why there is no bound-token gate, the obligations on a rule (restrict `transferred` for a + stateful rule, keep `canTransfer*` consistent with `detectTransferRestriction*`), one rule only, CMTAT only. + §5 lists the new suite. The `doc/README.md` bullet links to §4.8; `CLAUDE.md` / `AGENTS.md` list + `test/RuleStandalone/` and add the obligation to "Adding a new rule". +- **Hardcoded ids:** the four mocks import `RuleEngineInterfaceId` and `ERC1404ExtendInterfaceId` from CMTAT + instead of declaring `0x20c49ce7` / `0x78a8de7d` literals, so a CMTAT interface change reaches them. +- **Left as is:** the stateful mocks still accept `transferred` from any caller. Restricting it would change the + mocks' constructors and every test that deploys them, and they are documented as test doubles. Noted on the + way: `RuleConditionalTransferLightMock` already grants a `RULE_ENGINE_CONTRACT_ROLE` in its constructor but never + checks it, so the role is dead in the mock. Whether the CMTA/Rules production rules restrict `transferred` was + not checked. + +## J. Modularity + +### J-1. The binding registry embeds in a foreign host — re-verified by example + +**What is claimed.** rc6 split token binding out of the ERC-3643 code so it can be reused by any project that has +to bind tokens: `TokenBindingModule` (bind, unbind, `isTokenBound`, the `onlyBoundToken` guard) and +`TokenBindingExtendedModule` (batch binding, token self-binding, `getTokenBounds`) depend only on OpenZeppelin +(`Context`, `EnumerableSet`), and leave one hook to the host, `_onlyTokenBindingManager()`. +`TokenBindingStandaloneMock` and `test/TokenBinding/` (10 tests) keep a minimal host compiling. + +**Why re-check in rc7.** The inheritance of the two modules is unchanged since rc6, but rc7 touched their code +(`E-2`, the ERC-2771 `msg.sender` fix) and raised the pragma to `^0.8.27` (`F-1`), so a host now needs solc 0.8.27 +or later. The rc6 probes were re-run on the final rc7 code rather than carried on trust. + +**Method.** Two example hosts written in `src/` (so they compile with the project's remappings), built alone with +`forge build `, then deleted. They are examples of plausible reuse, not an exhaustive list. The errors are +graded as in the modularity check: `Error (6480)` ("derived contract must override") is an inconvenience the +integrator fixes with an override; `Error (5005)` ("linearization of inheritance graph impossible") is a blocker +that no glue can fix. + +**Example 1: an unrelated host with its own ERC-2771 forwarder and RBAC.** + +```solidity +contract Probe1 is ERC2771Context, AccessControl, TokenBindingExtendedModule { + constructor(address fwd, address admin) ERC2771Context(fwd) { _grantRole(DEFAULT_ADMIN_ROLE, admin); } + function _onlyTokenBindingManager() internal virtual override onlyRole(DEFAULT_ADMIN_ROLE) {} + // + _msgSender / _msgData / _contextSuffixLength, override(ERC2771Context, Context) +} +``` + +**Example 2: a CMTAT token embedding the registry itself**, using one deployment version, +`CMTATStandardStandalone` (it already carries ERC-2771, AccessControl, ERC-7551 and its own `Context` overrides). + +```solidity +contract Probe2 is CMTATStandardStandalone, TokenBindingModule { // also tried with TokenBindingExtendedModule + constructor(...) CMTATStandardStandalone(fwd, admin, erc20, extra, engines) {} + function _onlyTokenBindingManager() internal virtual override onlyRole(DEFAULT_ADMIN_ROLE) {} + // + _msgSender / _msgData / _contextSuffixLength, override(CMTATBaseERC7551Enforcement, Context) +} +``` + +**Results** (solc 0.8.37, optimizer on, 200 runs, `evm_version = osaka`, as in `foundry.toml`): + +| Example | Without the three overrides | With them | Runtime size (EIP-170 limit 24,576 B) | +|---|---|---|---| +| 1. ERC-2771 + RBAC host + `TokenBindingExtendedModule` | 3 x `Error (6480)` | **compiles** | 3,655 B | +| 2. `CMTATStandardStandalone` + `TokenBindingModule` | 3 x `Error (6480)` | **compiles** | 23,864 B (712 B left) | +| 2b. `CMTATStandardStandalone` + `TokenBindingExtendedModule` | 3 x `Error (6480)` | **compiles** | 24,902 B (326 B over) | +| Reference: `CMTATStandardStandalone` alone | — | — | 23,111 B | + +**Reading the examples:** + +- **No `Error (5005)`.** The modules' bases linearize with an unrelated host and with a full CMTAT token, which is + the property the reuse claim rests on. The only work left to the integrator is the hook and the three `Context` + overrides, which any contract combining ERC-2771 with another `Context` user writes anyway. +- **In a CMTAT host, the overrides name the CMTAT contract that declares them** (`CMTATBaseERC7551Enforcement` for + the Standard version), not the deployment contract: naming `CMTATStandardStandalone` fails with + `Error (4327)` / `(2353)`. +- **Contract size is a property of the host, not of the module.** The registry adds about 750 B of runtime code + (`TokenBindingModule`) or about 1,790 B (`TokenBindingExtendedModule`) to this host. Whether that fits depends + on the CMTAT deployment version chosen. CMTAT ships many (Light, Standard, Allowlist, Debt, DebtEngine, + ERC-1363, ERC-7551, HolderList, Permit, Snapshot, each Standalone and Upgradeable), with different module sets + and therefore different sizes; an upgradeable version behind a proxy is measured on its implementation, and + compiler settings change the result as well. So 2b being over the limit is specific to + `CMTATStandardStandalone` at these settings; another version may fit with the extended module, or not fit + with the base one. An integrator checks the size of their own composition (`forge build --sizes`). + +**Verdict: reuse claim confirmed.** No code change, and no general size limit to document: the examples above +are recorded as evidence. `TokenBindingStandaloneMock` and `test/TokenBinding/` remain the compiling fixture that +stops the linearization property from regressing. + +### J-2. ERC-2771 in the shared layer blocked a host with its own forwarder — fixed by the split + +The skill this review follows lists "meta-transaction bases in the shared layer" as a reuse hazard: ERC-2771 is a +deployment decision, and a host usually has its own. Up to the split, `RuleEngineOwnableShared` inherited +`ERC2771ModuleStandalone`, so every ownable engine carried an `ERC2771Context` with its own constructor argument. + +**Probe** (written in `src/`, built with only its imports, deleted afterwards): a host that brings OpenZeppelin's +`ERC2771Context` and embeds the ownable engine. + +```solidity +contract ProbeHost is ERC2771Context, RuleEngineOwnable { + constructor(address owner_, address fwd) ERC2771Context(fwd) RuleEngineOwnable(owner_, address(0)) {} + // + the three Context overrides any ERC-2771 host writes +} +``` + +| Code | Result | +|---|---| +| Pre-split (`4946c87`, engine constructor `(owner, forwarder, token)`) | **`Error (3364)`: "Base constructor arguments given twice"**, plus override errors (`2353`, `4327`) | +| Final rc7 (`3b94564`) | **compiles** | + +`Error (3364)` is the blocking class: no override or ordering fixes it, because `ERC2771Context` is constructed +by both the host and the engine. Before the split the host could only drop its own forwarder and accept the +engine's immutable one. Now it embeds `RuleEngineOwnable` (or `RuleEngine`) and supplies its own. **Fixed by the +split**, and kept as a regression guard in spirit by `NoForwarderTestBase`, which pins that the plain deployables +carry no ERC-2771 surface. + +## K. Tests + +### K-1. Correctness of the existing tests + +- **Tautologies:** none. **Bare `vm.expectRevert()`:** 0 (2 fixed at the first pass). +- **A negative test for every guard.** Every custom error in `src/` is reached by an `expectRevert`, except + `RuleEngine_RulesManagementModule_OperationNotSuccessful`, which was unreachable (`B-2`; removed since). The constructor guards + of the new contracts are covered: zero admin (`RuleEngine_AdminWithAddressZeroNotAllowed`) and zero owner + (`OwnableInvalidOwner`) for all six deployables, through the deployment suites and `ERC2771VariantTestBase`. +- **Through the public surface.** The shared suites assert observable behaviour (revert data, `isTokenBound`, + `supportsInterface` compared between the two contracts of a pair) rather than recomputing internals. + +### K-2. Coverage, measured + +`forge coverage --no-match-coverage "(mocks|test|script)" --report summary`, second pass: + +| Contract | Lines | Statements | Branches | Funcs | +|---|---|---|---|---| +| `RuleEngineBase.sol` | 100% (51/51) | 100% (62/62) | 100% (5/5) | 100% (14/14) | +| `RuleEngineAccessControlShared.sol` | 100% (18/18) | 100% (15/15) | 100% (7/7) | 100% (7/7) | +| `RuleEngineOwnableShared.sol` | 100% (10/10) | 100% (11/11) | 100% (2/2) | 100% (3/3) | +| `RuleEngine2771.sol` | 100% (6/6) | 100% (6/6) | — | 100% (3/3) | +| `RuleEngineOwnable.sol` | 100% (6/6) | 100% (2/2) | — | 100% (4/4) | +| `RuleEngineOwnable2771.sol` | 100% (6/6) | 100% (6/6) | — | 100% (3/3) | +| `RuleEngineOwnable2Step.sol` | 100% (9/9) | 100% (6/6) | — | 100% (5/5) | +| `RuleEngineOwnable2Step2771.sol` | 100% (6/6) | 100% (6/6) | — | 100% (3/3) | +| `ERC3643ComplianceModule.sol` | 100% (6/6) | 100% (6/6) | 100% (2/2) | 100% (2/2) | +| `ERC3643ComplianceExtendedModule.sol` | 100% (2/2) | 100% (1/1) | — | 100% (1/1) | +| `RulesManagementModule.sol` | 100% (64/64) | 100% (60/60) | **86.67% (13/15)** | 100% (19/19) | +| `TokenBindingModule.sol` | 100% (24/24) | 100% (16/16) | 100% (7/7) | 100% (9/9) | +| `TokenBindingExtendedModule.sol` | 100% (24/24) | 100% (25/25) | 100% (5/5) | 100% (7/7) | +| `VersionModule.sol` | 100% (2/2) | 100% (1/1) | — | 100% (1/1) | +| **Total** | **100% (234/234)** | **100% (223/223)** | **95.35% (41/43)** | **100% (81/81)** | + +`RuleEngine.sol` has no row: its constructor only forwards to `RuleEngineAccessControlShared`, so it holds no +statement of its own. The two uncovered branches are the same as at the first pass, both **dead code** (`B-2`): +the false sides of `require(_rules.add(...), OperationNotSuccessful())` (`RulesManagementModule.sol:181`) and +`require(_rules.remove(...), OperationNotSuccessful())` (`:194`). + +**After `B-2`:** both `require`s now carry the reachable error (`RuleAlreadyExists`, `RuleDoNotMatch`) and the +dead `contains()` checks are gone. Re-run: lines 232/232, statements 222/222, **branches 40/40**, functions 81/81. + +**Final rc7 code** (after `D-2`, `E-2`, `I-1`, `G-2` and the `K-5` invariants; the second-pass table above is kept +as measured, with `RuleEngineAccessControlShared.sol`, since folded into `RuleEngine.sol`): + +| Contract | Lines | Statements | Branches | Funcs | +|---|---|---|---|---| +| `RuleEngineBase.sol` | 100% (56/56) | 100% (69/69) | 100% (7/7) | 100% (15/15) | +| `RuleEngineOwnableShared.sol` | 100% (9/9) | 100% (10/10) | 100% (3/3) | 100% (3/3) | +| `accessControl/RuleEngine.sol` | 100% (18/18) | 100% (15/15) | 100% (7/7) | 100% (7/7) | +| `accessControl/RuleEngine2771.sol` | 100% (6/6) | 100% (6/6) | — | 100% (3/3) | +| `ownable/RuleEngineOwnable.sol` | 100% (6/6) | 100% (2/2) | — | 100% (4/4) | +| `ownable/RuleEngineOwnable2771.sol` | 100% (6/6) | 100% (6/6) | — | 100% (3/3) | +| `ownable/RuleEngineOwnable2Step.sol` | 100% (9/9) | 100% (6/6) | — | 100% (5/5) | +| `ownable/RuleEngineOwnable2Step2771.sol` | 100% (6/6) | 100% (6/6) | — | 100% (3/3) | +| `ERC3643ComplianceExtendedModule.sol` | 100% (2/2) | 100% (1/1) | — | 100% (1/1) | +| `ERC3643ComplianceModule.sol` | 100% (6/6) | 100% (6/6) | 100% (2/2) | 100% (2/2) | +| `RulesManagementModule.sol` | 100% (57/57) | 100% (52/52) | 100% (17/17) | 100% (19/19) | +| `TokenBindingExtendedModule.sol` | 100% (24/24) | 100% (25/25) | 100% (5/5) | 100% (7/7) | +| `TokenBindingModule.sol` | 100% (23/23) | 100% (15/15) | 100% (8/8) | 100% (9/9) | +| `VersionModule.sol` | 100% (2/2) | 100% (1/1) | — | 100% (1/1) | +| **Total** | **100% (230/230)** | **100% (220/220)** | **100% (49/49)** | **100% (82/82)** | + +`RuleEngine.sol` now has a row of its own: it holds the RBAC logic since `D-2`. The branch count rose 40 -> 49 with +`E-2` (each `require` is a branch) and `I-1` (the ERC-165 pre-check and the legacy-ID fallback); every one is +covered. 505 tests. + +### K-3. Mutation testing + +**First pass (`4946c87`, 33 mutants).** 4 of 32 survived the suite as it stood: a rule returning code 1 ignored +(M01), the message taken from `rule(0)` (M03), `from` / `to` swapped in `created` (M05) and `destroyed` (M06). An +added mutant (M33, no `TokenSelfBindingApprovalSet`) also survived. The tests written for `K-6` killed all five. +M05 / M06 were also killed by the real T-REX suite, which CI does not run (`K-4`). Those 33 mutants target files +the split did not change, apart from code that moved, which the second pass re-targets. + +**Second pass (`3b94564`, 17 mutants on the moved and new code).** + +**All 17 killed.** Failing tests per mutant are counted once each: + +| Mutant | Change | Failing tests | +|---|---|---| +| N01 | `RuleEngineAccessControlShared` constructor accepts a zero admin | 2 | +| N02 | RBAC constructor ignores `tokenContract` | 23 | +| N03 | RBAC `grantRole`: a rule may receive a role | 3 | +| N04 | RBAC `hasRole`: the admin loses its implicit roles | 18 | +| N05 | RBAC constructor emits no initial `SetMaxRules` | 2 | +| N06 | RBAC `_onlyRulesLimitManager` accepts `RULES_MANAGEMENT_ROLE` | 2 | +| N07 | `RuleEngine2771._msgSender` ignores the forwarder | 3 | +| N08 | `RuleEngineOwnable2771._msgSender` ignores the forwarder | 3 | +| N09 | `RuleEngineOwnable2Step2771._msgSender` ignores the forwarder | 3 | +| N10 | `RuleEngine2771._msgData` keeps the suffix | 1 | +| N11 | `RuleEngineOwnable2771._msgData` keeps the suffix | 1 | +| N12 | `RuleEngineOwnable2Step2771._contextSuffixLength` returns 0 | 4 | +| N13 | `RuleEngineOwnableShared` constructor ignores `tokenContract` | 7 | +| N14 | `RuleEngineOwnableShared` constructor emits no initial `SetMaxRules` | 4 | +| N15 | Ownable: a rule may become owner | 2 | +| N16 | Ownable ERC-165: drops ERC-173 | 3 | +| N17 | `RuleEngineOwnable2Step` ERC-165: drops the two-step id | 1 | + +The thinnest margins are N10, N11 and N17, each caught by a single test (`testMsgDataStripsTheRelayedSender` per +`*2771` pair, and the `Ownable2Step` interface test). They are still real assertions on the exact property, so no +test was added. Across both passes, **50 mutants, 0 surviving** against the current suite. + +### K-4. CI never runs the real ERC-3643 suite — fixed + +`.github/workflows/ci.yml` runs `forge test -vvv` and `npx hardhat test`. `test/ERC3643Real/` is in the default +profile's `skip` list, so its 13 tests are never run by CI, although they caught M05 / M06 at the first pass. +**Fix:** a step running `FOUNDRY_PROFILE=erc3643 forge test`. **Verdict: implement.** + +**Implemented after the second pass.** `.github/workflows/ci.yml` has a step "Run Forge tests against the real +ERC-3643 token" (`FOUNDRY_PROFILE=erc3643 forge test -vvv`) right after the default `forge test`. The vendored +token comes from the `lib/ERC-3643` submodule, which the existing `forge install` step initialises, and its +`@onchain-id` imports resolve to the stubs in `test/utils/onchainid/`, so no extra install is needed. Checked +locally: the workflow parses, and the command passes 13/13. **Not checked:** a run on GitHub Actions itself. + +### K-5. Fuzz and invariant tests — written + +| Property | Kind | Where | +|---|---|---| +| `detectTransferRestriction` returns the first non-zero code in rule order, and `canTransfer == (code == 0)` | **fuzz** (`uint8 × uint8`, 256 runs) × 6 deployables | `RuleAggregationTestBase.testFuzz_DetectReturnsFirstNonZeroCode` | +| The 4-argument view uses the rules' 4-argument answers | **fuzz** × 6 | `testFuzz_DetectFromReturnsFirstNonZeroCode` | +| Codes 1 and 255 are reported | spot-checked | `testBoundaryCodesAreReported` | +| Each `*2771` contract advertises the same ERC-165 ids as its counterpart | spot-checked over 13 ids × 3 pairs | `ERC2771VariantTestBase` | +| The rule set never holds a duplicate or `address(0)`, and every member advertises a rule ID | **invariant** × 6 | `invariant_RuleSetIsWellFormed` | +| The rule set and `rulesCount()` match what the successful calls imply | **invariant** × 6 | `invariant_RuleSetMatchesModel` | +| `maxRules()` is the last value set and never 0 | **invariant** × 6 | `invariant_MaxRulesMatchesModelAndIsNotZero` | +| A token is bound iff the successful calls imply it; `getTokenBounds()` agrees, no duplicate, no `address(0)` | **invariant** × 6 | `invariant_BoundTokensMatchModel` | + +`rulesCount() <= maxRules()` is deliberately **not** an invariant: lowering the cap below the current count is +allowed and tested. + +**Invariants implemented after the second pass.** `test/utils/RuleEngineInvariantTestBase.sol` holds a handler, +`RuleEngineHandler`, and the four invariants; a short `RuleEngineInvariant.t.sol` in each of the six +`test/RuleEngine*/` directories deploys the variant. + +- **Handler.** It is the only fuzz target. It calls, as the admin/owner, `addRule`, `removeRule`, `setRules` (0 to 2 + rules), `clearRules`, `setMaxRules` (0 to 6), `bindToken`, `unbindToken`, `bindTokens`, `unbindTokens`, with + inputs drawn from small pools so that collisions are frequent: four valid rules, one rule advertising only the + legacy ID, one ERC-165 contract with no rule ID, `address(0)`; four tokens and `address(0)`. Each call is in + `try/catch`; on success the handler updates its own model from the call's semantics (for example `setRules` + clears the model, then adds), never by reading the engine. A reverted call must leave both unchanged. +- **Invariants** (checked after every call): the four rows above. The model comparison is what makes them more + than restatements: `containsRule`, `rulesCount`, `isTokenBound` and `getTokenBounds` read storage, while the + model is derived from which calls succeeded. +- **Shown to fail.** Three mutants, each caught by the expected invariant on `RuleEngine`: `_setMaxRules` without + its zero check (`maxRules is zero`), `_unbindToken` that does not remove the token (`getTokenBounds().length: + 1 != 0`), `_removeRule` that does not remove the rule (`rulesCount: 3 != 2`). Source restored after each. +- **Budget.** At Foundry's defaults (256 sequences of 500 calls) the six suites took 4 min 43 s, against 0.1 s for + the rest of the suite. `foundry.toml` sets `invariant = { runs = 64, depth = 50 }` (about 3 s for the six); the + file comment gives the environment variables for a deeper run. All four invariants also passed once at the + defaults (128,000 calls each, six deployables). + +### K-6. Tests written + +| Pass | Test | Deployables | Covers | +|---|---|---|---| +| 1 | `RuleCodeProbe` + `RuleAggregationTestBase` (7 tests) | 6 (3 at the first pass) | M01, M03, M05, M06 | +| 1 | `testSetTokenSelfBindingApprovalEmitsEvent` | 3 access-control models | M33 | +| 1 | `testCannotBindTokensBatchWithDuplicateToken` | RBAC | duplicate-in-batch edge case | +| 1 | Bare `expectRevert()` made specific | — | `K-1` | +| split | `ERC2771VariantTestBase` (5 tests), `NoForwarderTestBase` (2 tests) | 3 + 3 | `H-2`, `F-2`, `J-2` | + +### K.3 edge cases, by family + +| Family | Status | Missing / written | +|---|---|---| +| Zero and identity | `address(0)` rule, token, admin/owner for all six deployables: tested. `created` / `destroyed` zero-address side: written | Zero **forwarder** on a `*2771`: accepted, see `H-3` | +| Boundaries | cap exact, cap + 1, lowered cap, `rule(i)` out of range, empty `setRules`, codes 1 and 255: tested | Empty `bindTokens` / `unbindTokens` / approval batch: no test; the expected value is now a no-op (`C-3`, revised) | +| Duplicates and order | duplicate in `setRules` and inside one bind batch, rule order for detect / message / enforcement: tested | — | +| State transitions | unbind then callback, re-bind, clear then add, ownership hand-over, approval revoked: tested | — | +| Authorization | unauthorized caller per protected function, rule as role holder or owner, relayed forwarder (`*2771`), appended sender ignored (no forwarder): tested | — | +| Reentrancy | the obligation is on the rule (`RuleEngine-with-CMTAT.md` §4.6); not tested at engine level | — | +| Events | all 8 asserted; initial `SetMaxRules` for all six deployables | — | diff --git a/doc/security/audits/tools/v3.0.0-rc7/CLAUDE_AUDIT.md b/doc/security/audits/tools/v3.0.0-rc7/CLAUDE_AUDIT.md new file mode 100644 index 00000000..3855aec9 --- /dev/null +++ b/doc/security/audits/tools/v3.0.0-rc7/CLAUDE_AUDIT.md @@ -0,0 +1,405 @@ +# RuleEngine v3.0.0-rc7 — Claude Security Audit + +| | | +|---|---| +| **Tool** | Claude (Anthropic), driven by a set of custom smart-contract security-audit skills | +| **Codebase** | CMTA RuleEngine, branch `dev`, commit `51d0337` (final rc7 code) | +| **Scope** | `src/` without `src/mocks/`: `RuleEngineBase`, the modules, the six deployables | +| **Severity** | Code4rena scale: High / Medium / Low / Informational | +| **Date** | 2026-10-15 | + +**Method.** Threat model of the actors and entry points, enumeration of the privileged surface with Slither's +call-graph, inheritance and function-summary printers, targeted review of each threat, executable proofs of +concept in the project's own test suite, mutation checks of the new tests, and an adversarial pass by a separate +agent whose task was to dismiss or downgrade every finding. The specific internal skills used are intentionally +not enumerated here. + +This is a security review, not a formal audit. It complements the rc7 code-quality review +([CLAUDE_ANALYSIS.md](./CLAUDE_ANALYSIS.md)) and the Slither and Aderyn reports in this directory. + +## 1. Scope & Methodology + +**In scope:** `src/RuleEngineBase.sol`, `src/RuleEngineOwnableShared.sol`, `src/modules/**`, `src/interfaces/**`, +and the six deployables in `src/deployment/accessControl/` and `src/deployment/ownable/`. + +**Out of scope:** `src/mocks/` (reference rules and test doubles), the CMTAT and T-REX token contracts, the +production rules maintained in [CMTA/Rules](https://github.com/CMTA/Rules), deployment scripts. + +**Trust model.** The admin or owner, the rules manager, the compliance manager, the rule contracts and the trusted +ERC-2771 forwarder (for administrative calls) are trusted. A bound token is an address the manager chose. Anyone +can call the views. The engine holds no funds; its assets are authority: which rules run, which tokens may drive +them, and the codes and messages the views report. + +**Steps.** + +1. Threat model: 27 threats in seven groups (access control, token binding, rule execution, interfaces, + forwarder, token-side integration, upgradeability), each with an ID and an initial severity. +2. Privileged surface from the Slither printers: every state-changing external function of the six deployables + and its guard. +3. Review of each threat against the code and the documentation. +4. Tests: 105 new tests integrated in the suite, following its convention (a shared base in `test/utils/`, a short + file per deployable), run in a Docker container (Foundry 1.5.1). +5. Mutation check: three deliberately broken versions of the code, each caught by a new test. +6. Adversarial pass, then correction of the findings. + +## 2. Executive Summary + +**0 Critical, 0 High, 0 Medium, 0 Low, 3 Informational** (F-1, F-2, F-3), plus one item already open in the +code-quality review (F-5). F-1, F-2 and F-3 have since been fixed (section 6); F-5 remains open. The first pass rated F-1 and F-2 Low; the adversarial pass downgraded them, and +dismissed three other items as documented behaviour (F-4, F-6, F-7). + +**Cleared hypotheses.** These would have been High or Medium had they held; each was probed and does not: + +- **An admin entry point callable without its guard.** Eleven administrative functions, six deployables, a + fuzzed caller (256 runs each): every one rejects every other caller with the exact error of its guard. +- **An unbound caller driving the rules.** `transferred` (3 and 4 arguments), `created` and `destroyed` reject + every caller that is not a bound token, fuzzed on all six deployables. +- **The trusted forwarder posing as a token.** Fixed earlier in rc7: token identity is `msg.sender`; covered by the + existing ERC-2771 token-gate suites. +- **A rule reconfiguring the engine from its callback.** A rule that calls `addRule` from `transferred` is rejected, + because rule accounts hold no role or ownership; the token operation reverts. +- **The ERC-165 gate fooled.** A contract claiming every interface, or one without ERC-165, is rejected. +- **No low-level hazard in `src/`:** no `unchecked` block, assembly, signature check, `delegatecall`, low-level call + or `tx.origin`. No proxy: constructors only. + +## 3. Findings + +| ID | Title | Severity | Status | Component | PoC | +|----|-------|----------|--------|-----------|-----| +| F-1 | Pending owner turned rule can accept ownership | Info (was Low) | Fixed | `RuleEngineOwnable2Step.sol:29-32`, inherited `acceptOwnership` | `testNomineeAddedAsRuleBeforeAcceptingBecomesOwner` | +| F-2 | Self-binding approval survives an administrative unbind | Info (was Low) | Fixed (option 1) | `TokenBindingModule.sol:81`, `TokenBindingExtendedModule.sol:52, 98` | `testApprovedTokenRebindsItselfAfterManagerUnbinds` | +| F-3 | Any address can be bound, including a rule or an EOA | Info | Fixed (rules) / documented (EOAs) | `TokenBindingModule.sol:100` | `testCannotBindACurrentRule`, `testCannotAddABoundTokenAsRule`, `testBoundEoaConsumesStatefulRuleState` | +| F-4 | Views revert when a rule's view reverts | — | Dismissed: documented | `RuleEngineBase.sol:172, 214` | `testViewsRevertWhenARuleViewReverts` | +| F-5 | `*2771` deployables accept `address(0)` as forwarder | Info | Duplicate of code-quality review `H-3` (open) | constructors of the three `*2771` | `testZeroForwarderIsAccepted` | +| F-6 | Renouncing administration freezes the configuration | — | Dismissed: OpenZeppelin default, documented | inherited `renounceOwnership` / `renounceRole` | `testRenouncingAdministrationFreezesConfiguration` | +| F-7 | ERC-3643 mint and burn carry no operator | — | Dismissed: ERC-3643 interface, documented | `RuleEngineBase.sol:79, 84` | `testErc3643CreatedDoesNotReachSpenderKeyedRule` | + +### F-1 — Pending owner turned rule can accept ownership (Info, was Low) + +The project keeps rule accounts away from privileges. In the ownable deployables the check is +`_checkOwnershipTransferTarget`, called from `transferOwnership`: + +```solidity +function transferOwnership(address newOwner) public virtual override onlyOwner { + RuleEngineOwnableShared._checkOwnershipTransferTarget(newOwner); + Ownable2Step.transferOwnership(newOwner); // only records the pending owner +} +``` + +With `Ownable2Step`, ownership moves in `acceptOwnership`, inherited from OpenZeppelin, which does not repeat the +check. An address nominated while it is not a rule, then added as a rule, can still accept: the engine is then owned +by one of its own rules. Affects `RuleEngineOwnable2Step` and `RuleEngineOwnable2Step2771`. + +**Severity adjustment.** First rated Low. Downgraded to Info: it requires two actions by the trusted owner, which +the owner can undo, and the same end state is already possible through the documented one-directional gap +(`RuleEngine-with-CMTAT.md` §4.6: the check "does not stop an already privileged address from later being added as +a rule"). F-1 adds a path, not a new end state. + +**Recommendation.** Override `acceptOwnership` to call `_checkOwnershipTransferTarget(msg.sender)` first. It is a +three-line change that closes the path. + +**Fixed.** `RuleEngineOwnable2Step` now overrides `acceptOwnership` and runs the check on `_msgSender()` (the same +sender OpenZeppelin's implementation uses, so the `*2771` variant resolves it through the forwarder consistently) +before delegating to `Ownable2Step.acceptOwnership`. A pending owner that is a rule reverts with +`RuleEngine_RulesManagementModule_RuleAccountCannotReceivePrivileges`; once removed from the rule set it can accept. +The proof of concept was inverted into `testNomineeAddedAsRuleBeforeAcceptingCannotAccept`, and +`testNomineeCanAcceptOnceRemovedFromRules` covers the recovery path, on both `Ownable2Step` deployables. + +### F-2 — Self-binding approval survives an administrative unbind (Info, was Low) + +`unbindToken` removes a token from the bound set and leaves its self-binding approval as it was. A token approved +for self-binding can therefore bind itself again after the compliance manager unbound it, and resume driving the +rules. The PoC uses a plain address; on a real T-REX token the path is longer, because `setCompliance(engine)` first +calls `unbindToken(this)` on the current compliance contract and reverts once the token is unbound, so the token's +owner has to point it at another compliance contract and then back at the engine. Revoking the approval before the +unbind prevents the re-bind (`testRevokingApprovalPreventsRebind`), but `RuleEngine-with-ERC3643.md` presents +revocation as optional. + +**Severity adjustment.** First rated Low. Downgraded to Info: the token's owner gains nothing it could not do +already (it can leave the engine through `setCompliance` at any time), and re-binding puts the token back under +the engine's rules. What remains is that the manager's unbind does not stand on its own, which the documentation +does not say. + +**Recommendation.** Three options, from the most to the least intrusive. Option 1 is the recommended one. + +*Option 1 — the manager's unbind also revokes the approval (code).* Clear the approval inside `_unbindToken` when +the caller is not the token itself. `_unbindToken` is the point both `unbindToken` and the batch `unbindTokens` +reach, so one change covers both entry points; checking the raw `msg.sender`, as the rest of the token-identity +logic does since rc7, keeps the token's own unbind (ERC-3643 `setCompliance` migrating away) untouched. + +```solidity +// TokenBindingExtendedModule +function _unbindToken(address token) internal virtual override { + TokenBindingModule._unbindToken(token); + if (msg.sender != token && _tokenSelfBindingApproval[token]) { + _setTokenSelfBindingApproval(token, false); // writes the flag and emits TokenSelfBindingApprovalSet + } +} +``` + +What it involves: + +- **A diamond override.** `_unbindToken` is defined in `TokenBindingModule` and would now be overridden in + `TokenBindingExtendedModule`; `ERC3643ComplianceExtendedModule` inherits both paths, so it needs the same + disambiguating `override(TokenBindingModule, TokenBindingExtendedModule)` it already has for + `_authorizeTokenBindingChange`. +- **One write path for the approval.** Factor the existing setter body into `_setTokenSelfBindingApproval`, used by + `setTokenSelfBindingApproval` and by the code above, so every change of the flag emits + `TokenSelfBindingApprovalSet` and indexers reconstructing approvals stay correct. +- **Behaviour change.** A token unbound by the manager must be approved again before it can bind itself. Clearing the + flag on a manager *bind* instead is not equivalent: it would take away the approval an ERC-3643 token needs to + unbind itself later when migrating to another compliance contract. +- **Tests.** Invert `testApprovedTokenRebindsItselfAfterManagerUnbinds` into a regression test, add the same case for + `unbindTokens`, assert the `TokenSelfBindingApprovalSet(token, false)` event, and keep a test that a token + unbinding itself keeps its approval. Gas: one extra storage read on unbind, plus a write and an event only when an + approval was set. + +*Option 2 — make the approval single-use (code).* Clear the flag when the token binds itself. It closes the re-bind +as well, but also removes the token's ability to unbind itself later, which ERC-3643 `setCompliance` needs to move to +another compliance contract; the manager would have to approve again before every migration. Not recommended. + +*Option 3 — documentation only.* Keep the behaviour and state, in the `unbindToken` NatSpec, in +`TokenBinding-module.md` §4 and in `RuleEngine-with-ERC3643.md` §3.2, that an approved token can bind itself again +until its approval is revoked, so revocation must come before the unbind when the intent is to remove the token. +The current mitigation test, `testRevokingApprovalPreventsRebind`, already shows the correct order. + +**Fixed: option 1.** `TokenBindingExtendedModule` overrides `_unbindToken`: after removing the token, it revokes +the approval when the caller is not the token itself (raw `msg.sender`), through a new `_setTokenSelfBindingApproval` +that also backs `setTokenSelfBindingApproval` and emits `TokenSelfBindingApprovalSet`. `ERC3643ComplianceExtendedModule` +disambiguates the override. Tests, on all six deployables: the proof of concept became +`testManagerUnbindRevokesSelfBindingApproval` (asserts the event and that the token can no longer bind itself), plus +`testManagerBatchUnbindRevokesSelfBindingApproval`, `testTokenUnbindingItselfKeepsApproval` and +`testManagerUnbindOfUnapprovedTokenEmitsNoApprovalEvent`. Removing the revocation fails two tests; revoking also on +the token's own unbind fails one. + +### F-3 — Any address can be bound, including a rule or an EOA (Info) + +`_bindToken` checks only for `address(0)` and duplicates. An address can be a rule and a bound token at the same +time, and a bound **exterwnally** owned account can drive a stateful rule with no token involved: the PoC consumes a +minter's allowance. Binding is therefore a full trust decision of the manager. A code-size check would not be a +defence (it is bypassed during construction). + +**Recommendation.** Two parts: a small code change for rule addresses, and documentation for everything else. + +*Part 1 — keep rules and bound tokens disjoint (code, recommended).* Both sets live in the engine, so unlike roles +the check can run in both directions and cheaply: + +- **Binding a rule is rejected.** Add a virtual hook to the generic registry, for example + `_checkBindingTarget(address token) internal view virtual {}` called from `_bindToken`. `TokenBindingModule` must + stay free of rule logic (it is reused outside this project), so the hook is empty there and `RuleEngineBase` + overrides it with `require(!containsRule(IRule(token)), RuleEngine_RulesManagementModule_RuleAccountCannotReceivePrivileges())`. + The override needs the usual disambiguation, because `RuleEngineBase` inherits the registry through both + `TokenBindingExtendedModule` and `ERC3643ComplianceModule`. +- **Adding a bound token as a rule is rejected.** In `RuleEngineBase._checkRule`, add + `require(!isTokenBound(rule_), ...)`, reusing the same error. +- **What it prevents.** An address cannot both drive the rules and be one, which removes a reentrancy path where a + rule's `transferred` calls the engine's `transferred` again as a bound token. It covers the batch `bindTokens` and + the self-binding path too, since all of them reach `_bindToken`. +- **Cost.** One `EnumerableSet.contains` read per bind and per rule addition, no new error, no ABI change. +- **Tests.** Invert `testRuleAddressCanBeBoundAsToken` into two regression tests (bind a rule; add a bound token as a + rule), on all six deployables. + +*Part 2 — document binding as a trust decision (docs).* An EOA, or any contract, can still be bound, and that cannot +be fixed in code: + +- **A code-size check is not a defence.** `token.code.length > 0` is false for a contract during its own + construction, and it would block binding a token before it is deployed at a counterfactual (CREATE2) address, which + a deployment script may want to do. It is not recommended. +- **What to write.** In the `bindToken` / `bindTokens` NatSpec and `TokenBinding-module.md` §4: a bound address is + trusted to report token operations; it can drive every stateful rule (consume approvals, allowances, counters) + without moving any token; bind only the token contracts the engine is meant to serve. +- `testBoundEoaConsumesStatefulRuleState` stays as the illustration of why. + +**Fixed: both parts.** + +- **Part 1, code.** `TokenBindingModule._bindToken` calls a new empty hook, `_checkBindingTarget`, which + `RuleEngineBase` overrides to reject a current rule; `RuleEngineBase._checkRule` rejects a bound token. Both revert + with `RuleEngine_RulesManagementModule_RuleAccountCannotReceivePrivileges`, so the ABI is unchanged and the + reusable registry stays free of rule logic. +- **Coverage of the paths.** Every binding path (`bindToken`, `bindTokens`, a rule binding itself with an + approval) and every rule path (`addRule`, `setRules`) goes through one of the two checks. +- **Part 2, documentation.** The `bindToken` NatSpec, the registry's `_bindToken` NatSpec and + `TokenBinding-module.md` §4 state that binding is a trust decision. +- **Tests, on all six deployables.** The proof of concept became `testCannotBindACurrentRule` and + `testCannotAddABoundTokenAsRule`; `testRuleAndTokenRolesCanBeSwappedSequentially` covers the legitimate + sequences; the invariant handler now also tries to bind rule addresses, with a new + `invariant_RulesAndBoundTokensAreDisjoint`. Removing either check fails its regression test and the invariant. + `testBoundEoaConsumesStatefulRuleState` stays as the documented illustration. + +### F-4 — Views revert when a rule's view reverts (dismissed) + +The views make plain external calls to every rule, so a rule whose view reverts makes +`detectTransferRestriction(From)`, `canTransfer(From)` and `messageForTransferRestriction` revert, while the +enforcement path may still accept the operation. Dismissed: the CMTAT guide already states that a reverting +contract "still blocks the operation and the token's views, so it is trusted for availability too". Wrapping the +calls in `try/catch` would hide a broken rule behind an arbitrary answer, so the current behaviour is preferable. + +#### Follow-up: should `canTransfer` catch a reverting rule? + +Asked after the review. A `try/catch` around each rule call in `canTransfer` / `canTransferFrom` would return `false` +(not allowed) instead of reverting when a rule's view reverts. A prototype was built and measured on `RuleEngine` +with three rules, then removed: + +```solidity +for (uint256 i = 0; i < _rules.length(); ++i) { + try IRule(_rules.pos(i)).detectTransferRestriction(from, to, value) returns (uint8 code) { + if (code != uint8(REJECTED_CODE_BASE.TRANSFER_OK)) return false; + } catch { + return false; // fail closed + } +} +return true; +``` + +| Case | Today | With `try/catch` | +|---|---|---| +| Three allowing rules, gas of `canTransfer` | 32,308 | 32,229 (−79: the loop skips the internal call to `detectTransferRestriction`) | +| A rule whose view reverts | reverts | returns `false` | +| A rule that returns malformed data (empty return) | reverts | **still reverts**: `try/catch` does not catch a failure to decode the return data in the caller | + +What it would buy: + +- **A boolean that never reverts for a reverting rule.** An on-chain integrator that checks eligibility in a loop, + such as a distributor or a contract screening many holders, would get `false` for one address instead of losing + the whole call. +- **Fail-closed semantics are preserved.** "Not allowed" is the safe answer for a rule that cannot answer. + +What it would not buy, or would cost: + +- **No change for the tokens.** T-REX requires `canTransfer == true` before `transfer`, `transferFrom` and `mint`, so + the operation is blocked either way, only with T-REX's own error instead of the rule's. CMTAT never calls the + view on its transfer path. Enforcement (`transferred`) must keep reverting in any case. +- **The views would disagree.** `detectTransferRestriction` has to return an ERC-1404 code, and there is no code + for "a rule failed" that cannot collide with the codes rules choose. Unless a code is reserved for the engine, + `detectTransferRestriction` keeps reverting while `canTransfer` returns `false`, and the property + `canTransfer == (detectTransferRestriction == 0)` (INV-7) no longer holds as an equality. +- **A broken rule looks like an ordinary refusal.** A view cannot emit an event, so the revert is the only signal + that a rule is broken. Catching it turns a configuration fault into a compliance "no" that an operator may not + notice. +- **It is partial.** Malformed return data still reverts (measured above), and a rule that burns its gas leaves the + engine only 1/64 of it in the `catch` branch, which may not be enough to finish the loop. + +**Opinion: not now.** The engine's own consumers (T-REX, CMTAT) get the same outcome either way, and the change +would split the two standard views and hide broken rules, against a benefit only a third-party on-chain integrator +would see. It becomes worth doing if such an integrator appears and needs a non-reverting boolean. In that case: + +- apply it to `canTransfer` / `canTransferFrom` only, failing closed, and leave `transferred` and + `detectTransferRestriction(From)` / `messageForTransferRestriction` reverting; +- document INV-7 as `canTransfer => detectTransferRestriction == 0`, and "a reverting rule makes `canTransfer` + return `false`"; +- state in the NatSpec that malformed return data still reverts; +- test it with `RevertingViewRule` (now returns `false`), a malformed-return rule (still reverts), and the + rule-aggregation fuzz (unchanged for well-behaved rules). + +### F-5 — `*2771` deployables accept `address(0)` as forwarder (duplicate) + +Already open as `H-3` in the rc7 code-quality review. With a zero forwarder the contract behaves as the variant +without forwarder; `testZeroForwarderIsAccepted` now pins that behaviour. + +### F-6 — Renouncing administration freezes the configuration (dismissed) + +After the owner renounces, or the last admin renounces `DEFAULT_ADMIN_ROLE`, nobody can change the rules or the +bindings, and bound tokens keep running under the last rule set. This is OpenZeppelin's default and is documented. + +### F-7 — ERC-3643 mint and burn carry no operator (dismissed) + +`created` and `destroyed` have no spender argument, so a spender-keyed rule such as a per-minter allowance is not +applied to a T-REX mint, whereas CMTAT's 4-argument path carries the minter. This follows from the ERC-3643 +interface and is documented in `RuleEngine-with-ERC3643.md`. + +## 4. Invariant Verification + +| Invariant | Property | Holds? | Evidence | +|---|---|---|---| +| INV-1 | The rule set never holds `address(0)`, a duplicate, or a contract without a rule ID | Yes | `invariant_RuleSetIsWellFormed`, 6 deployables, 3 200 calls each (handler-based) | +| INV-2 | `rulesCount() == rules().length` and `rule(i) == rules()[i]` | Yes | same | +| INV-3 | `maxRules() > 0` | Yes | `invariant_MaxRulesMatchesModelAndIsNotZero`, 6 deployables | +| INV-4 | Only a bound token reaches the rules through the engine | Yes | `testFuzz_UnboundCallerCannotDriveRules`, 6 × 256 runs; mutation-checked | +| INV-5 | Token identity is `msg.sender`, never the forwarder's appended sender | Yes | ERC-2771 token-gate suites, 3 deployables | +| INV-6 | Every admin entry point rejects every other caller | Yes | `testFuzz_NonAuthorizedCallerCannotAdminister`, 11 functions, 6 × 256 runs; mutation-checked | +| INV-7 | `canTransfer == (detectTransferRestriction == 0)`, and the 4-argument equivalent | Yes | rule-aggregation fuzz, 6 deployables | +| INV-8 | An address in the rule set cannot be granted a role, become owner, or be bound as a token, and a bound token cannot become a rule | Yes | checked at grant, at nomination, at `Ownable2Step` acceptance (F-1) and at binding / rule addition (F-3); `RuleGuard.t.sol`, `invariant_RulesAndBoundTokensAreDisjoint` (6 deployables), mutation-checked | +| INV-9 | `getTokenBounds()` holds no duplicate and no `address(0)` | Yes | `invariant_BoundTokensMatchModel`, 6 deployables | + +The handler-based invariants run in the default suite at 64 sequences of 50 calls; they also passed once at +Foundry's defaults (256 × 500, 128 000 calls each). + +## 5. Access-Control Verification + +| Entry point | RBAC (`RuleEngine`, `RuleEngine2771`) | Ownable (four deployables) | Verified | +|---|---|---|---| +| `addRule`, `removeRule`, `setRules`, `clearRules` | `RULES_MANAGEMENT_ROLE` | owner | fuzz × 6 | +| `setMaxRules` | `DEFAULT_ADMIN_ROLE` | owner | fuzz × 6, mutation-checked | +| `bindToken`, `unbindToken` | `COMPLIANCE_MANAGER_ROLE`, or an approved token for itself; a current rule cannot be bound | owner, or an approved token for itself; a current rule cannot be bound | fuzz × 6, existing self-binding tests | +| `bindTokens`, `unbindTokens`, `setTokenSelfBindingApproval(Batch)` | `COMPLIANCE_MANAGER_ROLE` | owner | fuzz × 6 | +| `transferred` (3/4), `created`, `destroyed` | bound token (`msg.sender`) | same | fuzz × 6, mutation-checked | +| `grantRole` | role admin; the target must not be a rule | — | existing tests | +| `transferOwnership`, `acceptOwnership` | — | owner; the target must not be a rule, at nomination and at acceptance | existing tests, `RuleGuard.t.sol` (F-1) | + +**Centralization premise.** In the RBAC deployables the default admin holds every role through the `hasRole` +override, and in the ownable deployables the owner holds all powers. This is the model, not a finding: the admin +key is the trust anchor, and its custody (multisig, timelock) is a deployment decision. + +**Negative results.** A rules manager cannot change the cap or the bindings; a compliance manager cannot change the +rules; a bound token can only call the callbacks and, when approved, bind or unbind itself; a rule account cannot +call any administrative function, even from inside its callback. + +## 6. Remediation — What Was Implemented + +Three findings were fixed after the review; F-5 (H-3) is open. + +| Item | Status | What changed | Verified by | +|---|---|---|---| +| F-1 | Fixed | `RuleEngineOwnable2Step.acceptOwnership` re-checks that the caller is not a rule (inherited by `RuleEngineOwnable2Step2771`). Behaviour change: a nominee that became a rule can no longer accept until it is removed from the rule set | PoC inverted into a regression test, plus a recovery test, on both deployables; removing the check makes both fail | +| F-2 | Fixed | A manager's `unbindToken` / `unbindTokens` revokes the token's self-binding approval (`_unbindToken` override, single approval write path). Behaviour change: an ERC-3643 token unbound by the manager needs a new approval before it can bind itself; a token unbinding itself keeps its approval | PoC inverted into a regression test, plus batch, self-unbind and event tests on six deployables; mutation-checked | +| F-3 | Fixed (rules) / documented (EOAs) | `_checkBindingTarget` hook in `TokenBindingModule`, overridden in `RuleEngineBase` to reject a current rule; `_checkRule` rejects a bound token; NatSpec and `TokenBinding-module.md` document binding as a trust decision. Behaviour change: an address can no longer be both a rule and a bound token | PoC inverted into two regression tests, plus a sequencing test and a new handler invariant on six deployables; mutation-checked | +| F-5 / H-3 | Open | Behaviour unchanged; pinned on three deployables | `ERC2771VariantTestBase` | +| Access control, unbound callers | Verified | New fuzz tests on six deployables | mutation-checked | + +**Tests added.** 105 tests: `test/utils/SecurityReviewTestBase.sol` (15 tests, run by `test//SecurityReview.t.sol` +for the six deployables), `invariant_RulesAndBoundTokensAreDisjoint` in `test/utils/RuleEngineInvariantTestBase.sol` +(six deployables), `test/utils/Ownable2StepRuleGuardTestBase.sol` (3 tests, run by `RuleGuard.t.sol` for the +two `Ownable2Step` deployables), `testZeroForwarderIsAccepted` in `test/utils/ERC2771VariantTestBase.sol` (three +`*2771` deployables), and two test-only rules, `RevertingViewRule` and `ReentrantAdminRule`. Suite: 610 tests, all +passing; the real T-REX suite: 13, all passing; coverage of `src/` at 100% of lines, statements, +branches (54/54) and functions. + +Several new tests pin today's behaviour of an open item. When an item is fixed, its PoC is expected to fail and must +be inverted into a regression test, as was done for F-1, F-2 and F-3: applying each fix made its PoC fail, and the PoC +was then rewritten to assert the fixed behaviour. + +## 7. Potential Improvements (open backlog) + +These are hardening items, not vulnerabilities. + +| # | Improvement | Addresses | Effort | Breaking? | Priority | +|---|---|---|---|---|---| +| 1 | Decide `H-3`: reject `address(0)` as forwarder in the three `*2771` constructors (not in `ERC2771ModuleStandalone`, which the mock rules use with zero) | F-5 | Small | Constructor rejects a value it accepts today | Low | + +## 8. Scope & Duplicate Check + +All items are in scope (`src/`). + +- **Duplicates:** F-5 is `H-3` of the rc7 code-quality review. F-3's multi-tenant aspect (several tokens sharing + one engine's rule state) is the rc1 Nethermind Audit Agent finding 1, already documented. +- **Documented behaviours:** F-4, F-6 and F-7. +- **New:** F-1, F-2 and F-3 do not appear in the earlier reviews, the Slither and Aderyn reports, or the Nethermind + triage. +- **Static analysis:** Slither's `calls-loop` and `unindexed-event-address` results, by design, were not re-raised. + +**Considered and dismissed:** + +| Threat | Reason | +|---|---| +| Compromised admin, rules manager or forwarder | Trusted actors; keys are a deployment responsibility | +| Admin cannot be stripped of a single role | By design (`hasRole` override), documented | +| Several tokens on one engine share rule state | By design, documented | +| `getTokenBound()` returns an arbitrary token when several are bound | By design, documented | +| Batch binding reverts as a whole | By design (code-quality review C-3) | +| Reverting or gas-heavy rule blocks transfers | Rules are trusted; the cap bounds the loop | +| 3-argument views fail open for spender-dependent rules | Documented (rc5 code-quality review `H-1`) | +| Two rules sharing a restriction code | Documented; the first claimant's message is returned | +| Legacy `IRule` ID accepted | By design: it describes a superset of what the engine calls | +| Zero-value CMTAT `transferFrom` reaching the engine | A rule obligation, documented by CMTAT | +| Engine must revert on a rejected operation | Verified by the CMTAT and T-REX integration suites | +| Initializer front-running, storage collision | No proxy | diff --git a/doc/security/audits/tools/v3.0.0-rc7/aderyn-report-feedback.md b/doc/security/audits/tools/v3.0.0-rc7/aderyn-report-feedback.md new file mode 100644 index 00000000..b9e5c965 --- /dev/null +++ b/doc/security/audits/tools/v3.0.0-rc7/aderyn-report-feedback.md @@ -0,0 +1,222 @@ +# Aderyn Report — Assessment Feedback + +**Tool:** [Aderyn](https://github.com/Cyfrin/aderyn) 0.6.5 +**Report file:** `doc/security/audits/tools/v3.0.0-rc7/aderyn-report.md` +**Assessment date:** 2026-10-16 (commit `29556e5`: the final rc7 code, `src/` as of `c7a19c7`, after the rc7 security review fixes; earlier runs at `3055fe2`, `a91ca9a`, `4946c87` and `850976f` + pragma) +**Scope:** `src/`, **mocks excluded** (`-x mocks`), 31 files analysed, 716 nSLOC, solc 0.8.37 / EVM Osaka, `pragma ^0.8.27` + +```bash +aderyn -x mocks --output doc/security/audits/tools/v3.0.0-rc7/aderyn-report.md +``` + +## Summary + +| ID | Finding | Tool Impact | Instances | Assessment | Decision | +|----|---------|-------------|-----------|------------|----------| +| L-1 | Centralization Risk | Low | 14 | The engine is by definition an admin-operated compliance controller | Accepted by design | +| L-2 | Unspecific Solidity Pragma | Low | 26 | The floating range is kept for integrators, but it was wrong: raised from `^0.8.20` to the real floor `^0.8.27`; the build pins 0.8.37 | **Fixed (pragma corrected)**, floating kept by design | +| L-3 | PUSH0 Opcode | Low | 31 | EVM target is Osaka, which includes PUSH0 (since Shanghai) | Accepted by design | +| L-4 | Modifier Invoked Only Once | Low | 1 | `onlyRulesLimitManager`, kept for symmetry with the hook pattern | Cosmetic, kept | +| L-5 | Empty Block | Low | 10 | The three access-control hooks × three access-control models, where the modifier does the work, plus the empty default of the `_checkBindingTarget` hook (F-3) | Accepted by design | +| L-6 | Loop Contains `require`/`revert` | Low | 4 | Admin batch operations, atomic on purpose (code-quality review `C-3`) | Accepted by design | +| L-7 | Costly operations inside loop | Low | 4 | Admin-gated batch writes; inherent to a batch operation | Accepted by design | +| L-8 | Unchecked Return | Low | 1 | `_grantRole` cannot return `false` in a constructor | False positive | + +**0 High · 8 Low (91 instances). Nothing exploitable; one change made (`L-2`: pragma corrected to `^0.8.27`).** + +## Scope verification + +| Check | Result | +|---|---| +| `grep -c 'lib/' aderyn-report.md` | **0** — no vendored dependency in scope | +| `grep -c 'src/mocks/' aderyn-report.md` | **0** — `-x mocks` applied correctly | +| `grep -c '/home/' aderyn-report.md` | **0** — no absolute paths committed | + +The last check caught a real mistake again. Aderyn computes its source links relative to the `--output` path, so a +run written outside the repository produces `../../../../../home//…/src/…` links — machine-specific paths +in a committed document. It happened again in rc7: the first run wrote to a scratch directory and +produced 84 such links, so it was re-run with the output inside the repository to get the correct relative +`../../../../../src/…` form. Always write the report straight to its final path. + +## Changes since v3.0.0-rc6 + +**Same 8 findings, 84 -> 91 instances** (92 at the intermediate rc7 run, before `D-2`; 90 at `3055fe2`, before the security review fixes). + +| ID | rc6 | rc7, `850976f` + pragma | rc7, `3055fe2` | rc7 final, `29556e5` | Why | +|----|-----|-----|-----|-----|-----| +| L-1 | 14 | 14 | 14 | 14 | RBAC instances: `RuleEngine.sol` -> `RuleEngineAccessControlShared.sol` -> back to `RuleEngine.sol` (`D-2`) | +| L-2 | 23 | 27 | 26 | 26 | per-file detector: +4 files with the ERC-2771 split, −1 when the shared RBAC base was folded | +| L-3 | 28 | 32 | 31 | 31 | same as L-2 | +| L-4 | 1 | 1 | 1 | 1 | — | +| L-5 | 9 | 9 | 9 | **10** | RBAC hooks back in `RuleEngine.sol`; +1 `TokenBindingModule._checkBindingTarget` (F-3) | +| L-6 / L-7 | 4 / 4 | 4 / 4 | 4 / 4 | 4 / 4 | — | +| L-8 | 1 | 1 | 1 | 1 | `RuleEngine.sol:40` (was `RuleEngineAccessControlShared.sol:41`) | + +**Changes after the intermediate rc7 run** (the code-quality review fixes, up to `3055fe2`): +`RuleEngineAccessControlShared` folded into `RuleEngine`, so `RuleEngine2771 is ERC2771ModuleStandalone, RuleEngine` +(`D-2`), and the six deployables moved to `src/deployment/accessControl/` and `src/deployment/ownable/`; view loops +read `_rules` directly (`A-3`, `B-1`); `addRule` / `removeRule` use the set's return value and the unreachable +`OperationNotSuccessful` error is gone (`B-2`); every conditional `revert` became a `require` (`E-2`); `IRule` +narrowed with the legacy ID still accepted (`I-1`); stale NatSpec fixed (`G-2`). None produced a new finding. +nSLOC 707 -> 694, per file: `RuleEngine` 5 -> 54 and `RuleEngineAccessControlShared` 54 -> 0 (the fold), +`RuleEngineBase` 145 -> 153 (`_supportsRuleInterface`, the `EnumerableSet` using-directive), `RulesManagementModule` +109 -> 96 (`B-2`, `E-2`), `IRule` 5 -> 8 (the narrowed interface declares its own `transferred`), +`RuleEngineOwnableShared` 23 -> 21, `TokenBindingModule` 51 -> 49, `RuleInterfaceId` 13 -> 12 and +`RulesManagementModuleInvariantStorage` 17 -> 16 (`E-2`, `B-2`, `I-1`). + +**Changes after the `3055fe2` run** (the rc7 security review fixes, `efaf860` F-1, `9c43b01` F-2, `c7a19c7` F-3): +one new instance, `L-5` on `TokenBindingModule._checkBindingTarget` (see L-5 below). nSLOC 694 -> 716: +`TokenBindingExtendedModule` 48 -> 57 (`_unbindToken` override, `_setTokenSelfBindingApproval`), `RuleEngineBase` +153 -> 157 (`_checkBindingTarget` override, bound-token check in `_checkRule`), `RuleEngineOwnable2Step` 25 -> 29 +(`acceptOwnership`), `ERC3643ComplianceExtendedModule` 18 -> 21 (disambiguating override), `TokenBindingModule` +49 -> 51 (the hook). No other finding moved. + +**Where the change comes from.** rc7 made ERC-2771 opt-in: each access-control model now has a deployable +without a forwarder (`RuleEngine`, `RuleEngineOwnable`, `RuleEngineOwnable2Step`) and a `*2771` deployable with one, +and the RBAC logic moved to the abstract `RuleEngineAccessControlShared` (folded back into `RuleEngine` later, `D-2`). That added four files at the intermediate run. The three `*2771` +contracts contain only a constructor and the three `Context` overrides, so they appear in the two per-file +detectors and nowhere else: no centralization, empty-block or unchecked-return instance is duplicated, because the +hooks and the constructor are inherited, not re-declared. + +**nSLOC 683 -> 707.** +17 in the three interface-ID libraries: the rc6 report was generated (`dc7a4d3`, 2026-08-20 +16:09) about an hour before the rc6 commit that replaced those hardcoded constants with computed +`type(I).interfaceId` XOR expressions (`bdd59fd`, 17:22), so rc7 is the first run on their final form. +7 from the +deployable split. + +**Runs:** `a91ca9a` (2026-10-14) and `4946c87` (2026-10-15) gave 84 instances on the pre-split code; `850976f` + +pragma gave 92 on the six-deployable code; `3055fe2` gave 90; this final run at `29556e5` gives 91. The ERC-2771 token-identity fix (`4946c87`) replaced +`_msgSender()` with `msg.sender` in place and produced no finding. + +The build changes (solc 0.8.37, EVM Osaka, CMTAT v3.3.0-rc4, forge-std v1.17.0) produced nothing either. + +## Detailed triage + +### L-1: Centralization Risk (14 instances) + +Flags the `onlyRole` / `onlyOwner` privileged functions: the RBAC ones in `RuleEngine` and the +ownable ones in `RuleEngineOwnable` / `RuleEngineOwnable2Step`. The `*2771` deployables inherit them and add none (`RuleEngine2771` extends `RuleEngine`). + +The RuleEngine is a compliance controller: an operator must be able to add and remove rules and bind tokens, or +the contract has no purpose. The project deliberately ships three access-control shapes — RBAC (`RuleEngine`), +single-owner (`RuleEngineOwnable`) and two-step handover (`RuleEngineOwnable2Step`) — so the issuer can pick the +centralization profile that matches its governance. ERC-3643 itself specifies ERC-173 ownership for the +compliance contract. + +**Decision: accepted by design.** + +### L-2: Unspecific Solidity Pragma (26 instances) — pragma corrected + +Every `src/` file declared `pragma solidity ^0.8.20;`, now **`^0.8.27`**. + +The caret is intentional: these contracts are consumed as a library by integrators compiling against their own +toolchain, and pinning an exact version would force their whole project onto it. The *build* is deterministic +regardless — `foundry.toml` pins `solc = "0.8.37"`. + +**But the range was wrong.** Up to this run, this triage accepted the caret because "`^0.8.20` is the supported +range". The rc7 code-quality review (`CLAUDE_ANALYSIS.md`, `F-1`) built the production contracts with older +compilers and showed it is not: + +| solc | Result with `^0.8.20` | +|---|---| +| 0.8.20 | fails: CMTAT's interface-ID libraries require `^0.8.24` | +| 0.8.24 | fails: `Error (9322)`, no `require(bool, error)` overload | +| 0.8.26 | fails: "Require with a custom error is only available using the via-ir pipeline" | +| 0.8.27 | compiles | + +The code uses `require(cond, CustomError())`, available on the legacy pipeline from 0.8.27 only, and so does +`TokenBindingModule`, which is offered for reuse in other projects. **Fix applied:** every file under `src/` and +`script/` now declares `^0.8.27`, the real floor. A consumer on 0.8.26 now gets a clear "no matching version" error +from the pragma instead of a compile error deep in a `require`. Checked: `forge build --use 0.8.27` succeeds, 0.8.26 +is rejected by the pragma, and the full suite (default profile on 0.8.37, `erc3643` profile on 0.8.30, Hardhat) +passes. The count moved 23 -> 27 -> 26 with the files added and folded during rc7, unrelated to the fix. + +**Decision: floating pragma accepted by design; its range corrected to `^0.8.27`.** + +### L-3: PUSH0 Opcode (31 instances) + +`foundry.toml` sets `evm_version = 'osaka'` (Prague up to rc6). PUSH0 has been available since Shanghai, so its presence is +expected for the declared target. A chain that has not adopted Shanghai must recompile with a lower +`evm_version` — a build-configuration decision, not a source change. + +**Decision: accepted by design**, with the deployment caveat recorded here. + +### L-4: Modifier Invoked Only Once (1 instance) + +`onlyRulesLimitManager` at `RulesManagementModule.sol:23` guards `setMaxRules` and nothing else. Inlining it +would break the documented pattern in which every protected operation goes through a virtual `_onlyX` hook +wrapped in an `onlyX` modifier, so each deployable variant can override the authorization independently. + +**Decision: cosmetic, kept deliberately.** + +### L-5: Empty Block (10 instances) + +Nine are the same three hooks, declared once per access-control model (`RuleEngine.sol:104/109/114`, +`RuleEngineOwnable.sol:35/40/45`, `RuleEngineOwnable2Step.sol:55/60/65`; the `*2771` deployables inherit them): + +```solidity +function _onlyComplianceManager() internal virtual override onlyRole(COMPLIANCE_MANAGER_ROLE) {} +function _onlyRulesManager() internal virtual override onlyRole(RULES_MANAGEMENT_ROLE) {} +function _onlyRulesLimitManager() internal virtual override onlyRole(DEFAULT_ADMIN_ROLE) {} +``` + +The body is empty because the modifier performs the check — the core access-control pattern described in +`CLAUDE.md`. The rc6 token binding split added one more indirection (`ERC3643ComplianceModule._onlyTokenBindingManager()` calls +`_onlyComplianceManager()`), but that body is not empty, so the count is unchanged. + +The tenth, since the F-3 fix, is the default of the binding-target hook in the standalone registry +(`TokenBindingModule.sol:119`): + +```solidity +function _checkBindingTarget(address token) internal view virtual {} +``` + +The registry is reusable outside the engine and has no notion of a rule, so by default it accepts any target. +`RuleEngineBase` overrides the hook to reject an address that is a current rule +(`RuleEngine_RulesManagementModule_RuleAccountCannotReceivePrivileges`). An empty default is the point of the hook. + +**Decision: accepted by design.** + +### L-6: Loop Contains `require`/`revert` (4 instances) + +`TokenBindingExtendedModule` lines 39, 46 and 65 (`bindTokens`, `unbindTokens`, +`setTokenSelfBindingApprovalBatch`) and `RulesManagementModule.setRules` line 60. + +These are administrative batch operations. Reverting the whole batch on a bad element is the wanted semantics: a +partially-applied compliance change is worse than a rejected one. For `bindTokens` / `unbindTokens` this is now a +recorded decision (code-quality review `C-3`): they stay atomic, unlike the skip-if-already-done convention of +the reference `RuleAddressList` batches, because a binding change is security-relevant; the NatSpec of both +functions and `TokenBinding-module.md` §4 say so, and tests pin the rollback. + +**Decision: accepted by design.** + +### L-7: Costly operations inside loop (4 instances) + +The same four loops, flagged for storage writes inside the iteration. A batch operation cannot avoid writing +once per element. All four are gated on a privileged role, so the only party who can pass an oversized array is +the operator, and the only consequence is their own transaction running out of gas. + +Recorded as `A-3` in the rc5 `CLAUDE_ANALYSIS.md`, where the same conclusion was reached independently. + +**Decision: accepted by design.** + +### L-8: Unchecked Return (1 instance) — false positive + +`RuleEngine.sol:40` (in `RuleEngineAccessControlShared.sol` at the intermediate rc7 run, back in `RuleEngine` since `D-2`): + +```solidity +_grantRole(DEFAULT_ADMIN_ROLE, admin); +``` + +OpenZeppelin's `_grantRole` returns `true` when the role was newly granted and `false` when the account already +held it. This call is in the constructor, on a contract whose role storage is necessarily empty, so the return +value is invariably `true`. Checking it would add a branch that can never be taken. + +**Decision: false positive.** + +## Conclusion + +**No security fix is required from this Aderyn run.** Six findings are by-design consequences of what the +RuleEngine is — an admin-operated, rule-iterating compliance controller distributed as a library — one (`L-4`) is a +deliberately kept cosmetic, and one (`L-8`) is a verified false positive. No finding is exploitable, and rc7 +introduced none. One improvement was made: `L-2`'s accepted range was false, so the pragma now states the real +floor, `^0.8.27`. diff --git a/doc/security/audits/tools/v3.0.0-rc7/aderyn-report.md b/doc/security/audits/tools/v3.0.0-rc7/aderyn-report.md new file mode 100644 index 00000000..0ab7df16 --- /dev/null +++ b/doc/security/audits/tools/v3.0.0-rc7/aderyn-report.md @@ -0,0 +1,756 @@ +# Aderyn report — v3.0.0-rc7 + +| | | +|---|---| +| **Tool** | Aderyn 0.6.5 | +| **Scope** | `src/`, **mocks excluded** (`-x mocks`) | +| **Compiler** | solc 0.8.37, EVM Osaka, `pragma solidity ^0.8.27` | +| **Files analysed** | 31 (716 nSLOC) | +| **Date** | 2026-10-16 | +| **Commit** | `29556e5` (final rc7 code: `src/` as of `c7a19c7`, after the rc7 security review fixes F-1 to F-3) | + +```bash +aderyn -x mocks --output doc/security/audits/tools/v3.0.0-rc7/aderyn-report.md +``` + +**Result: 0 High · 8 Low (91 instances) — nothing to fix.** One finding led to a change during rc7: `L-2`'s +justification ("`^0.8.20` is the supported range") was false, so the pragma was raised to the real floor, `^0.8.27`. + +| ID | Finding | Severity | Instances | Assessment | +|----|---------|----------|-----------|------------| +| L-1 | Centralization Risk | Low | 14 | **By design** — the engine is an admin-operated compliance controller | +| L-2 | Unspecific Solidity Pragma | Low | 26 | **By design, pragma corrected** — `^0.8.27` is the real supported range; the build pins 0.8.37 | +| L-3 | PUSH0 Opcode | Low | 31 | **By design** — EVM target is Osaka, which has PUSH0 (since Shanghai) | +| L-4 | Modifier Invoked Only Once | Low | 1 | **Cosmetic** — `onlyRulesLimitManager`, kept for symmetry with the hook pattern | +| L-5 | Empty Block | Low | 10 | **By design** — access-control hooks, and the default `_checkBindingTarget` hook (F-3), are intentionally empty bodies | +| L-6 | Loop Contains `require`/`revert` | Low | 4 | **By design** — admin batch operations, atomic on purpose (`C-3`) | +| L-7 | Costly operations inside loop | Low | 4 | **By design** — admin-gated batch writes | +| L-8 | Unchecked Return | Low | 1 | **False positive** — `_grantRole` cannot return `false` in a constructor | + +**Scope verified:** `grep -c 'lib/'` = **0**, `grep -c 'src/mocks/'` = **0** and `grep -c '/home/'` = **0** in this report. + +**Delta from the run at `3055fe2` (before the rc7 security review fixes): same 8 findings, 90 -> 91 instances.** +`L-5` 9 -> 10: `TokenBindingModule._checkBindingTarget` (line 119), the empty default of the hook added for F-3, +overridden in `RuleEngineBase` to reject current rules. Other instances only moved lines. nSLOC 694 -> 716. + +**Delta from the intermediate rc7 run (`850976f` + pragma): same 8 findings, 92 -> 90 instances.** `L-2` 27 -> 26 and +`L-3` 32 -> 31: one file fewer, `RuleEngineAccessControlShared.sol`, folded into `RuleEngine.sol` (code-quality +review `D-2`). The RBAC instances of `L-1`, `L-5` and `L-8` moved back to `RuleEngine.sol`, now under +`src/deployment/accessControl/`. nSLOC 707 -> 694. **Delta from v3.0.0-rc6: same 8 findings, 84 -> 91 instances.** + +Triage and per-finding reasoning: [aderyn-report-feedback.md](./aderyn-report-feedback.md). +Overview of all analyses: [AUDIT_OVERVIEW.md](../../AUDIT_OVERVIEW.md). + +--- +# Aderyn Analysis Report + +This report was generated by [Aderyn](https://github.com/Cyfrin/aderyn), a static analysis tool built by [Cyfrin](https://cyfrin.io), a blockchain security company. This report is not a substitute for manual audit or security review. It should not be relied upon for any purpose other than to assist in the identification of potential security vulnerabilities. +# Table of Contents + +- [Summary](#summary) + - [Files Summary](#files-summary) + - [Files Details](#files-details) + - [Issue Summary](#issue-summary) +- [Low Issues](#low-issues) + - [L-1: Centralization Risk](#l-1-centralization-risk) + - [L-2: Unspecific Solidity Pragma](#l-2-unspecific-solidity-pragma) + - [L-3: PUSH0 Opcode](#l-3-push0-opcode) + - [L-4: Modifier Invoked Only Once](#l-4-modifier-invoked-only-once) + - [L-5: Empty Block](#l-5-empty-block) + - [L-6: Loop Contains `require`/`revert`](#l-6-loop-contains-requirerevert) + - [L-7: Costly operations inside loop](#l-7-costly-operations-inside-loop) + - [L-8: Unchecked Return](#l-8-unchecked-return) + + +# Summary + +## Files Summary + +| Key | Value | +| --- | --- | +| .sol Files | 31 | +| Total nSLOC | 716 | + + +## Files Details + +| Filepath | nSLOC | +| --- | --- | +| src/RuleEngineBase.sol | 157 | +| src/RuleEngineOwnableShared.sol | 21 | +| src/deployment/accessControl/RuleEngine.sol | 54 | +| src/deployment/accessControl/RuleEngine2771.sol | 19 | +| src/deployment/ownable/RuleEngineOwnable.sol | 13 | +| src/deployment/ownable/RuleEngineOwnable2771.sol | 19 | +| src/deployment/ownable/RuleEngineOwnable2Step.sol | 29 | +| src/deployment/ownable/RuleEngineOwnable2Step2771.sol | 19 | +| src/interfaces/IERC3643Compliance.sol | 8 | +| src/interfaces/IERC3643ComplianceExtended.sol | 4 | +| src/interfaces/IRule.sol | 8 | +| src/interfaces/IRulesManagementModule.sol | 14 | +| src/interfaces/ITokenBinding.sol | 8 | +| src/interfaces/ITokenBindingExtended.sol | 12 | +| src/modules/ERC2771ModuleStandalone.sol | 6 | +| src/modules/ERC3643ComplianceExtendedModule.sol | 21 | +| src/modules/ERC3643ComplianceModule.sol | 18 | +| src/modules/RulesManagementModule.sol | 96 | +| src/modules/TokenBindingExtendedModule.sol | 57 | +| src/modules/TokenBindingModule.sol | 51 | +| src/modules/VersionModule.sol | 8 | +| src/modules/library/ComplianceInterfaceId.sol | 13 | +| src/modules/library/ERC1404InterfaceId.sol | 5 | +| src/modules/library/ERC3643ComplianceRolesStorage.sol | 4 | +| src/modules/library/Ownable2StepInterfaceId.sol | 4 | +| src/modules/library/OwnableInterfaceId.sol | 4 | +| src/modules/library/RuleEngineInvariantStorage.sol | 5 | +| src/modules/library/RuleInterfaceId.sol | 12 | +| src/modules/library/RulesManagementModuleInvariantStorage.sol | 16 | +| src/modules/library/RulesManagementModuleRolesStorage.sol | 4 | +| src/modules/library/TokenBindingModuleInvariantStorage.sol | 7 | +| **Total** | **716** | + + +## Issue Summary + +| Category | No. of Issues | +| --- | --- | +| High | 0 | +| Low | 8 | + + +# Low Issues + +## L-1: Centralization Risk + +Contracts have owners with privileged rights to perform admin tasks and need to be trusted to not perform malicious updates or drain funds. + +
14 Found Instances + + +- Found in src/deployment/accessControl/RuleEngine.sol [Line: 24](../../../../../src/deployment/accessControl/RuleEngine.sol#L24) + + ```solidity + AccessControlEnumerable, + ``` + +- Found in src/deployment/accessControl/RuleEngine.sol [Line: 104](../../../../../src/deployment/accessControl/RuleEngine.sol#L104) + + ```solidity + function _onlyComplianceManager() internal virtual override onlyRole(COMPLIANCE_MANAGER_ROLE) {} + ``` + +- Found in src/deployment/accessControl/RuleEngine.sol [Line: 109](../../../../../src/deployment/accessControl/RuleEngine.sol#L109) + + ```solidity + function _onlyRulesManager() internal virtual override onlyRole(RULES_MANAGEMENT_ROLE) {} + ``` + +- Found in src/deployment/accessControl/RuleEngine.sol [Line: 114](../../../../../src/deployment/accessControl/RuleEngine.sol#L114) + + ```solidity + function _onlyRulesLimitManager() internal virtual override onlyRole(DEFAULT_ADMIN_ROLE) {} + ``` + +- Found in src/deployment/ownable/RuleEngineOwnable.sol [Line: 13](../../../../../src/deployment/ownable/RuleEngineOwnable.sol#L13) + + ```solidity + contract RuleEngineOwnable is RuleEngineOwnableShared, Ownable { + ``` + +- Found in src/deployment/ownable/RuleEngineOwnable.sol [Line: 26](../../../../../src/deployment/ownable/RuleEngineOwnable.sol#L26) + + ```solidity + function transferOwnership(address newOwner) public virtual override onlyOwner { + ``` + +- Found in src/deployment/ownable/RuleEngineOwnable.sol [Line: 35](../../../../../src/deployment/ownable/RuleEngineOwnable.sol#L35) + + ```solidity + function _onlyRulesManager() internal virtual override onlyOwner {} + ``` + +- Found in src/deployment/ownable/RuleEngineOwnable.sol [Line: 40](../../../../../src/deployment/ownable/RuleEngineOwnable.sol#L40) + + ```solidity + function _onlyRulesLimitManager() internal virtual override onlyOwner {} + ``` + +- Found in src/deployment/ownable/RuleEngineOwnable.sol [Line: 45](../../../../../src/deployment/ownable/RuleEngineOwnable.sol#L45) + + ```solidity + function _onlyComplianceManager() internal virtual override onlyOwner {} + ``` + +- Found in src/deployment/ownable/RuleEngineOwnable2Step.sol [Line: 16](../../../../../src/deployment/ownable/RuleEngineOwnable2Step.sol#L16) + + ```solidity + contract RuleEngineOwnable2Step is RuleEngineOwnableShared, Ownable2Step { + ``` + +- Found in src/deployment/ownable/RuleEngineOwnable2Step.sol [Line: 29](../../../../../src/deployment/ownable/RuleEngineOwnable2Step.sol#L29) + + ```solidity + function transferOwnership(address newOwner) public virtual override onlyOwner { + ``` + +- Found in src/deployment/ownable/RuleEngineOwnable2Step.sol [Line: 65](../../../../../src/deployment/ownable/RuleEngineOwnable2Step.sol#L65) + + ```solidity + function _onlyRulesManager() internal virtual override onlyOwner {} + ``` + +- Found in src/deployment/ownable/RuleEngineOwnable2Step.sol [Line: 70](../../../../../src/deployment/ownable/RuleEngineOwnable2Step.sol#L70) + + ```solidity + function _onlyRulesLimitManager() internal virtual override onlyOwner {} + ``` + +- Found in src/deployment/ownable/RuleEngineOwnable2Step.sol [Line: 75](../../../../../src/deployment/ownable/RuleEngineOwnable2Step.sol#L75) + + ```solidity + function _onlyComplianceManager() internal virtual override onlyOwner {} + ``` + +
+ + + +## L-2: Unspecific Solidity Pragma + +Consider using a specific version of Solidity in your contracts instead of a wide version. For example, instead of `pragma solidity ^0.8.0;`, use `pragma solidity 0.8.0;` + +
26 Found Instances + + +- Found in src/RuleEngineBase.sol [Line: 3](../../../../../src/RuleEngineBase.sol#L3) + + ```solidity + pragma solidity ^0.8.27; + ``` + +- Found in src/RuleEngineOwnableShared.sol [Line: 3](../../../../../src/RuleEngineOwnableShared.sol#L3) + + ```solidity + pragma solidity ^0.8.27; + ``` + +- Found in src/deployment/accessControl/RuleEngine.sol [Line: 3](../../../../../src/deployment/accessControl/RuleEngine.sol#L3) + + ```solidity + pragma solidity ^0.8.27; + ``` + +- Found in src/deployment/accessControl/RuleEngine2771.sol [Line: 3](../../../../../src/deployment/accessControl/RuleEngine2771.sol#L3) + + ```solidity + pragma solidity ^0.8.27; + ``` + +- Found in src/deployment/ownable/RuleEngineOwnable.sol [Line: 3](../../../../../src/deployment/ownable/RuleEngineOwnable.sol#L3) + + ```solidity + pragma solidity ^0.8.27; + ``` + +- Found in src/deployment/ownable/RuleEngineOwnable2771.sol [Line: 3](../../../../../src/deployment/ownable/RuleEngineOwnable2771.sol#L3) + + ```solidity + pragma solidity ^0.8.27; + ``` + +- Found in src/deployment/ownable/RuleEngineOwnable2Step.sol [Line: 3](../../../../../src/deployment/ownable/RuleEngineOwnable2Step.sol#L3) + + ```solidity + pragma solidity ^0.8.27; + ``` + +- Found in src/deployment/ownable/RuleEngineOwnable2Step2771.sol [Line: 3](../../../../../src/deployment/ownable/RuleEngineOwnable2Step2771.sol#L3) + + ```solidity + pragma solidity ^0.8.27; + ``` + +- Found in src/interfaces/IERC3643Compliance.sol [Line: 3](../../../../../src/interfaces/IERC3643Compliance.sol#L3) + + ```solidity + pragma solidity ^0.8.27; + ``` + +- Found in src/interfaces/IERC3643ComplianceExtended.sol [Line: 3](../../../../../src/interfaces/IERC3643ComplianceExtended.sol#L3) + + ```solidity + pragma solidity ^0.8.27; + ``` + +- Found in src/interfaces/IRule.sol [Line: 3](../../../../../src/interfaces/IRule.sol#L3) + + ```solidity + pragma solidity ^0.8.27; + ``` + +- Found in src/interfaces/IRulesManagementModule.sol [Line: 3](../../../../../src/interfaces/IRulesManagementModule.sol#L3) + + ```solidity + pragma solidity ^0.8.27; + ``` + +- Found in src/interfaces/ITokenBinding.sol [Line: 3](../../../../../src/interfaces/ITokenBinding.sol#L3) + + ```solidity + pragma solidity ^0.8.27; + ``` + +- Found in src/interfaces/ITokenBindingExtended.sol [Line: 3](../../../../../src/interfaces/ITokenBindingExtended.sol#L3) + + ```solidity + pragma solidity ^0.8.27; + ``` + +- Found in src/modules/ERC2771ModuleStandalone.sol [Line: 3](../../../../../src/modules/ERC2771ModuleStandalone.sol#L3) + + ```solidity + pragma solidity ^0.8.27; + ``` + +- Found in src/modules/ERC3643ComplianceExtendedModule.sol [Line: 3](../../../../../src/modules/ERC3643ComplianceExtendedModule.sol#L3) + + ```solidity + pragma solidity ^0.8.27; + ``` + +- Found in src/modules/ERC3643ComplianceModule.sol [Line: 3](../../../../../src/modules/ERC3643ComplianceModule.sol#L3) + + ```solidity + pragma solidity ^0.8.27; + ``` + +- Found in src/modules/RulesManagementModule.sol [Line: 3](../../../../../src/modules/RulesManagementModule.sol#L3) + + ```solidity + pragma solidity ^0.8.27; + ``` + +- Found in src/modules/TokenBindingExtendedModule.sol [Line: 3](../../../../../src/modules/TokenBindingExtendedModule.sol#L3) + + ```solidity + pragma solidity ^0.8.27; + ``` + +- Found in src/modules/TokenBindingModule.sol [Line: 3](../../../../../src/modules/TokenBindingModule.sol#L3) + + ```solidity + pragma solidity ^0.8.27; + ``` + +- Found in src/modules/VersionModule.sol [Line: 3](../../../../../src/modules/VersionModule.sol#L3) + + ```solidity + pragma solidity ^0.8.27; + ``` + +- Found in src/modules/library/ERC3643ComplianceRolesStorage.sol [Line: 3](../../../../../src/modules/library/ERC3643ComplianceRolesStorage.sol#L3) + + ```solidity + pragma solidity ^0.8.27; + ``` + +- Found in src/modules/library/RuleEngineInvariantStorage.sol [Line: 3](../../../../../src/modules/library/RuleEngineInvariantStorage.sol#L3) + + ```solidity + pragma solidity ^0.8.27; + ``` + +- Found in src/modules/library/RulesManagementModuleInvariantStorage.sol [Line: 3](../../../../../src/modules/library/RulesManagementModuleInvariantStorage.sol#L3) + + ```solidity + pragma solidity ^0.8.27; + ``` + +- Found in src/modules/library/RulesManagementModuleRolesStorage.sol [Line: 3](../../../../../src/modules/library/RulesManagementModuleRolesStorage.sol#L3) + + ```solidity + pragma solidity ^0.8.27; + ``` + +- Found in src/modules/library/TokenBindingModuleInvariantStorage.sol [Line: 3](../../../../../src/modules/library/TokenBindingModuleInvariantStorage.sol#L3) + + ```solidity + pragma solidity ^0.8.27; + ``` + +
+ + + +## L-3: PUSH0 Opcode + +Solc compiler version 0.8.20 switches the default target EVM version to Shanghai, which means that the generated bytecode will include PUSH0 opcodes. Be sure to select the appropriate EVM version in case you intend to deploy on a chain other than mainnet like L2 chains that may not support PUSH0, otherwise deployment of your contracts will fail. + +
31 Found Instances + + +- Found in src/RuleEngineBase.sol [Line: 3](../../../../../src/RuleEngineBase.sol#L3) + + ```solidity + pragma solidity ^0.8.27; + ``` + +- Found in src/RuleEngineOwnableShared.sol [Line: 3](../../../../../src/RuleEngineOwnableShared.sol#L3) + + ```solidity + pragma solidity ^0.8.27; + ``` + +- Found in src/deployment/accessControl/RuleEngine.sol [Line: 3](../../../../../src/deployment/accessControl/RuleEngine.sol#L3) + + ```solidity + pragma solidity ^0.8.27; + ``` + +- Found in src/deployment/accessControl/RuleEngine2771.sol [Line: 3](../../../../../src/deployment/accessControl/RuleEngine2771.sol#L3) + + ```solidity + pragma solidity ^0.8.27; + ``` + +- Found in src/deployment/ownable/RuleEngineOwnable.sol [Line: 3](../../../../../src/deployment/ownable/RuleEngineOwnable.sol#L3) + + ```solidity + pragma solidity ^0.8.27; + ``` + +- Found in src/deployment/ownable/RuleEngineOwnable2771.sol [Line: 3](../../../../../src/deployment/ownable/RuleEngineOwnable2771.sol#L3) + + ```solidity + pragma solidity ^0.8.27; + ``` + +- Found in src/deployment/ownable/RuleEngineOwnable2Step.sol [Line: 3](../../../../../src/deployment/ownable/RuleEngineOwnable2Step.sol#L3) + + ```solidity + pragma solidity ^0.8.27; + ``` + +- Found in src/deployment/ownable/RuleEngineOwnable2Step2771.sol [Line: 3](../../../../../src/deployment/ownable/RuleEngineOwnable2Step2771.sol#L3) + + ```solidity + pragma solidity ^0.8.27; + ``` + +- Found in src/interfaces/IERC3643Compliance.sol [Line: 3](../../../../../src/interfaces/IERC3643Compliance.sol#L3) + + ```solidity + pragma solidity ^0.8.27; + ``` + +- Found in src/interfaces/IERC3643ComplianceExtended.sol [Line: 3](../../../../../src/interfaces/IERC3643ComplianceExtended.sol#L3) + + ```solidity + pragma solidity ^0.8.27; + ``` + +- Found in src/interfaces/IRule.sol [Line: 3](../../../../../src/interfaces/IRule.sol#L3) + + ```solidity + pragma solidity ^0.8.27; + ``` + +- Found in src/interfaces/IRulesManagementModule.sol [Line: 3](../../../../../src/interfaces/IRulesManagementModule.sol#L3) + + ```solidity + pragma solidity ^0.8.27; + ``` + +- Found in src/interfaces/ITokenBinding.sol [Line: 3](../../../../../src/interfaces/ITokenBinding.sol#L3) + + ```solidity + pragma solidity ^0.8.27; + ``` + +- Found in src/interfaces/ITokenBindingExtended.sol [Line: 3](../../../../../src/interfaces/ITokenBindingExtended.sol#L3) + + ```solidity + pragma solidity ^0.8.27; + ``` + +- Found in src/modules/ERC2771ModuleStandalone.sol [Line: 3](../../../../../src/modules/ERC2771ModuleStandalone.sol#L3) + + ```solidity + pragma solidity ^0.8.27; + ``` + +- Found in src/modules/ERC3643ComplianceExtendedModule.sol [Line: 3](../../../../../src/modules/ERC3643ComplianceExtendedModule.sol#L3) + + ```solidity + pragma solidity ^0.8.27; + ``` + +- Found in src/modules/ERC3643ComplianceModule.sol [Line: 3](../../../../../src/modules/ERC3643ComplianceModule.sol#L3) + + ```solidity + pragma solidity ^0.8.27; + ``` + +- Found in src/modules/RulesManagementModule.sol [Line: 3](../../../../../src/modules/RulesManagementModule.sol#L3) + + ```solidity + pragma solidity ^0.8.27; + ``` + +- Found in src/modules/TokenBindingExtendedModule.sol [Line: 3](../../../../../src/modules/TokenBindingExtendedModule.sol#L3) + + ```solidity + pragma solidity ^0.8.27; + ``` + +- Found in src/modules/TokenBindingModule.sol [Line: 3](../../../../../src/modules/TokenBindingModule.sol#L3) + + ```solidity + pragma solidity ^0.8.27; + ``` + +- Found in src/modules/VersionModule.sol [Line: 3](../../../../../src/modules/VersionModule.sol#L3) + + ```solidity + pragma solidity ^0.8.27; + ``` + +- Found in src/modules/library/ComplianceInterfaceId.sol [Line: 3](../../../../../src/modules/library/ComplianceInterfaceId.sol#L3) + + ```solidity + pragma solidity ^0.8.27; + ``` + +- Found in src/modules/library/ERC1404InterfaceId.sol [Line: 3](../../../../../src/modules/library/ERC1404InterfaceId.sol#L3) + + ```solidity + pragma solidity ^0.8.27; + ``` + +- Found in src/modules/library/ERC3643ComplianceRolesStorage.sol [Line: 3](../../../../../src/modules/library/ERC3643ComplianceRolesStorage.sol#L3) + + ```solidity + pragma solidity ^0.8.27; + ``` + +- Found in src/modules/library/Ownable2StepInterfaceId.sol [Line: 3](../../../../../src/modules/library/Ownable2StepInterfaceId.sol#L3) + + ```solidity + pragma solidity ^0.8.27; + ``` + +- Found in src/modules/library/OwnableInterfaceId.sol [Line: 3](../../../../../src/modules/library/OwnableInterfaceId.sol#L3) + + ```solidity + pragma solidity ^0.8.27; + ``` + +- Found in src/modules/library/RuleEngineInvariantStorage.sol [Line: 3](../../../../../src/modules/library/RuleEngineInvariantStorage.sol#L3) + + ```solidity + pragma solidity ^0.8.27; + ``` + +- Found in src/modules/library/RuleInterfaceId.sol [Line: 3](../../../../../src/modules/library/RuleInterfaceId.sol#L3) + + ```solidity + pragma solidity ^0.8.27; + ``` + +- Found in src/modules/library/RulesManagementModuleInvariantStorage.sol [Line: 3](../../../../../src/modules/library/RulesManagementModuleInvariantStorage.sol#L3) + + ```solidity + pragma solidity ^0.8.27; + ``` + +- Found in src/modules/library/RulesManagementModuleRolesStorage.sol [Line: 3](../../../../../src/modules/library/RulesManagementModuleRolesStorage.sol#L3) + + ```solidity + pragma solidity ^0.8.27; + ``` + +- Found in src/modules/library/TokenBindingModuleInvariantStorage.sol [Line: 3](../../../../../src/modules/library/TokenBindingModuleInvariantStorage.sol#L3) + + ```solidity + pragma solidity ^0.8.27; + ``` + +
+ + + +## L-4: Modifier Invoked Only Once + +Consider removing the modifier or inlining the logic into the calling function. + +
1 Found Instances + + +- Found in src/modules/RulesManagementModule.sol [Line: 23](../../../../../src/modules/RulesManagementModule.sol#L23) + + ```solidity + modifier onlyRulesLimitManager() { + ``` + +
+ + + +## L-5: Empty Block + +Consider removing empty blocks. + +
10 Found Instances + + +- Found in src/deployment/accessControl/RuleEngine.sol [Line: 104](../../../../../src/deployment/accessControl/RuleEngine.sol#L104) + + ```solidity + function _onlyComplianceManager() internal virtual override onlyRole(COMPLIANCE_MANAGER_ROLE) {} + ``` + +- Found in src/deployment/accessControl/RuleEngine.sol [Line: 109](../../../../../src/deployment/accessControl/RuleEngine.sol#L109) + + ```solidity + function _onlyRulesManager() internal virtual override onlyRole(RULES_MANAGEMENT_ROLE) {} + ``` + +- Found in src/deployment/accessControl/RuleEngine.sol [Line: 114](../../../../../src/deployment/accessControl/RuleEngine.sol#L114) + + ```solidity + function _onlyRulesLimitManager() internal virtual override onlyRole(DEFAULT_ADMIN_ROLE) {} + ``` + +- Found in src/deployment/ownable/RuleEngineOwnable.sol [Line: 35](../../../../../src/deployment/ownable/RuleEngineOwnable.sol#L35) + + ```solidity + function _onlyRulesManager() internal virtual override onlyOwner {} + ``` + +- Found in src/deployment/ownable/RuleEngineOwnable.sol [Line: 40](../../../../../src/deployment/ownable/RuleEngineOwnable.sol#L40) + + ```solidity + function _onlyRulesLimitManager() internal virtual override onlyOwner {} + ``` + +- Found in src/deployment/ownable/RuleEngineOwnable.sol [Line: 45](../../../../../src/deployment/ownable/RuleEngineOwnable.sol#L45) + + ```solidity + function _onlyComplianceManager() internal virtual override onlyOwner {} + ``` + +- Found in src/deployment/ownable/RuleEngineOwnable2Step.sol [Line: 65](../../../../../src/deployment/ownable/RuleEngineOwnable2Step.sol#L65) + + ```solidity + function _onlyRulesManager() internal virtual override onlyOwner {} + ``` + +- Found in src/deployment/ownable/RuleEngineOwnable2Step.sol [Line: 70](../../../../../src/deployment/ownable/RuleEngineOwnable2Step.sol#L70) + + ```solidity + function _onlyRulesLimitManager() internal virtual override onlyOwner {} + ``` + +- Found in src/deployment/ownable/RuleEngineOwnable2Step.sol [Line: 75](../../../../../src/deployment/ownable/RuleEngineOwnable2Step.sol#L75) + + ```solidity + function _onlyComplianceManager() internal virtual override onlyOwner {} + ``` + +- Found in src/modules/TokenBindingModule.sol [Line: 119](../../../../../src/modules/TokenBindingModule.sol#L119) + + ```solidity + function _checkBindingTarget(address token) internal view virtual {} + ``` + +
+ + + +## L-6: Loop Contains `require`/`revert` + +Avoid `require` / `revert` statements in a loop because a single bad item can cause the whole transaction to fail. It's better to forgive on fail and return failed elements post processing of the loop + +
4 Found Instances + + +- Found in src/modules/RulesManagementModule.sol [Line: 60](../../../../../src/modules/RulesManagementModule.sol#L60) + + ```solidity + for (uint256 i = 0; i < rules_.length; ++i) { + ``` + +- Found in src/modules/TokenBindingExtendedModule.sol [Line: 39](../../../../../src/modules/TokenBindingExtendedModule.sol#L39) + + ```solidity + for (uint256 i = 0; i < tokens.length; ++i) { + ``` + +- Found in src/modules/TokenBindingExtendedModule.sol [Line: 46](../../../../../src/modules/TokenBindingExtendedModule.sol#L46) + + ```solidity + for (uint256 i = 0; i < tokens.length; ++i) { + ``` + +- Found in src/modules/TokenBindingExtendedModule.sol [Line: 64](../../../../../src/modules/TokenBindingExtendedModule.sol#L64) + + ```solidity + for (uint256 i = 0; i < tokens.length; ++i) { + ``` + +
+ + + +## L-7: Costly operations inside loop + +Invoking `SSTORE` operations in loops may waste gas. Use a local variable to hold the loop computation result. + +
4 Found Instances + + +- Found in src/modules/RulesManagementModule.sol [Line: 60](../../../../../src/modules/RulesManagementModule.sol#L60) + + ```solidity + for (uint256 i = 0; i < rules_.length; ++i) { + ``` + +- Found in src/modules/TokenBindingExtendedModule.sol [Line: 39](../../../../../src/modules/TokenBindingExtendedModule.sol#L39) + + ```solidity + for (uint256 i = 0; i < tokens.length; ++i) { + ``` + +- Found in src/modules/TokenBindingExtendedModule.sol [Line: 46](../../../../../src/modules/TokenBindingExtendedModule.sol#L46) + + ```solidity + for (uint256 i = 0; i < tokens.length; ++i) { + ``` + +- Found in src/modules/TokenBindingExtendedModule.sol [Line: 64](../../../../../src/modules/TokenBindingExtendedModule.sol#L64) + + ```solidity + for (uint256 i = 0; i < tokens.length; ++i) { + ``` + +
+ + + +## L-8: Unchecked Return + +Function returns a value but it is ignored. Consider checking the return value. + +
1 Found Instances + + +- Found in src/deployment/accessControl/RuleEngine.sol [Line: 40](../../../../../src/deployment/accessControl/RuleEngine.sol#L40) + + ```solidity + _grantRole(DEFAULT_ADMIN_ROLE, admin); + ``` + +
+ + + diff --git a/doc/security/audits/tools/v3.0.0-rc7/slither-report-feedback.md b/doc/security/audits/tools/v3.0.0-rc7/slither-report-feedback.md new file mode 100644 index 00000000..59d30e9c --- /dev/null +++ b/doc/security/audits/tools/v3.0.0-rc7/slither-report-feedback.md @@ -0,0 +1,140 @@ +# Slither Report — Assessment Feedback + +**Tool:** [Slither](https://github.com/crytic/slither) 0.11.5 (run with `uvx --python 3.12 --from slither-analyzer==0.11.5`) +**Report file:** `doc/security/audits/tools/v3.0.0-rc7/slither-report.md` +**Assessment date:** 2026-10-16 (commit `29556e5`: the final rc7 code, `src/` as of `c7a19c7`, after the rc7 security review fixes; earlier runs at `3055fe2`, `a91ca9a`, `4946c87` and `850976f` + pragma gave the same findings) +**Scope:** `src/`, **mocks excluded**, 111 contracts analysed, solc 0.8.37 / EVM Osaka, `pragma ^0.8.27` + +```bash +slither . --checklist --filter-paths "openzeppelin-contracts|test|CMTAT|forge-std|mocks" \ + > doc/security/audits/tools/v3.0.0-rc7/slither-report.md +``` + +## Summary + +| IDs | Detector | Tool Impact | Assessment | Decision | +|-----|----------|-------------|------------|----------| +| 0-9 | `calls-loop` | Low | Inherent to pluggable rule-engine dispatch; bounded by `maxRules` | Accepted by design | +| 10-11 | `unindexed-event-address` | Informational | The ERC-3643 reference declares these events unindexed — matching it is conformance | Accepted by design | + +**0 High · 0 Medium · 10 Low · 2 Informational. Nothing to fix.** + +## Scope verification + +Confirmed before triage, because a `--filter-paths` entry that matches nothing fails open and silently pulls +the whole vendored tree into scope: + +| Check | Result | +|---|---| +| `grep -c 'lib/\|node_modules/' slither-report.md` | **0** — no vendored dependency in scope | +| `grep -c 'src/mocks/' slither-report.md` | **0** — mocks correctly excluded | + +The filter lists dependency names (`openzeppelin-contracts`, `CMTAT`, `forge-std`) rather than filtering `lib` +wholesale. That still resolves correctly here — each entry matches its `lib/` path as a substring, and +`lib/CMTATv3.0.0` and `lib/openzeppelin-contracts-upgradeable` are caught by the `CMTAT` and +`openzeppelin-contracts` entries. `lib/ERC-3643` matches no entry, but nothing under `src/` imports it, so the +compiler never pulls it in — confirmed by the zero `lib/` count above. Worth revisiting if that ever changes. + +## Changes since v3.0.0-rc6 + +**None in findings.** Same two detectors, same 10 + 2 instances, in the same functions: the two +`RulesManagementModule._transferred` overloads, the three `RuleEngineBase` view loops, and the two `ITokenBinding` +events. + +That holds although rc7 changed `src/` substantially, and it is worth recording why: + +- **ERC-2771 token-identity fix** (`4946c87`): `_checkBoundToken` and the token self-binding check compare + `msg.sender`. Neither function contains a loop or an event. +- **ERC-2771 made opt-in, six deployables** (`a183425`, `850976f`): `RuleEngine`, `RuleEngineOwnable` and + `RuleEngineOwnable2Step` lost the forwarder; `RuleEngine2771`, `RuleEngineOwnable2771` and + `RuleEngineOwnable2Step2771` carry it; the RBAC logic moved to the abstract `RuleEngineAccessControlShared`. These + are constructors, access-control hooks and `Context` overrides: no external call in a loop, no new event. The + contract count rose 108 -> 112 (three deployables and the shared base) with no new result. +- **Pragma `^0.8.20` -> `^0.8.27`**, following the Aderyn `L-2` triage (see its feedback). No Slither detector + depends on it; the output is identical before and after. +- `VERSION` string, `forge fmt` re-wrap of two interface-ID constants. + +- **Code-quality review fixes, after the previous run** (up to `3055fe2`): `RuleEngineAccessControlShared` folded + into `RuleEngine`, so `RuleEngine2771` extends `RuleEngine` (`D-2`; 112 -> 111 contracts); the deployables moved + to `src/deployment/accessControl/` and `src/deployment/ownable/`; the view loops read `_rules` directly and + cache the rule (`A-3`, `B-1`); `addRule` / `removeRule` rely on the set's return value (`B-2`); every + conditional `revert` became a `require` (`E-2`); `IRule` was narrowed with the legacy ID still accepted + (`I-1`); stale NatSpec fixed (`G-2`). The `calls-loop` instances are the same calls in the same five functions + (`IRule(_rules.pos(i))` instead of `IRule(rule(i))` in the views); the events are unchanged, and their NatSpec + now records why they stay unindexed. + +- **rc7 security review fixes, after the `3055fe2` run** (`efaf860` F-1, `9c43b01` F-2, `c7a19c7` F-3): + `RuleEngineOwnable2Step.acceptOwnership` re-checks the rule-account guard; an administrative unbind revokes the + token's self-binding approval (`TokenBindingExtendedModule._unbindToken` override); rules and bound tokens are + kept disjoint (`_checkBindingTarget` hook, bound-token check in `_checkRule`). Checks and one internal hook: no + external call in a loop, no event. The report is byte-identical to the `3055fe2` one. + +**Runs:** `a91ca9a` (2026-10-14), `4946c87`, `850976f` + pragma, `3055fe2` (2026-10-15), and this final run at `29556e5` (2026-10-16). +Same 12 findings each time; only `file:line` positions moved with the edited files. + +The rest of rc7 is build and dependency changes: solc 0.8.36 -> **0.8.37**, EVM Prague -> **Osaka**, CMTAT +v3.3.0-rc4 (NatSpec-only change to `IRuleEngine`), forge-std v1.17.0, and T-REX 4.2.0-beta1 in `lib/ERC-3643`. +None of these produced a finding. `lib/ERC-3643` is still imported by nothing under `src/` (only by +`test/ERC3643Real/`, which the default Foundry profile skips), so the `lib/` count stays at 0. + +**Tooling note:** the global Slither install (Python 3.10 site-packages) no longer starts after the system moved +to Python 3.14. The same version, 0.11.5, was run in an isolated `uvx` environment on Python 3.12, so the +results are comparable with rc6. + +## Detailed triage + +### IDs 0-9: `calls-loop` + +Ten instances across `RulesManagementModule._transferred` (both overloads, `RulesManagementModule.sol:205-210` +and `:225-230`), `RuleEngineBase._detectTransferRestriction` (`RuleEngineBase.sol:169-178`), +`_detectTransferRestrictionFrom` (`:188-202`) and `_messageForTransferRestriction` (`:214-226`). Slither counts one +instance per call path that reaches the loop (for example `created`, `destroyed` and `transferred` all reach the +3-argument `_transferred`). + +The engine exists to call a configurable list of rule contracts, so an external call inside a loop is the +product, not a defect. The risk the detector points at — unbounded iteration — is bounded on-chain by +`maxRules` (default **10**, `DEFAULT_MAX_RULES`), and the cap is emitted at deployment so it is visible from the +event log alone. + +Rules are trusted business logic by convention: the engine refuses to grant a role to an address currently +configured as a rule, and the documentation states that rule contracts must not hold `RULES_MANAGEMENT_ROLE`. + +**Decision: accepted by design.** Documented in `doc/technical/RuleEngine-with-CMTAT.md` §4.1 and +`RuleEngine-with-ERC3643.md` §4.4, and recorded as `A-3` in the rc5 `CLAUDE_ANALYSIS.md`. + +### IDs 10-11: `unindexed-event-address` + +`TokenBound(address token)` and `TokenUnbound(address token)`, declared in `ITokenBinding.sol` (lines 23 and +31), pass their address parameter without `indexed`. + +The ERC-3643 reference implementation declares the same two events **unindexed**: + +```solidity +// lib/ERC-3643/contracts/compliance/modular/IModularCompliance.sol:82,89 +event TokenBound(address _token); +event TokenUnbound(address _token); +``` + +(identically in `compliance/legacy/ICompliance.sol:85,92`.) + +Adding `indexed` would move the parameter from the data section into a topic, changing the topic layout and +breaking any indexer written against the ERC-3643 interface. The correct place to change this is the standard. + +The move to `ITokenBinding` does not weaken that argument: `IERC3643Compliance` inherits the interface, so an +ERC-3643 consumer still sees exactly the reference signature. The generic interface deliberately kept it rather +than "improving" it, precisely so a binding registry reused elsewhere emits the same event an ERC-3643 indexer +already understands. + +Note the contrast with `TokenSelfBindingApprovalSet`, which *is* indexed: it is specific to this project's +extended module and carries no conformance obligation, so indexing it was free. + +Since the code-quality review (`C-2`), the NatSpec of both events in `ITokenBinding.sol` says they mirror the +ERC-3643 declaration and must stay non-indexed, so the decision is recorded next to the code. + +**Decision: accepted by design (spec conformance).** + +## Conclusion + +**No actionable security fixes are required from this Slither run.** Both detectors are architectural by-design +outcomes, and neither is exploitable: `calls-loop` describes the engine's core dispatch, bounded by an on-chain +cap, and `unindexed-event-address` reflects deliberate conformance with the ERC-3643 event signatures. diff --git a/doc/security/audits/tools/v3.0.0-rc7/slither-report.md b/doc/security/audits/tools/v3.0.0-rc7/slither-report.md new file mode 100644 index 00000000..2f3ccb69 --- /dev/null +++ b/doc/security/audits/tools/v3.0.0-rc7/slither-report.md @@ -0,0 +1,146 @@ +# Slither report — v3.0.0-rc7 + +| | | +|---|---| +| **Tool** | Slither 0.11.5 (run with `uvx --python 3.12 --from slither-analyzer==0.11.5`) | +| **Scope** | `src/`, **mocks excluded** | +| **Compiler** | solc 0.8.37, EVM Osaka, `pragma solidity ^0.8.27` | +| **Contracts analysed** | 111 | +| **Date** | 2026-10-16 | +| **Commit** | `29556e5` (final rc7 code: `src/` as of `c7a19c7`, after the rc7 security review fixes F-1 to F-3) | + +```bash +slither . --checklist --filter-paths "openzeppelin-contracts|test|CMTAT|forge-std|mocks" \ + > doc/security/audits/tools/v3.0.0-rc7/slither-report.md +``` + +**Result: 0 High · 0 Medium · 10 Low · 2 Informational — nothing to fix.** + +| Detector | Severity | Instances | Assessment | +|---|---|---|---| +| `calls-loop` | Low | 10 | **By design** — the engine iterates its rule set; bounded by `maxRules` (default 10) | +| `unindexed-event-address` | Informational | 2 | **By design (spec conformance)** — `TokenBound` / `TokenUnbound` keep the unindexed signature of ERC-3643 | + +**Scope verified:** `grep -c 'lib/\|node_modules/'` = **0** and `grep -c 'src/mocks/'` = **0** in this report, so +no vendored dependency or mock contract entered the analysis. + +**Delta from the previous rc7 run (`850976f` + pragma): none in findings.** Same two detectors, same 10 + 2 +instances, in the same functions; only `file:line` positions moved. The contract count drops 112 -> 111 because +`RuleEngineAccessControlShared` was folded into `RuleEngine` (code-quality review `D-2`). The other changes made +since (`A-3`, `B-1`, `B-2`, `E-2`, `I-1`, `G-2`, deployables moved to `src/deployment/accessControl/` and +`src/deployment/ownable/`) touch the loops' bodies, the error style and comments, not the looped external calls +or the events. **Delta from v3.0.0-rc6: none in findings** (108 contracts then). + +**Delta from the run at `3055fe2` (before the rc7 security review fixes): none.** The output is byte-identical, +including every `file:line`. The fixes (rule-account check in `RuleEngineOwnable2Step.acceptOwnership`, approval +revoked on an administrative unbind, rules and bound tokens kept disjoint) add checks and one internal hook, but +no external call in a loop and no event. + +Triage and per-finding reasoning: [slither-report-feedback.md](./slither-report-feedback.md). +Overview of all analyses: [AUDIT_OVERVIEW.md](../../AUDIT_OVERVIEW.md). + +--- +**THIS CHECKLIST IS NOT COMPLETE**. Use `--show-ignored-findings` to show all the results. +Summary + - [calls-loop](#calls-loop) (10 results) (Low) + - [unindexed-event-address](#unindexed-event-address) (2 results) (Informational) +## calls-loop +Impact: Low +Confidence: Medium + - [ ] ID-0 +[RulesManagementModule._transferred(address,address,uint256)](src/modules/RulesManagementModule.sol#L205-L210) has external calls inside a loop: [IRule(_rules.pos(i)).transferred(from,to,value)](src/modules/RulesManagementModule.sol#L208) + Calls stack containing the loop: + RuleEngineBase.created(address,uint256) + +src/modules/RulesManagementModule.sol#L205-L210 + + + - [ ] ID-1 +[RuleEngineBase._detectTransferRestrictionFrom(address,address,address,uint256)](src/RuleEngineBase.sol#L188-L202) has external calls inside a loop: [restriction = IRule(_rules.pos(i)).detectTransferRestrictionFrom(spender,from,to,value)](src/RuleEngineBase.sol#L196) + Calls stack containing the loop: + RuleEngineBase.canTransferFrom(address,address,address,uint256) + RuleEngineBase.detectTransferRestrictionFrom(address,address,address,uint256) + +src/RuleEngineBase.sol#L188-L202 + + + - [ ] ID-2 +[RuleEngineBase._messageForTransferRestriction(uint8)](src/RuleEngineBase.sol#L214-L226) has external calls inside a loop: [rule_.messageForTransferRestriction(restrictionCode)](src/RuleEngineBase.sol#L222) + Calls stack containing the loop: + RuleEngineBase.messageForTransferRestriction(uint8) + +src/RuleEngineBase.sol#L214-L226 + + + - [ ] ID-3 +[RuleEngineBase._detectTransferRestrictionFrom(address,address,address,uint256)](src/RuleEngineBase.sol#L188-L202) has external calls inside a loop: [restriction = IRule(_rules.pos(i)).detectTransferRestrictionFrom(spender,from,to,value)](src/RuleEngineBase.sol#L196) + Calls stack containing the loop: + RuleEngineBase.detectTransferRestrictionFrom(address,address,address,uint256) + +src/RuleEngineBase.sol#L188-L202 + + + - [ ] ID-4 +[RulesManagementModule._transferred(address,address,address,uint256)](src/modules/RulesManagementModule.sol#L225-L230) has external calls inside a loop: [IRule(_rules.pos(i)).transferred(spender,from,to,value)](src/modules/RulesManagementModule.sol#L228) + Calls stack containing the loop: + RuleEngineBase.transferred(address,address,address,uint256) + +src/modules/RulesManagementModule.sol#L225-L230 + + + - [ ] ID-5 +[RulesManagementModule._transferred(address,address,uint256)](src/modules/RulesManagementModule.sol#L205-L210) has external calls inside a loop: [IRule(_rules.pos(i)).transferred(from,to,value)](src/modules/RulesManagementModule.sol#L208) + Calls stack containing the loop: + RuleEngineBase.transferred(address,address,uint256) + +src/modules/RulesManagementModule.sol#L205-L210 + + + - [ ] ID-6 +[RulesManagementModule._transferred(address,address,uint256)](src/modules/RulesManagementModule.sol#L205-L210) has external calls inside a loop: [IRule(_rules.pos(i)).transferred(from,to,value)](src/modules/RulesManagementModule.sol#L208) + Calls stack containing the loop: + RuleEngineBase.destroyed(address,uint256) + +src/modules/RulesManagementModule.sol#L205-L210 + + + - [ ] ID-7 +[RuleEngineBase._detectTransferRestriction(address,address,uint256)](src/RuleEngineBase.sol#L169-L178) has external calls inside a loop: [restriction = IRule(_rules.pos(i)).detectTransferRestriction(from,to,value)](src/RuleEngineBase.sol#L172) + Calls stack containing the loop: + RuleEngineBase.detectTransferRestriction(address,address,uint256) + +src/RuleEngineBase.sol#L169-L178 + + + - [ ] ID-8 +[RuleEngineBase._messageForTransferRestriction(uint8)](src/RuleEngineBase.sol#L214-L226) has external calls inside a loop: [rule_.canReturnTransferRestrictionCode(restrictionCode)](src/RuleEngineBase.sol#L221) + Calls stack containing the loop: + RuleEngineBase.messageForTransferRestriction(uint8) + +src/RuleEngineBase.sol#L214-L226 + + + - [ ] ID-9 +[RuleEngineBase._detectTransferRestriction(address,address,uint256)](src/RuleEngineBase.sol#L169-L178) has external calls inside a loop: [restriction = IRule(_rules.pos(i)).detectTransferRestriction(from,to,value)](src/RuleEngineBase.sol#L172) + Calls stack containing the loop: + RuleEngineBase.canTransfer(address,address,uint256) + RuleEngineBase.detectTransferRestriction(address,address,uint256) + +src/RuleEngineBase.sol#L169-L178 + + +## unindexed-event-address +Impact: Informational +Confidence: High + - [ ] ID-10 +Event [ITokenBinding.TokenBound(address)](src/interfaces/ITokenBinding.sol#L23) has address parameters but no indexed parameters + +src/interfaces/ITokenBinding.sol#L23 + + + - [ ] ID-11 +Event [ITokenBinding.TokenUnbound(address)](src/interfaces/ITokenBinding.sol#L31) has address parameters but no indexed parameters + +src/interfaces/ITokenBinding.sol#L31 + + diff --git a/doc/specification/Cover_RuleEngine_specification_overview.odg b/doc/specification/Cover_RuleEngine_specification_overview.odg new file mode 100644 index 00000000..f509d81b Binary files /dev/null and b/doc/specification/Cover_RuleEngine_specification_overview.odg differ diff --git a/doc/specification/Cover_RuleEngine_specificationv3.0.0-rc0.odg b/doc/specification/Cover_RuleEngine_specificationv3.0.0-rc0.odg new file mode 100644 index 00000000..b55f9075 Binary files /dev/null and b/doc/specification/Cover_RuleEngine_specificationv3.0.0-rc0.odg differ diff --git a/doc/specification/RuleEngine_specificationv3.0.0-rc0.odg b/doc/specification/RuleEngine_specificationv3.0.0-rc0.odg deleted file mode 100644 index b6f6e3fd..00000000 Binary files a/doc/specification/RuleEngine_specificationv3.0.0-rc0.odg and /dev/null differ diff --git a/doc/specification/previous_specification/rc6/Cover_RuleEngine_specification_overview.pdf b/doc/specification/previous_specification/rc6/Cover_RuleEngine_specification_overview.pdf new file mode 100644 index 00000000..1f5234cb Binary files /dev/null and b/doc/specification/previous_specification/rc6/Cover_RuleEngine_specification_overview.pdf differ diff --git a/doc/specification/previous_specification/rc6/Cover_RuleEngine_specificationv3.0.0-rc0.pdf b/doc/specification/previous_specification/rc6/Cover_RuleEngine_specificationv3.0.0-rc0.pdf new file mode 100644 index 00000000..4e145275 Binary files /dev/null and b/doc/specification/previous_specification/rc6/Cover_RuleEngine_specificationv3.0.0-rc0.pdf differ diff --git a/doc/specification/previous_specification/rc6/RuleEngineSpecificationOverviewv3.0.0-rc6.pdf b/doc/specification/previous_specification/rc6/RuleEngineSpecificationOverviewv3.0.0-rc6.pdf new file mode 100644 index 00000000..72ef1b50 Binary files /dev/null and b/doc/specification/previous_specification/rc6/RuleEngineSpecificationOverviewv3.0.0-rc6.pdf differ diff --git a/doc/specification/previous_specification/rc6/RuleEngineSpecificationv3.0.0-rc6.pdf b/doc/specification/previous_specification/rc6/RuleEngineSpecificationv3.0.0-rc6.pdf new file mode 100644 index 00000000..66de67d8 Binary files /dev/null and b/doc/specification/previous_specification/rc6/RuleEngineSpecificationv3.0.0-rc6.pdf differ diff --git a/doc/technical/RuleEngine-with-CMTAT.md b/doc/technical/RuleEngine-with-CMTAT.md index 43e643a5..4897e9ce 100644 --- a/doc/technical/RuleEngine-with-CMTAT.md +++ b/doc/technical/RuleEngine-with-CMTAT.md @@ -28,27 +28,78 @@ if (spender != address(0)) { } ``` -The `spender` value comes from `CMTATBaseCommon`: +The `spender` value comes from `CMTATBaseCommon`. Every CMTAT path that reaches the engine (CMTAT v3.3.0): -| CMTAT operation | spender passed | Overload called | -|---|---|---| -| `transfer(to, value)` | `address(0)` | **3-argument** `transferred(from, to, value)` | -| `transferFrom(from, to, value)` | `_msgSender()` | 4-argument `transferred(spender, from, to, value)` | -| `mint(to, value)` | `_msgSender()` | 4-argument, with `from == address(0)` | -| `burn(from, value)` | `_msgSender()` | 4-argument, with `to == address(0)` | +| CMTAT operation | `spender` passed | `from` | `to` | Overload called | +|---|---|---|---|---| +| `transfer(to, value)` | `address(0)` | holder | recipient | **3-argument** `transferred(from, to, value)` | +| `transferFrom(from, to, value)` | `_msgSender()` | holder | recipient | 4-argument `transferred(spender, from, to, value)` | +| `mint`, `batchMint`, `crosschainMint`, mint leg of `burnAndMint` | operator (`_msgSender()`) | `address(0)` | recipient | 4-argument | +| `burn`, `batchBurn`, `burnFrom`, self `burn(uint256)`, `crosschainBurn`, burn leg of `burnAndMint` | operator (`_msgSender()`) | holder | `address(0)` | 4-argument | +| minter `batchTransfer(tos, values)` | minter (`_msgSender()`) | **minter** | recipient | 4-argument, **`spender == from`** | +| `forcedTransfer` (enforcer) | — | — | — | **not called** | + +Points to note in this table: + +- **`spender == from`** happens on two paths: the minter `batchTransfer` and a holder calling + `transferFrom` on its own tokens. A rule that screens the spender screens the minter a second time there. +- **`burn` and `burnFrom` are indistinguishable** to the engine: both arrive as `(operator, holder, address(0), value)`. +- **`forcedTransfer` bypasses the engine.** Stateful rules are not notified and observing rules are not + consulted. This differs from ERC-3643 T-REX, whose `forcedTransfer` notifies the compliance contract. + +The reference list is CMTAT's own [`doc/technical/ruleengine-integration.md`](https://github.com/CMTA/CMTAT/blob/v3.3.0-rc4/doc/technical/ruleengine-integration.md) (§"Runtime Call Flow"), whose routing is pinned by CMTAT's `RuleEngineSpenderDispatchCommon.js` tests. Two consequences follow: - A **plain transfer never carries a spender**. The zero address is a branch condition inside CMTAT and is never forwarded, so the engine is never called with a zero spender. -- Since CMTAT v3.3.0, **mint and burn go through the 4-argument overload** with the operator as `spender`. +- Since CMTAT v3.3.0, **mint, burn and the minter `batchTransfer` go through the 4-argument overload** with the operator as `spender` (documented in the `IRuleEngine.transferred` NatSpec since CMTAT v3.3.0-rc4). A rule that rejects unknown spenders must skip or adapt that check when `from == address(0)` (mint) or `to == address(0)` (burn), or it will block issuance and redemption. +- **On CMTAT v3.0.0 – v3.2.0, mint, burn and the minter transfer arrive on the 3-argument overload** + (`_checkTransferred(address(0), ...)` in `lib/CMTATv3.0.0/contracts/modules/0_CMTATBaseCommon.sol`). The engine + works with these versions, but a spender-keyed rule (a per-minter mint allowance, minter screening) is inert + there: it never sees the operator. See [CMTAT v3.0.0](#cmtat-v300). **CMTAT never calls `created()` or `destroyed()`.** Those belong to `IERC3643Compliance` and are used only by ERC-3643 tokens. The 4-argument `transferred` is conversely declared by CMTAT's `IRuleEngine` and is never reached by an ERC-3643 token. +### CMTAT v3.0.0 + +CMTAT v3.0.0 is the last audited CMTAT release, and the oldest one the engine supports. It is pinned as the +submodule `lib/CMTATv3.0.0` (remapped `CMTATv3.0.0/`) so the engine is tested against it. + +The engine is unchanged: the token sets it with `setRuleEngine(IRuleEngine)` and calls the same two overloads, +chosen by the same `spender != address(0)` branch (`ValidationModuleRuleEngine._transferred` in v3.0.0). What +differs is the spender CMTAT passes. In v3.0.0 (`modules/0_CMTATBaseCommon.sol`) only `transferFrom` carries +one; mint, burn and the minter transfer call `_checkTransferred(address(0), ...)`: + +| CMTAT v3.0.0 operation | `spender` passed | `from` | `to` | Overload called | +|---|---|---|---|---| +| `transfer(to, value)` | `address(0)` | holder | recipient | 3-argument | +| `transferFrom(from, to, value)` | `_msgSender()` | holder | recipient | 4-argument | +| `mint`, `batchMint`, `crosschainMint` | `address(0)` | `address(0)` | recipient | **3-argument** (4-argument since v3.3.0) | +| `burn`, `batchBurn`, `burnFrom`, `crosschainBurn` | `address(0)` | holder | `address(0)` | **3-argument** (4-argument since v3.3.0) | +| minter `batchTransfer(tos, values)` | `address(0)` | minter | recipient | **3-argument** (4-argument since v3.3.0) | +| `forcedTransfer` | — | — | — | not called | + +Consequences for an integrator on v3.0.0 – v3.2.0: + +- **Spender-keyed rules are inert on mint and burn.** A rule that acts only on the 4-argument path, such as a + per-minter mint allowance (`RuleMintAllowance` in the Rules repository), never sees the operator, so it + neither debits nor blocks a mint. Minter screening by a deny-list does not happen either. +- **Rules enforced on the 3-argument path still apply to mint and burn**, with `from == address(0)` for a mint + and `to == address(0)` for a burn, exactly as on an ERC-3643 token. +- **`transferFrom` is the only operation with a spender**, so a spender whitelist screens it as on later + versions. + +Pinned by `RuleEngine/RulesManagementModuleTest/CMTATOperationRoutingV3.t.sol` (10 tests): for `transfer`, +`transferFrom`, `mint` and `burn`, the exact overload and arguments reaching the engine and the rule +(`vm.expectCall`), and the absence of the other overload. A rule rejecting that overload blocks each operation, +and a rule enforced only on the 4-argument path lets mint and burn through. The other `…V3` suites (§5) run +the integration and whitelist tests against the same v3.0.0 token. + ### Read-only path CMTAT exposes the ERC-1404 view path, which the engine answers by iterating the same rules and returning the **first non-zero** restriction code: @@ -57,24 +108,38 @@ CMTAT exposes the ERC-1404 view path, which the engine answers by iterating the - `detectTransferRestrictionFrom(spender, from, to, value)` / `canTransferFrom(spender, from, to, value)` - `messageForTransferRestriction(code)` — resolves the code against the rule that claims it +**Pre-flighting a mint or a burn.** The engine and every rule read `from == address(0)` as a mint and +`to == address(0)` as a burn. The **token's** `detectTransferRestriction*` does not: CMTAT scopes it to +`transfer` / `transferFrom` and answers, for example, `TRANSFER_REJECTED_PAUSED` for `from == address(0)` while +paused, although `mint` proceeds while paused (see the header of CMTAT's `ValidationModuleERC1404.sol`). To +predict a mint or a burn, call `canTransfer*` on the token, which branches on the zero address, or +`detectTransferRestriction*` on the engine directly — not `detectTransferRestriction*` on the token. + ## 3. Configuration ### 3.1 Deploy the RuleEngine -Three deployable variants share identical core logic and differ only in access control. Pick one: +Six deployable variants share identical core logic and differ only in access control and ERC-2771 support. Pick one: | Contract | Access control | Use case | |---|---|---| -| `RuleEngine` | Role-based (`AccessControlEnumerable`) | Multiple operators, granular permissions | -| `RuleEngineOwnable` | ERC-173 `Ownable` | Single owner | -| `RuleEngineOwnable2Step` | ERC-173 `Ownable2Step` | Single owner, safer handover | +| `RuleEngine` | Role-based (`AccessControlEnumerable`), no ERC-2771 | Multiple operators, granular permissions | +| `RuleEngine2771` | Role-based, with an immutable ERC-2771 forwarder | Same, administered through meta-transactions | +| `RuleEngineOwnable` | ERC-173 `Ownable`, no ERC-2771 | Single owner | +| `RuleEngineOwnable2771` | ERC-173 `Ownable`, with an immutable ERC-2771 forwarder | Single owner, meta-transactions | +| `RuleEngineOwnable2Step` | ERC-173 `Ownable2Step`, no ERC-2771 | Single owner, safer handover | +| `RuleEngineOwnable2Step2771` | ERC-173 `Ownable2Step`, with an immutable ERC-2771 forwarder | Single owner, safer handover, meta-transactions | ```solidity -// admin, trusted ERC-2771 forwarder (address(0) to disable gasless), token to bind (may be address(0)) -RuleEngine engine = new RuleEngine(admin, forwarder, address(0)); +// admin, token to bind (may be address(0)) +RuleEngine engine = new RuleEngine(admin, address(0)); +// admin, trusted ERC-2771 forwarder, token to bind (may be address(0)) +RuleEngine2771 engine2771 = new RuleEngine2771(admin, forwarder, address(0)); ``` -The forwarder is **immutable** — it is fixed at construction and cannot be changed afterwards. +The forwarder is **immutable** — it is fixed at construction and cannot be changed afterwards. The ownable +variants follow the same pattern: `RuleEngineOwnable(owner, token)` / `RuleEngineOwnable2771(owner, forwarder, token)`, +and likewise for `RuleEngineOwnable2Step` / `RuleEngineOwnable2Step2771`. ### 3.2 Bind the token to the engine @@ -109,7 +174,17 @@ engine.addRule(IRule(address(rule))); // RULES_MANAGEMENT_ROLE, engine.setRules(rulesArray); // replaces the whole set atomically ``` -A rule must implement `IRule` and advertise `RuleInterfaceId.IRULE_INTERFACE_ID` (`0x2497d6cb`) through ERC-165; the engine validates this on `addRule` and rejects anything else. Rules run **in declaration order** and the first one to revert aborts the whole transaction. +A rule must implement `IRule` and advertise `RuleInterfaceId.IRULE_INTERFACE_ID` (`0xb1a69752`) through ERC-165, or the pre-rc7 `IRULE_LEGACY_INTERFACE_ID` (`0x2497d6cb`); the engine validates this on `addRule` and rejects anything else. The rules of [CMTA/Rules](https://github.com/CMTA/Rules) up to v0.6.0 advertise the legacy ID. Rules run **in declaration order** and the first one to revert aborts the whole transaction. + +The operation rules of CMTA/Rules accept `transferred` only from a caller bound on the rule itself, so tell them about the engine before the first transfer: + +```solidity +conditionalTransfer.bindToken(address(token)); // RuleConditionalTransferLight +conditionalTransfer.bindRuleEngine(address(engine)); // ... and the engine that relays the token +mintAllowance.bindToken(address(engine)); // RuleMintAllowance: the engine is its caller +``` + +`RuleConditionalTransferLightMultiToken` is the exception: it is never added to an engine (see [doc/README.md §Available Rules](../README.md#available-rules)). ### 3.5 Roles reference (`RuleEngine` variant) @@ -156,6 +231,11 @@ Any stateful rule that keeps per-address accounting therefore mixes state across Only bind tokens that are equally trusted and governed together. Unbinding does not retroactively separate state already accumulated. +Some rules of [CMTA/Rules](https://github.com/CMTA/Rules) cannot be shared at all: + +- `RuleMaxTotalSupply`, `RuleChainlinkPoR` (and their ERC-3643 variants) and `RuleMaxBalance` read `totalSupply()` / `balanceOf()` from a token set at deployment, not from the token that triggered the check. Behind an engine bound to several tokens, every token is checked against that one token's supply or balances. Deploy one instance per token, in an engine dedicated to that token. +- `RuleConditionalTransferLight` keys approvals `(from, to, value)` with no token dimension: an approval recorded for one token can be consumed by a transfer of another. Bind it only to an engine that serves a single token. + ### 4.5 Restriction codes must be unique across the rule set The engine returns the first non-zero code, and `messageForTransferRestriction` resolves a code against the first rule claiming it. @@ -166,8 +246,70 @@ If two rules share a code they must return the same message, or operators get in Rule contracts are called on every transfer and can revert or consume arbitrary gas. Treat them as trusted business logic. +**Rule `transferred*` hooks must not make a state-changing external call.** Only three CMTAT variants +(Standard, Snapshot and ERC-7551) wrap the `transferred` callback in a reentrancy guard; on the six others +(Debt, DebtEngine, Permit, UUPS, ERC-1363 and HolderList), CMTAT's safety rests on the trust model: the +engine, its rules and every contract they call must not hand control to untrusted code during +`transferred(...)`. The engine forwards the call to every rule, so the obligation lands on rule authors: a hook +may update the rule's own storage, but external reads (oracle, registry, price feed, token) must be `view` +calls, which run as `STATICCALL` and cannot re-enter the token. A called contract that reverts still blocks the +operation and the token's views, so it is trusted for availability too. See CMTAT's +[`ruleengine-integration.md`](https://github.com/CMTA/CMTAT/blob/v3.3.0-rc4/doc/technical/ruleengine-integration.md) §"Deployment Coverage". + Do not grant `RULES_MANAGEMENT_ROLE` to a rule contract — the engine blocks granting any role -to an address currently configured as a rule, but the check is one-directional and does not stop an already privileged address from later being added as a rule. +to an address currently configured as a rule, but the check is one-directional and does not stop an already privileged address from later being added as a rule. The ownable variants apply the same check to a new owner, and `RuleEngineOwnable2Step` applies it both when the owner is nominated and when it accepts. Binding is checked in both directions: a current rule cannot be bound as a token, and a bound token cannot be added as a rule. + +### 4.7 The trusted forwarder cannot act as a token + +The three `*2771` deployables inherit `ERC2771Context` (the others have no forwarder at all), but the bound-token gate (`onlyBoundToken`, on `transferred`, +`created` and `destroyed`) compares the raw **`msg.sender`**, not `_msgSender()`. CMTAT calls the engine directly +from its own transfer, mint and burn, never through a forwarder, so nothing changes for a real token. A forwarder +that appends a bound token's address, however, is rejected with `TokenBinding_UnauthorizedCaller`. + +This has been the case since v3.0.0-rc7. Before that, the gate used `_msgSender()`, and a trusted forwarder could +reach `transferred` "as" a bound token and drive stateful rules with no token movement: for example, consuming a +per-minter mint quota with no mint. This follows CMTAT's integration guide, which recommends `msg.sender` for this +check. Administrative calls still resolve through `_msgSender()`, so gasless administration keeps working. Use a +signature-verifying ERC-2771 forwarder, or deploy the contract without the `2771` suffix if gasless administration +is not needed. Details: +[doc/README.md §Gasless support](../README.md#gasless-support-erc-2771). + +### 4.8 A single rule can be the token's rule engine + +Since v3.0.0-rc7, `IRule` requires only what the engine calls, so it no longer includes `canTransfer` / +`canTransferFrom`. A rule that also wants this role implements CMTAT's `IRuleEngineERC1404` on top of `IRule` +and advertises `RULE_ENGINE_INTERFACE_ID`, as the four reference rules and every rule of [CMTA/Rules](https://github.com/CMTA/Rules) do. An issuer who needs exactly one rule can therefore skip the RuleEngine and +call `token.setRuleEngine(rule)`. CMTAT's `setRuleEngine` performs no ERC-165 check, so the token accepts any +contract with the right functions. The token then calls the rule directly: `transferred` (3- or 4-argument, +see §2), `canTransfer` / `canTransferFrom`, and the ERC-1404 views `detectTransferRestriction(From)` and +`messageForTransferRestriction`. This is the only configuration in which a rule's `canTransfer` / +`canTransferFrom` are called; behind a RuleEngine the engine computes them from `detectTransferRestriction*`. + +What changes compared to a rule behind an engine, and what a rule must do to support the role: + +- **There is no bound-token gate in front of the rule.** Behind an engine, only a bound token reaches the + rules. Standalone, the token calls the rule, and so can anyone else: `transferred` is a public function of the + rule. **A stateful rule must restrict who may call `transferred`** (its token when standalone, its engine + otherwise), or any account can consume its state, for example a transfer approval or a minter's allowance, + and block the real operation. The operation rules of CMTA/Rules do this: their hooks accept only the token + bound on the rule (`bindToken`), plus, for `RuleConditionalTransferLight`, an engine bound with + `bindRuleEngine`. The reference rules `RuleConditionalTransferLightMock` and `RuleMintAllowanceMock` do + **not**: they are test doubles, not production rules. Note that the same exposure exists behind an engine, + since a direct call to the rule never goes through the engine at all. +- **`canTransfer` / `canTransferFrom` must agree with `detectTransferRestriction*`.** The token answers + `canTransfer` from the rule's own function, not from the restriction code, so a stub that returns a constant + makes the token report a wrong answer. +- **The rule's codes and messages are the token's.** No engine stands in between to aggregate them, so the + token's `detectTransferRestriction` and `messageForTransferRestriction` return the rule's values unchanged + (after CMTAT's own codes: paused, deactivated, frozen). +- **One rule only.** Several restrictions need a RuleEngine. +- **CMTAT only.** An ERC-3643 token calls `created` / `destroyed` and the binding functions, which the + validation rules do not implement, so a rule cannot replace the engine for an ERC-3643 token. CMTA/Rules + recommends an engine for every ERC-3643 setup. + +Tested with each reference rule in `test/RuleStandalone/RuleStandaloneCMTAT.t.sol`: allowed and refused +transfers with the rule's code and message, the spender check on `transferFrom`, a conditional-transfer approval +consumed once, a mint allowance consumed by `mint`, and a reverting rule blocking the transfer. ## 5. What is tested @@ -179,11 +321,13 @@ to an address currently configured as a rule, but the check is one-directional a | Whitelist rule + CMTAT v3.0.0 | `RuleWhitelist/CMTATIntegrationV3.t.sol` | 11 | | Reverting rule propagation | `RuleEngine/RulesManagementModuleTest/RuleEngineOperationRevert.t.sol` | 1 | | Reverting rule, CMTAT v3.0.0 | `RuleEngine/RulesManagementModuleTest/RuleEngineOperationRevertV3.t.sol` | 1 | +| Overload per operation (transfer, transferFrom, mint, burn), CMTAT v3.0.0 | `RuleEngine/RulesManagementModuleTest/CMTATOperationRoutingV3.t.sol` | 10 | | Deployment script | `script/CMTATWithRuleEngineScript.t.sol` | 1 | +| A rule as the token's engine, no RuleEngine (§4.8) | `RuleStandalone/RuleStandaloneCMTAT.t.sol` | 9 | -**31 CMTAT-specific tests.** Coverage includes: a real `CMTATStandardStandalone` bound to the engine, transfers accepted and rejected through the whitelist, restriction-code propagation back to the token, and a rule that reverts mid-transfer. +**50 CMTAT-specific tests.** Coverage includes: a real `CMTATStandardStandalone` bound to the engine, transfers accepted and rejected through the whitelist, restriction-code propagation back to the token, and a rule that reverts mid-transfer. -**Backward compatibility is tested against two CMTAT versions.** The `…V3` suites deploy a real CMTAT **v3.0.0** token (submodule `lib/CMTATv3.0.0`, remapped `CMTATv3.0.0/`) alongside the current **v3.3.0-rc3** token (`lib/CMTAT`). +**Backward compatibility is tested against two CMTAT versions.** The `…V3` suites deploy a real CMTAT **v3.0.0** token (submodule `lib/CMTATv3.0.0`, remapped `CMTATv3.0.0/`) alongside the current **v3.3.0-rc4** token (`lib/CMTAT`). Both are bound to the same engine implementation. @@ -191,6 +335,8 @@ Both are bound to the same engine implementation. | RuleEngine | CMTAT | |---|---| +| v3.0.0-rc7 | ≥ v3.0.0, target v3.3.0-rc4 | +| v3.0.0-rc6 | ≥ v3.0.0, target v3.3.0-rc3 | | v3.0.0-rc5 | ≥ v3.0.0, target v3.3.0-rc3 | | v3.0.0-rc4 | ≥ v3.0.0, target v3.3.0-rc1 | | v1.0.2.1 | v2.3.0 (audited) | diff --git a/doc/technical/RuleEngine-with-ERC3643.md b/doc/technical/RuleEngine-with-ERC3643.md index 4ad00263..dc2f252b 100644 --- a/doc/technical/RuleEngine-with-ERC3643.md +++ b/doc/technical/RuleEngine-with-ERC3643.md @@ -14,7 +14,7 @@ _Diagram source: [doc/schema/plantuml/ruleengine-flow-erc3643.puml](../schema/pl ## 2. Which entry points an ERC-3643 token uses -In ERC-3643 the RuleEngine plays the role of the **compliance contract**. Taken from `Token.sol` in the reference implementation (submodule `lib/ERC-3643`, tag 4.1.3): +In ERC-3643 the RuleEngine plays the role of the **compliance contract**. Taken from `Token.sol` in the reference implementation (submodule `lib/ERC-3643`, tag 4.2.0-beta1; unchanged from 4.1.3 for these calls), and pinned against the real token by `test/ERC3643Real/` (section 5): | Token operation | Pre-check | State-changing callback | |---|---|---| @@ -42,14 +42,16 @@ section 4. ### 3.1 Deploy the RuleEngine -Same three variants as for CMTAT. ERC-3643's own specification points at ERC-173 for ownership: +Same six variants as for CMTAT. ERC-3643's own specification points at ERC-173 for ownership: > The standard relies on ERC-173 to define contract ownership, with the owner having the responsibility of setting the Compliance parameters and binding the Compliance to a Token contract. -so `RuleEngineOwnable` or `RuleEngineOwnable2Step` is the closest match to the spec, though `RuleEngine` (role-based) works identically and is preferable with multiple operators. +so `RuleEngineOwnable` or `RuleEngineOwnable2Step` (or their `*2771` versions) is the closest match to the spec, though `RuleEngine` / `RuleEngine2771` (role-based) work identically and are preferable with multiple operators. ```solidity -RuleEngineOwnable engine = new RuleEngineOwnable(owner, forwarder, address(0)); +RuleEngineOwnable engine = new RuleEngineOwnable(owner, address(0)); +// or, with an ERC-2771 forwarder for gasless administration: +RuleEngineOwnable2771 engine2771 = new RuleEngineOwnable2771(owner, forwarder, address(0)); ``` ### 3.2 Grant self-binding approval — required before `setCompliance` @@ -81,6 +83,8 @@ engine.isTokenSelfBindingApproved(address(token)); // -> true 2. Call `token.setCompliance(address(engine))`. 3. Optionally revoke the approval afterwards if no further migration is expected. +If the binding manager later unbinds the token (`unbindToken` / `unbindTokens`), the engine also revokes its self-binding approval, so the token cannot bind itself again without a new approval. A token that unbinds itself, when `setCompliance` moves it to another compliance contract, keeps its approval and can come back. + Without step 1, `setCompliance` reverts. This is exercised by `testSetComplianceRevertsWithoutSelfBindingApproval`. @@ -100,7 +104,15 @@ Identical to the CMTAT case: engine.addRule(IRule(address(rule))); ``` -Rules must implement `IRule` and advertise `RuleInterfaceId.IRULE_INTERFACE_ID` via ERC-165. They run in declaration order; the first to revert aborts the transaction. +Rules must implement `IRule` and advertise `RuleInterfaceId.IRULE_INTERFACE_ID` (`0xb1a69752`) or the pre-rc7 `IRULE_LEGACY_INTERFACE_ID` (`0x2497d6cb`, advertised by [CMTA/Rules](https://github.com/CMTA/Rules) up to v0.6.0) via ERC-165. They run in declaration order; the first to revert aborts the transaction. + +**Not every rule works on an ERC-3643 token.** The token forwards no spender (`transfer` and `transferFrom` both call the 3-argument `transferred`) and calls compliance *after* it moves the value. In CMTA/Rules this means: + +- spender checks and flags never fire (`RuleSpenderWhitelist` is inert, the spender leg of the deny-lists and of `RuleERC2980` is skipped); +- the supply caps need their ERC-3643 variants, `RuleMaxTotalSupplyERC3643` and `RuleChainlinkPoRERC3643` (the stock rules count the minted amount twice); +- `RuleMaxBalance` and `RuleConditionalTransferLightMultiToken` are not supported, and `RuleMintAllowance` is inert: every mint passes. + +`RuleConditionalTransferLight` works, once bound with `bindToken(token)` and `bindRuleEngine(engine)`. Per-rule table: [doc/README.md §Available Rules](../README.md#available-rules), from the Rules repository's [compatibility matrix](https://github.com/CMTA/Rules/blob/main/doc/technical/guides/RULE_SEMANTICS.md#6-erc-3643-compatibility--which-rules-actually-work-on-a-t-rex-token). ### 3.5 Batch helpers @@ -133,8 +145,7 @@ The state-changing path is unaffected and still enforces correctly; the damage i ### 4.2 `address(0)` must be whitelisted for minting to work -**This concerns `RuleWhitelistMock`, a reference rule in `src/mocks/`, not a production rule.** Production rules live in [CMTA/Rules](https://github.com/CMTA/Rules) and may handle the sentinel differently — check the -rule you actually deploy. +**This concerns `RuleWhitelistMock`, a reference rule in `src/mocks/`, not a production rule.** Production rules live in [CMTA/Rules](https://github.com/CMTA/Rules) and handle the sentinel differently: there, `address(0)` can never be listed, and `RuleWhitelist` / `RuleERC2980` permit mint and burn through explicit `allowMint` / `allowBurn` flags (v0.6.0). Check the rule you actually deploy. The behavior is described here because the mock is what the examples, scripts and tests in this repository use, and because integrators copy it. @@ -155,6 +166,7 @@ per-address accounting mixes state across every bound token. - Only bind tokens that are equally trusted and governed together. - Unbinding does not retroactively separate state already accumulated in a rule. +- Some rules protect one token per instance: `RuleMaxTotalSupplyERC3643` and `RuleChainlinkPoRERC3643` read `totalSupply()` from a token set at deployment, and `RuleConditionalTransferLight` keys approvals with no token dimension. Use them only in an engine dedicated to that token. This matters more here than for CMTAT, because `bindTokens` makes multi-token binding a one-call operation. @@ -170,6 +182,12 @@ A gas-heavy rule affects every operation on every bound token. `TokenBinding_UnauthorizedCaller` for any caller that is not a bound token. Verified by `testUnboundCallerCannotCallTransferred` and `testUnboundCallerCannotCallCreatedOrDestroyed`. +The gate compares the raw `msg.sender`, not the ERC-2771 `_msgSender()`, and so does the token self-binding +check that `setCompliance` relies on. A trusted forwarder therefore cannot pass as a bound token, and it cannot +unbind a token approved for self-binding by claiming to be it. Both were possible up to v3.0.0-rc6. A T-REX token +calls `transferred` / `created` / `destroyed` and `bindToken` / `unbindToken(this)` directly, so it is unaffected. +See [RuleEngine-with-CMTAT.md §4.7](./RuleEngine-with-CMTAT.md#47-the-trusted-forwarder-cannot-act-as-a-token). + ### 4.6 Restriction codes must be unique across the rule set As with CMTAT: the engine returns the first non-zero code, so overlapping codes across rules produce inconsistent operator feedback unless they share the same message. @@ -179,22 +197,45 @@ As with CMTAT: the engine returns the first non-zero code, so overlapping codes `IERC7551Compliance` comes from `draft-IERC7551` and is not final. This project implements a subset focused on `canTransferFrom`. Do not assume full ERC-7551 conformance. -### 4.8 The reference T-REX token cannot be compiled into this test suite +### 4.8 The real T-REX token is tested in a separate Foundry profile -Relevant if you intend to add tests against the vendored implementation in `lib/ERC-3643`. Three independent blockers: +The vendored token (`lib/ERC-3643`, T-REX **4.2.0-beta1**) pins `pragma solidity 0.8.30` exactly, while this +project compiles with **0.8.37**, and it imports the `@onchain-id/solidity` npm package, which is not a +submodule. The suite that deploys it therefore runs in its own profile: -- it pins `pragma solidity 0.8.17` (exact), while this project compiles with **0.8.36**; -- it requires **OpenZeppelin 4.8.x**, while this project uses **5.7.0**; -- it imports the `onchain-id/solidity` package, which is not installed here. +```bash +FOUNDRY_PROFILE=erc3643 forge test +``` -Attempting it fails at resolution: +The CI workflow (`.github/workflows/ci.yml`) runs this profile in its own step, after the default `forge test`. -``` -Error: Encountered invalid solc version in lib/ERC-3643/contracts/token/Token.sol: -No solc version exists that matches the version requirement: =0.8.17 -``` +- `[profile.erc3643]` in `foundry.toml` builds the whole project at solc 0.8.30 (the engine is `^0.8.27`, + CMTAT and OpenZeppelin `^0.8.24` at most) into `out-erc3643/`, and runs only `test/ERC3643Real/`. +- The default profile lists `test/ERC3643Real/**` in `skip`, so a plain `forge test` is unaffected. +- `test/utils/onchainid/` holds minimal `IIdentity` / `IClaimIssuer` stubs, wired in by a **context-scoped** + remapping (`lib/ERC-3643/:@onchain-id/solidity/contracts/=...`) that applies to the ERC-3643 sources only. + It is declared in the profile, not in `remappings.txt`: `hardhat-foundry` reads `forge remappings` and + rejects context-scoped lines. +- T-REX 4.2.0-beta1 uses OpenZeppelin 5, so no second OpenZeppelin major is needed (4.1.3 required 4.8.x). +- The identity registry is `IdentityRegistryStub`, which answers `isVerified` from a test flag, so every + rejection observed comes from the engine. + +`test/RuleEngine/ERC3643TokenIntegration.t.sol` keeps driving `ERC3643TokenMock` in the default profile, so the +compliance surface is also covered by the ordinary `forge test` and by coverage. + +### 4.9 Compliance is notified after the state change -The integration tests therefore use `ERC3643TokenMock`, whose compliance interaction is copied from the reference `Token.sol` (the table in section 2 is taken from it directly). Compiling the real token would require unpinning the project compiler and vendoring a second OpenZeppelin major alongside the current one. +The reference `Token.sol` updates balances first and notifies compliance afterwards: `_transfer` then +`transferred`, `_mint` then `created`, `_burn` then `destroyed`. A rule that reads `totalSupply()` or +`balanceOf()` from inside the callback therefore sees the amount **already applied**, whereas CMTAT calls the +engine **before** the update. A supply or balance cap written for CMTAT (current value + amount ≤ cap) counts the +amount twice on an ERC-3643 token and rejects operations that should pass. + +Use the ERC-3643 variants of such rules where the Rules repository provides them +(`RuleMaxTotalSupplyERC3643`, `RuleChainlinkPoRERC3643`), and check each rule's documentation for ERC-3643 +support before binding an engine to a T-REX token. The pre-check `canTransfer` runs before the update, so it +does not show the problem. Pinned against the real token by `testComplianceIsNotifiedAfterTheMint`: a +CMTAT-style cap of 100 accepts the pre-check of a 100-token mint, then rejects it in `created`. ## 5. What is tested @@ -203,8 +244,9 @@ The integration tests therefore use `ERC3643TokenMock`, whose compliance interac | Compliance module, RBAC variant | `RuleEngine/ERC3643Compliance.t.sol` | 30 | | Compliance module, ownable variant | `RuleEngineOwnable/ERC3643Compliance.t.sol` | 29 | | End-to-end with an ERC-3643 style token | `RuleEngine/ERC3643TokenIntegration.t.sol` | 11 | +| End-to-end with the real T-REX 4.2.0-beta1 token (`FOUNDRY_PROFILE=erc3643`) | `ERC3643Real/ERC3643RealTokenRuleEngine.t.sol` | 13 | -**70 ERC-3643-specific tests.** The `RuleEngineOwnable2Step` suite exercises the same compliance surface again +**83 ERC-3643-specific tests** (70 in the default profile, 13 in the `erc3643` profile). The `RuleEngineOwnable2Step` suite exercises the same compliance surface again through its own variant. The end-to-end suite covers, using a token that drives the engine exactly as `Token.sol` does: @@ -217,6 +259,17 @@ The end-to-end suite covers, using a token that drives the engine exactly as `To - the two documented limitations above (`H-1` fail-open, `F-2` zero-address whitelist), pinned so a change in behaviour is noticed +The real-token suite (`test/ERC3643Real/`) checks the same surface against the genuine `Token`, plus what the +mock cannot show: + +- `init` self-binding the token through `setCompliance`, and reverting without self-binding approval +- mint pre-checked with `canTransfer(address(0), ...)` then notified through `created`, forwarded to the rules + as the 3-argument `transferred(address(0), to, value)`; burn through `destroyed` +- `transfer` and `transferFrom` both reaching the 3-argument `transferred` — the spender is never forwarded +- `forcedTransfer` notifying compliance, so a rule can block it (unlike CMTAT, whose `forcedTransfer` bypasses + the engine) +- the post-update notification order of section 4.9 + ## 6. Related documents - [RuleEngine-with-CMTAT.md](./RuleEngine-with-CMTAT.md) — the CMTAT counterpart diff --git a/doc/technical/TokenBinding-module.md b/doc/technical/TokenBinding-module.md index 2651e332..c93e017b 100644 --- a/doc/technical/TokenBinding-module.md +++ b/doc/technical/TokenBinding-module.md @@ -61,6 +61,7 @@ Two hooks are left to the embedding contract: |---|---|---| | `_onlyTokenBindingManager()` | access control for binding administration | abstract, must be implemented | | `_authorizeTokenBindingChange(address token)` | authorizes one bind/unbind | manager check | +| `_checkBindingTarget(address token)` | host-specific restriction on which addresses may be bound; reverts to reject | empty (`RuleEngineBase` rejects current rules) | A minimal deployment therefore only has to wire its access control model: @@ -111,17 +112,52 @@ These are properties of the registry itself, not of any standard built on it. while the token was bound. - **`address(0)` cannot be bound.** It could never call the engine, and binding it would only emit a `TokenBound` event that indexers would have to filter out. +- **Token identity uses `msg.sender`, administration uses `_msgSender()`.** `onlyBoundToken` and the token + self-binding check compare the raw `msg.sender`. A token never calls through a forwarder, so in a host that + inherits `ERC2771Context` the forwarder cannot pass as a bound or self-binding token. The manager path + (`_onlyTokenBindingManager`) is left to the host and normally resolves through `_msgSender()`, so binding + administration can stay gasless. Do not override `_checkBoundToken` back to `_msgSender()`. - **Binding and unbinding are not idempotent.** Re-binding a bound token reverts with `TokenBinding_TokenAlreadyBound`, and unbinding an unbound one with `TokenBinding_TokenNotBound`, so a redundant administrative call is reported rather than silently accepted. +- **Binding is a trust decision.** A bound address can drive every stateful downstream check (consume + approvals, allowances, counters) without moving any token. The registry cannot tell a token contract from an + EOA or any other contract, and a code-size check would not help: it is false for a contract under + construction, and it would block binding a token before it is deployed at a counterfactual (CREATE2) address. + Bind only the token contracts the host is meant to serve. The RuleEngine adds one restriction through + `_checkBindingTarget`: an address that is currently a rule cannot be bound, and `_checkRule` rejects a bound + token as a rule, so the two sets stay disjoint. +- **An administrative unbind revokes the self-binding approval.** When the binding manager unbinds a token + (`unbindToken` or `unbindTokens`), `TokenBindingExtendedModule._unbindToken` also clears the token's + self-binding approval and emits `TokenSelfBindingApprovalSet(token, false)`, so the token cannot undo the + manager's decision by binding itself again. A token that unbinds itself (`msg.sender == token`) keeps its + approval. A host that combines this module with another one defining `_unbindToken` must disambiguate the + override in favour of `TokenBindingExtendedModule`, as `ERC3643ComplianceExtendedModule` does. +- **Self-binding approvals have two events; indexers must handle both.** `setTokenSelfBindingApproval` emits + `TokenSelfBindingApprovalSet(address indexed token, bool approved)`; `setTokenSelfBindingApprovalBatch` emits + a single `TokenSelfBindingApprovalBatchSet(address[] tokens, bool approved)` with the array as passed, and no + per-token event. A log filter on the indexed `token` therefore misses batch updates, and the batch array also + lists tokens that were already at the requested value, and duplicates. Monitoring that must catch every token + gaining self-binding rights (which lets it unbind itself) subscribes to both events, or reads + `isTokenSelfBindingApproved(token)`, which is authoritative. Kept as is by decision; the alternatives + (per-token events, with or without a change check) are measured in the rc7 code-quality review, `C-2`. +- **The batch functions are atomic, on purpose.** `bindTokens` / `unbindTokens` apply the single-call rule to + every element: one token already bound (or listed twice) in `bindTokens`, or not bound in `unbindTokens`, + reverts the whole call, and the tokens processed before it in the same call are rolled back. This departs + from the batch convention used elsewhere in the project (the reference `RuleAddressList` rule skips elements + already in the target state so that one stale entry does not waste the whole batch). Binding is treated + differently because a binding change is security-relevant: a token that is already bound in the list is most + likely an operator mistake (wrong list, wrong environment), and it should stop the operation rather than be + silently skipped. The cost is that the operator re-submits a corrected list. An empty array is accepted as a + no-op, consistent with the batch rule (nothing to change, nothing reverts). ## 5. What is tested | Area | File | Tests | |---|---|---| | Standalone reuse, outside any compliance context | `test/TokenBinding/TokenBindingStandalone.t.sol` | 10 | -| Registry through the ERC-3643 surface, RBAC variant | `test/RuleEngine/ERC3643Compliance.t.sol` | 30 | -| Registry through the ERC-3643 surface, ownable variant | `test/RuleEngineOwnable/ERC3643Compliance.t.sol` | 29 | +| Registry through the ERC-3643 surface, RBAC variant | `test/RuleEngine/ERC3643Compliance.t.sol` | 31 | +| Registry through the ERC-3643 surface, ownable variant | `test/RuleEngineOwnable/ERC3643Compliance.t.sol` | 30 | ## 6. Related documents diff --git a/foundry.lock b/foundry.lock index fbd84ce1..4f0a7b14 100644 --- a/foundry.lock +++ b/foundry.lock @@ -5,6 +5,18 @@ "rev": "78e6e48e491e01e853e6490e061189875d4785ea" } }, + "lib/CMTATv3.0.0": { + "rev": "69eecc9735ce8ada84fd35801888b05747658939" + }, + "lib/ERC-3643": { + "rev": "a708758313f7589c6709c29d003f73b6db24663a" + }, + "lib/Rules": { + "tag": { + "name": "v0.6.0", + "rev": "283efe723225c89729fd618852a9c2705a47180b" + } + }, "lib/forge-std": { "rev": "8bbcf6e3f8f62f419e5429a0bd89331c85c37824" }, diff --git a/foundry.toml b/foundry.toml index 6aff2703..afebce1f 100644 --- a/foundry.toml +++ b/foundry.toml @@ -1,10 +1,43 @@ [profile.default] -solc = "0.8.36" +solc = "0.8.37" src = 'src' out = 'out' libs = ['lib'] optimizer = true optimizer_runs = 200 +evm_version = 'osaka' +# Handler-based invariant tests (test/utils/RuleEngineInvariantTestBase.sol, six deployables): 64 sequences of +# 50 calls each keep `forge test` fast; the defaults (256 x 500) take about 5 minutes. For a deeper run: +# FOUNDRY_INVARIANT_RUNS=256 FOUNDRY_INVARIANT_DEPTH=500 forge test --match-contract InvariantTest +invariant = { runs = 64, depth = 50 } +# The vendored ERC-3643 `Token.sol` (T-REX 4.2.0-beta1) pins `pragma solidity 0.8.30` exactly, which cannot +# share a compilation unit with solc 0.8.37. The tests that deploy the real token therefore live in their own +# directory and are built by the `erc3643` profile below. Run them with: +# FOUNDRY_PROFILE=erc3643 forge test +skip = ['test/ERC3643Real/**'] + +# Stays on evm_version 'prague': `osaka` is experimental in solc 0.8.30. The default profile targets osaka. +# Builds the project at solc 0.8.30 so the vendored ERC-3643 `Token.sol` compiles alongside our own contracts +# (`^0.8.20`; CMTAT and OpenZeppelin are `^0.8.24` at most, so 0.8.30 satisfies them). +[profile.erc3643] +solc = "0.8.30" +src = 'src' +out = 'out-erc3643' +libs = ['lib'] +optimizer = true +optimizer_runs = 200 evm_version = 'prague' +# Profiles inherit unspecified keys from [profile.default]: clear `skip`, or this profile would skip the very +# tests it exists to run. +skip = [] +match_path = 'test/ERC3643Real/*' +# ERC-3643 imports `@onchain-id/solidity`, an npm package rather than a submodule. `test/utils/onchainid/` +# holds minimal IIdentity / IClaimIssuer stubs, wired in by a CONTEXT-SCOPED remapping (the `lib/ERC-3643/:` +# prefix) so they apply to the ERC-3643 build only. It is declared here rather than in `remappings.txt` on +# purpose: `hardhat-foundry` reads `forge remappings` and rejects context-scoped lines. +remappings = [ + 'lib/ERC-3643/:@onchain-id/solidity/contracts/=test/utils/onchainid/', + 'ERC3643/=lib/ERC-3643/contracts/', +] # See more config options https://github.com/foundry-rs/foundry/tree/master/config diff --git a/hardhat.config.js b/hardhat.config.js index 302db33a..0a263be1 100644 --- a/hardhat.config.js +++ b/hardhat.config.js @@ -3,13 +3,13 @@ require("@nomicfoundation/hardhat-toolbox"); require("@nomicfoundation/hardhat-foundry"); module.exports = { solidity: { - version: "0.8.36", + version: "0.8.37", settings: { optimizer: { enabled: true, runs: 200 }, - evmVersion: "prague" + evmVersion: "osaka" } } }; diff --git a/lib/CMTAT b/lib/CMTAT index 658672f1..3d9b0e9e 160000 --- a/lib/CMTAT +++ b/lib/CMTAT @@ -1 +1 @@ -Subproject commit 658672f190d56d3f61663a7d6d51962b8980df70 +Subproject commit 3d9b0e9e7e372d3f6bb6b2fa2752e77874c22098 diff --git a/lib/ERC-3643 b/lib/ERC-3643 index dab1660f..a7087583 160000 --- a/lib/ERC-3643 +++ b/lib/ERC-3643 @@ -1 +1 @@ -Subproject commit dab1660fe594e17e83d691137ba67272534732ac +Subproject commit a708758313f7589c6709c29d003f73b6db24663a diff --git a/lib/Rules b/lib/Rules new file mode 160000 index 00000000..283efe72 --- /dev/null +++ b/lib/Rules @@ -0,0 +1 @@ +Subproject commit 283efe723225c89729fd618852a9c2705a47180b diff --git a/lib/forge-std b/lib/forge-std index 1801b054..f3dae6e6 160000 --- a/lib/forge-std +++ b/lib/forge-std @@ -1 +1 @@ -Subproject commit 1801b0541f4fda118a10798fd3486bb7051c5dd6 +Subproject commit f3dae6e6ee381f25eb6a246f7da9b85c91a68219 diff --git a/package-lock.json b/package-lock.json index 4d77cf1b..4f52bd1a 100644 --- a/package-lock.json +++ b/package-lock.json @@ -4,6 +4,7 @@ "requires": true, "packages": { "": { + "name": "RuleEngineNew", "devDependencies": { "@nomicfoundation/hardhat-foundry": "^1.2.1", "@nomicfoundation/hardhat-toolbox": "^6.1.2", @@ -2129,9 +2130,9 @@ } }, "node_modules/axios": { - "version": "1.19.0", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.19.0.tgz", - "integrity": "sha512-ht/iuYZXEjFxLH/Hkezgd7m6JKlHHXEUSneaDz8uZe1Gj5QZtCnpyDsckvAiEnT89OEbCLmnte4R4sn7P0EKFw==", + "version": "1.20.0", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.20.0.tgz", + "integrity": "sha512-r8aOh8j9cGKpgQAqpzrUHnSIc6a59Y3Xf/cv8sy1DrHCkZHzQGEuoq1tARk6qSyDdtQGSDgpb9kFlruzPvrgwg==", "dev": true, "license": "MIT", "dependencies": { @@ -2352,9 +2353,9 @@ } }, "node_modules/brace-expansion": { - "version": "2.1.4", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.4.tgz", - "integrity": "sha512-hGfVzPxthbf3+2yjg/RBs60cB0FhqBS/zvdV/4wn4/BmN0bNMMHPc4V/BbFieqf1TKAGGAHnY4eSjajCl0f2Xg==", + "version": "2.1.7", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.7.tgz", + "integrity": "sha512-uZbew1NqdmPDTMJ8ah1y+b+9QEJrfkXFk3RcTQw3X0jW/xRUvFKsg1CfQdSYGdTbXZWExtU3J3ccxtnfw1Fi0g==", "dev": true, "license": "MIT", "dependencies": { @@ -2681,9 +2682,9 @@ } }, "node_modules/cheerio/node_modules/undici": { - "version": "7.29.0", - "resolved": "https://registry.npmjs.org/undici/-/undici-7.29.0.tgz", - "integrity": "sha512-IDxfleLmmbSskfWSUATiN1nfn2rDuvnMOqb5CWR92iIfojA0Ud+ulOAAEQ57LPr9rWmsreUyf5lwyao+7GNNVw==", + "version": "7.30.0", + "resolved": "https://registry.npmjs.org/undici/-/undici-7.30.0.tgz", + "integrity": "sha512-dkrQXeHSaoamnItlYbmzG0wFYrM0ZwDxCIg0A7aKjTyyhh9svRzCNFEzV+Vm05/yehjCzjDZ31KXfGEjYSztDQ==", "dev": true, "license": "MIT", "engines": { @@ -4194,9 +4195,9 @@ "peer": true }, "node_modules/fast-uri": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.5.tgz", - "integrity": "sha512-gHwA1O9LDIcKunMKhObS/HimwtehO1nPUECKAu5TpKgaO19fcWEl4bliWe1jWxVFvIXztJjjQ4L8XQ1EU9f7Jw==", + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.8.tgz", + "integrity": "sha512-GZMtZUTNRpOVIECoXwLNZS5xUGE+mVNbTB8h/7Rwh2TFWcBQiPzTgyZi05BF9UMZKkLJv8XBRJTlU7zg8+ZfMg==", "dev": true, "funding": [ { @@ -4714,9 +4715,9 @@ } }, "node_modules/globby/node_modules/brace-expansion": { - "version": "1.1.18", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", - "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", + "version": "1.1.21", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz", + "integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==", "dev": true, "license": "MIT", "peer": true, @@ -4794,14 +4795,14 @@ } }, "node_modules/handlebars": { - "version": "4.7.9", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.9.tgz", - "integrity": "sha512-4E71E0rpOaQuJR2A3xDZ+GM1HyWYv1clR58tC8emQNeQe3RH7MAzSbat+V0wG78LQBo6m6bzSG/L4pBuCsgnUQ==", + "version": "4.7.10", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.10.tgz", + "integrity": "sha512-P5VJMVM7qgBn6vjXMw8WG9uVI+ncf2pi72j4de4yz5ZULLj2RGqLYaKOYGsgyrViQ0tePOVlN1tDCCXXtFqXKg==", "dev": true, "license": "MIT", "peer": true, "dependencies": { - "minimist": "^1.2.5", + "minimist": "^1.2.8", "neo-async": "^2.6.2", "source-map": "^0.6.1", "wordwrap": "^1.0.0" @@ -4817,9 +4818,9 @@ } }, "node_modules/hardhat": { - "version": "2.29.0", - "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-2.29.0.tgz", - "integrity": "sha512-tsj5mCSjDCFOhGfBl4vwqDEcwdlES9VUzRWfdrwvEVhus6D8W6u+WfUKRLLwFhKGS/8lKPoXGsjYWPXl3CCpOg==", + "version": "2.29.1", + "resolved": "https://registry.npmjs.org/hardhat/-/hardhat-2.29.1.tgz", + "integrity": "sha512-BVPE15F9+gWH5Eof7aAhprXTi05mNHwn32fwIKMeMFqrkU3Jun1f7NubXsJ0SOeMqu0mchF6KkW7rx1CHinlWw==", "dev": true, "license": "MIT", "dependencies": { @@ -5582,9 +5583,9 @@ } }, "node_modules/ip-address": { - "version": "10.5.0", - "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.5.0.tgz", - "integrity": "sha512-R5SnVLJmgYYvf2F2ZgwSBnelz5G4q5AxIC277GDfUaNbrZKNANcBC7RHqYYePlszf4kBolVkJauG0ZjHHFh55g==", + "version": "10.7.4", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-10.7.4.tgz", + "integrity": "sha512-DWBMKyeM25D70nrIiTkgQth59/G+naKOTep6huF9j+GmeK3DMD60Zvxg5d5qQnz+38AHgou6ean2LECX+lrKDg==", "dev": true, "license": "MIT", "engines": { @@ -5818,9 +5819,9 @@ "license": "MIT" }, "node_modules/js-yaml": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.1.tgz", - "integrity": "sha512-CY6crGq313MX8GkwvB7tzgp99vjQxY1++5y10/BKN/GUfHqWaOGQMNZkBvqSzsZKWk/ijwHlWzzkLulsGHhjWQ==", + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.3.2.tgz", + "integrity": "sha512-SFNOvSJ+Dgf/9An904Yx+CgSlIPCkIpao4qo51lpee25TIRejdH3rhR4EZMGoNx3/TP3O+wzWuiTFl4sqbltzA==", "dev": true, "funding": [ { @@ -7030,9 +7031,9 @@ } }, "node_modules/pbkdf2": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.5.tgz", - "integrity": "sha512-Q3CG/cYvCO1ye4QKkuH7EXxs3VC/rI1/trd+qX2+PolbaKG0H+bgcZzrTt96mMyRtejk+JMCiLUn3y29W8qmFQ==", + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.7.tgz", + "integrity": "sha512-nS4mvFgVwUrecPTRdpdseM2fwpdfnX0/HibA8DgBRQtihUAzHQYJFU2l+OlEtiXtpqkrMvCPDwyXMUnASDt6Qw==", "dev": true, "license": "MIT", "peer": true, @@ -7042,7 +7043,7 @@ "ripemd160": "^2.0.3", "safe-buffer": "^5.2.1", "sha.js": "^2.4.12", - "to-buffer": "^1.2.1" + "to-buffer": "^1.2.2" }, "engines": { "node": ">= 0.10" @@ -7402,9 +7403,9 @@ } }, "node_modules/recursive-readdir/node_modules/brace-expansion": { - "version": "1.1.18", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", - "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", + "version": "1.1.21", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz", + "integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==", "dev": true, "license": "MIT", "peer": true, @@ -7622,9 +7623,9 @@ } }, "node_modules/sc-istanbul/node_modules/brace-expansion": { - "version": "1.1.18", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", - "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", + "version": "1.1.21", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz", + "integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==", "dev": true, "license": "MIT", "peer": true, @@ -7664,9 +7665,9 @@ } }, "node_modules/sc-istanbul/node_modules/js-yaml": { - "version": "3.15.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.15.1.tgz", - "integrity": "sha512-S99WuO3HlhO3XN41EtYUNl9zzXjoJx7QvmipxsJVxtCBT0YHEFy+iOJhjSvrmV12nYhWpZaM8lPHkJm0yUMbag==", + "version": "3.15.2", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.15.2.tgz", + "integrity": "sha512-6EuL879VkRA+1Cz578mKMiKvjPNEuk6+r1JaFzoSWejZmtf7xWbIyw1e3KkxlkzTIt9Taw6JBhEppG7utc1P+w==", "dev": true, "license": "MIT", "peer": true, @@ -7905,9 +7906,9 @@ } }, "node_modules/shelljs/node_modules/brace-expansion": { - "version": "1.1.18", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", - "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", + "version": "1.1.21", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz", + "integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==", "dev": true, "license": "MIT", "peer": true, @@ -8917,9 +8918,9 @@ } }, "node_modules/typechain/node_modules/brace-expansion": { - "version": "1.1.18", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.18.tgz", - "integrity": "sha512-Edep/X9fGqVNmzKBVsDYIOtD+z1tuezV70LBjdCst9Tqu76lsnvRiZ6oTic1n+/BIwX6QDGAO94PN4N2SADvtw==", + "version": "1.1.21", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.21.tgz", + "integrity": "sha512-9zeA+KLZNNzglF2TPKRQEDyx6Yby7daAkuy8MiPzpXPsYDWi/DRM8jmwUDxokQjYqBpv5DgPiwD4h4ZZSy1Ujw==", "dev": true, "license": "MIT", "peer": true, diff --git a/package.json b/package.json index 2b94dbc6..cc3b3b4f 100644 --- a/package.json +++ b/package.json @@ -2,10 +2,10 @@ "scripts": { "test:hardhat": "npx hardhat test test/hardhat/RuleEngine.smoke.js", "uml": "mkdir -p docOut/uml && npx sol2uml class src -o docOut/uml/uml_src.svg", - "uml:ruleEngine": "mkdir -p docOut/uml && npx sol2uml class src/deployment/RuleEngine.sol -o docOut/uml/uml_RuleEngine.svg", + "uml:ruleEngine": "mkdir -p docOut/uml && npx sol2uml class src/deployment/accessControl/RuleEngine.sol -o docOut/uml/uml_RuleEngine.svg", "uml:test": "mkdir -p docOut/uml && npx sol2uml class test -o docOut/uml/uml_test.svg", - "surya:report": "mkdir -p docOut/npm && npx surya mdreport docOut/npm/surya_report_ruleEngine.md src/deployment/RuleEngine.sol", - "surya:graph": "mkdir -p docOut/npm && npx surya graph src/deployment/RuleEngine.sol | dot -Tpng > docOut/npm/surya_graph_RuleEngine.png" + "surya:report": "mkdir -p docOut/npm && npx surya mdreport docOut/npm/surya_report_ruleEngine.md src/deployment/accessControl/RuleEngine.sol", + "surya:graph": "mkdir -p docOut/npm && npx surya graph src/deployment/accessControl/RuleEngine.sol | dot -Tpng > docOut/npm/surya_graph_RuleEngine.png" }, "devDependencies": { "@nomicfoundation/hardhat-foundry": "^1.2.1", diff --git a/script/CMTATWithRuleEngineScript.s.sol b/script/CMTATWithRuleEngineScript.s.sol index 93bc7c75..bda0ab26 100644 --- a/script/CMTATWithRuleEngineScript.s.sol +++ b/script/CMTATWithRuleEngineScript.s.sol @@ -2,13 +2,13 @@ // Documentation : // https://book.getfoundry.sh/tutorials/solidity-scripting -pragma solidity ^0.8.20; +pragma solidity ^0.8.27; import {Script, console} from "forge-std/Script.sol"; import {ICMTATConstructor, CMTATStandardStandalone} from "CMTAT/deployment/CMTATStandardStandalone.sol"; import {IERC1643CMTAT} from "CMTAT/interfaces/tokenization/draft-IERC1643CMTAT.sol"; import {IRuleEngine} from "CMTAT/interfaces/engine/IRuleEngine.sol"; -import {RuleEngine} from "../src/deployment/RuleEngine.sol"; +import {RuleEngine} from "../src/deployment/accessControl/RuleEngine.sol"; import {RuleWhitelistMock} from "../src/mocks/rules/validation/RuleWhitelistMock.sol"; /** @@ -48,7 +48,7 @@ contract CMTATWithRuleEngineScript is Script { RuleWhitelistMock ruleWhitelist = new RuleWhitelistMock(admin, trustedForwarder); console.log("whitelist: ", address(ruleWhitelist)); // ruleEngine - RuleEngine ruleEngine = new RuleEngine(admin, trustedForwarder, address(cmtatContract)); + RuleEngine ruleEngine = new RuleEngine(admin, address(cmtatContract)); console.log("RuleEngine : ", address(ruleEngine)); ruleEngine.addRule(ruleWhitelist); cmtatContract.setRuleEngine(ruleEngine); diff --git a/script/RuleEngineScript.s.sol b/script/RuleEngineScript.s.sol index 17cec897..2acccc8d 100644 --- a/script/RuleEngineScript.s.sol +++ b/script/RuleEngineScript.s.sol @@ -2,10 +2,10 @@ // Documentation : // https://book.getfoundry.sh/tutorials/solidity-scripting -pragma solidity ^0.8.20; +pragma solidity ^0.8.27; import {Script, console} from "forge-std/Script.sol"; -import {RuleEngine} from "../src/deployment/RuleEngine.sol"; +import {RuleEngine} from "../src/deployment/accessControl/RuleEngine.sol"; import {RuleWhitelistMock} from "../src/mocks/rules/validation/RuleWhitelistMock.sol"; import {IRuleEngine} from "CMTAT/interfaces/engine/IRuleEngine.sol"; import { @@ -49,7 +49,7 @@ contract RuleEngineScript is Script { listed[1] = address(0); ruleWhitelist.addAddressesToTheList(listed); // ruleEngine, bound to the CMTAT token - RuleEngine ruleEngine = new RuleEngine(admin, address(0), cmtatAddress); + RuleEngine ruleEngine = new RuleEngine(admin, cmtatAddress); console.log("RuleEngine: ", address(ruleEngine)); ruleEngine.addRule(ruleWhitelist); // Configure the new ruleEngine for CMTAT. diff --git a/src/RuleEngineBase.sol b/src/RuleEngineBase.sol index bbf9be81..39fa416e 100644 --- a/src/RuleEngineBase.sol +++ b/src/RuleEngineBase.sol @@ -1,9 +1,10 @@ // SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.20; +pragma solidity ^0.8.27; /* ==== OpenZeppelin === */ import {ERC165Checker} from "@openzeppelin/contracts/utils/introspection/ERC165Checker.sol"; +import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; /* ==== CMTAT interface IDs === */ import {ERC1404ExtendInterfaceId} from "CMTAT/library/ERC1404ExtendInterfaceId.sol"; import {RuleEngineInterfaceId} from "CMTAT/library/RuleEngineInterfaceId.sol"; @@ -36,6 +37,8 @@ abstract contract RuleEngineBase is RuleEngineInvariantStorage, IRuleEngineERC1404 { + using EnumerableSet for EnumerableSet.AddressSet; + /* ============ State variables ============ */ /** * @dev ERC-1404 reserves the code 0 as the "no restriction" sentinel. It is never claimed by a rule, @@ -56,7 +59,7 @@ abstract contract RuleEngineBase is override(IRuleEngine) onlyBoundToken { - // Apply on RuleEngine + // Every rule is applied; the first one that rejects the operation reverts it RulesManagementModule._transferred(spender, from, to, value); } @@ -84,11 +87,11 @@ abstract contract RuleEngineBase is /* ============ View functions ============ */ /** - * @notice Go through all the rule to know if a restriction exists on the transfer + * @notice Queries every rule, in order, and returns the first restriction code that is not zero * @param from the origin address * @param to the destination address * @param value to transfer - * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK (0) if the transfer is valid + * @return The restriction code or REJECTED_CODE_BASE.TRANSFER_OK (0) if the transfer is valid * */ function detectTransferRestriction(address from, address to, uint256 value) @@ -164,9 +167,9 @@ abstract contract RuleEngineBase is * @return The first non-zero ERC-1404 restriction code, or TRANSFER_OK when every rule allows it. */ function _detectTransferRestriction(address from, address to, uint256 value) internal view virtual returns (uint8) { - uint256 rulesLength = rulesCount(); + uint256 rulesLength = _rules.length(); for (uint256 i = 0; i < rulesLength; ++i) { - uint8 restriction = IRule(rule(i)).detectTransferRestriction(from, to, value); + uint8 restriction = IRule(_rules.pos(i)).detectTransferRestriction(from, to, value); if (restriction > 0) { return restriction; } @@ -188,9 +191,9 @@ abstract contract RuleEngineBase is virtual returns (uint8) { - uint256 rulesLength = rulesCount(); + uint256 rulesLength = _rules.length(); for (uint256 i = 0; i < rulesLength; ++i) { - uint8 restriction = IRule(rule(i)).detectTransferRestrictionFrom(spender, from, to, value); + uint8 restriction = IRule(_rules.pos(i)).detectTransferRestrictionFrom(spender, from, to, value); if (restriction > 0) { return restriction; } @@ -212,24 +215,53 @@ abstract contract RuleEngineBase is if (restrictionCode == uint8(REJECTED_CODE_BASE.TRANSFER_OK)) { return TEXT_TRANSFER_OK; } - uint256 rulesLength = rulesCount(); + uint256 rulesLength = _rules.length(); for (uint256 i = 0; i < rulesLength; ++i) { - if (IRule(rule(i)).canReturnTransferRestrictionCode(restrictionCode)) { - return IRule(rule(i)).messageForTransferRestriction(restrictionCode); + IRule rule_ = IRule(_rules.pos(i)); + if (rule_.canReturnTransferRestrictionCode(restrictionCode)) { + return rule_.messageForTransferRestriction(restrictionCode); } } return TEXT_CODE_NOT_FOUND; } /** - * @dev Override to add ERC-165 interface check for the full IRule hierarchy. + * @dev Override to add the ERC-165 interface check, see {_supportsRuleInterface}, and to reject a bound + * token: an address may be a rule or a bound token, never both (see {_checkBindingTarget}). * @param rule_ The candidate rule address to validate. */ function _checkRule(address rule_) internal view virtual override { RulesManagementModule._checkRule(rule_); - if (!ERC165Checker.supportsInterface(rule_, RuleInterfaceId.IRULE_INTERFACE_ID)) { - revert RuleEngine_RuleInvalidInterface(); + require(!_boundTokens.contains(rule_), RuleEngine_RulesManagementModule_RuleAccountCannotReceivePrivileges()); + require(_supportsRuleInterface(rule_), RuleEngine_RuleInvalidInterface()); + } + + /** + * @dev Rejects binding an address that is currently a rule. Binding lets an address drive every rule, so a + * rule that was also a bound token could call the engine's callbacks from inside its own `transferred` hook. + * Together with the bound-token check in {_checkRule}, the rule set and the bound tokens stay disjoint. + * @param token The address about to be bound. + */ + function _checkBindingTarget(address token) internal view virtual override { + require(!_rules.contains(token), RuleEngine_RulesManagementModule_RuleAccountCannotReceivePrivileges()); + } + + /** + * @dev Tells whether `rule_` advertises a rule interface the engine can use: the current + * {RuleInterfaceId-IRULE_INTERFACE_ID} or the legacy {RuleInterfaceId-IRULE_LEGACY_INTERFACE_ID}. + * The legacy interface (up to v3.0.0-rc6) is a superset of the current one, adding `canTransfer` and + * `canTransferFrom`, which the engine never calls, so a rule built against it remains usable. + * ERC-165 support itself is checked once, then each ID with a single call; the legacy ID is only + * queried when the current one is not advertised. + * @param rule_ The candidate rule address. + * @return True if the rule advertises the current or the legacy rule interface. + */ + function _supportsRuleInterface(address rule_) internal view virtual returns (bool) { + if (!ERC165Checker.supportsERC165(rule_)) { + return false; } + return ERC165Checker.supportsERC165InterfaceUnchecked(rule_, RuleInterfaceId.IRULE_INTERFACE_ID) + || ERC165Checker.supportsERC165InterfaceUnchecked(rule_, RuleInterfaceId.IRULE_LEGACY_INTERFACE_ID); } /** diff --git a/src/RuleEngineOwnableShared.sol b/src/RuleEngineOwnableShared.sol index c29f35b1..4f315332 100644 --- a/src/RuleEngineOwnableShared.sol +++ b/src/RuleEngineOwnableShared.sol @@ -1,13 +1,10 @@ // SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.20; +pragma solidity ^0.8.27; /* ==== OpenZeppelin === */ -import {Context} from "@openzeppelin/contracts/utils/Context.sol"; import {ERC165} from "@openzeppelin/contracts/utils/introspection/ERC165.sol"; import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; -/* ==== Modules === */ -import {ERC2771ModuleStandalone, ERC2771Context} from "./modules/ERC2771ModuleStandalone.sol"; /* ==== Base contract === */ import {RuleEngineBase} from "./RuleEngineBase.sol"; import {OwnableInterfaceId} from "./modules/library/OwnableInterfaceId.sol"; @@ -16,15 +13,15 @@ import {IRule} from "./interfaces/IRule.sol"; /** * @title Shared Ownable deployment logic for RuleEngine variants * @dev Kept abstract to let child contracts choose the ownership mechanism - * (`Ownable` or `Ownable2Step`) while reusing constructor, ERC-165 and ERC-2771 code. + * (`Ownable` or `Ownable2Step`) while reusing constructor and ERC-165 code. Free of ERC-2771: + * the `*2771` deployables add the trusted forwarder on top of the ownable deployables. */ -abstract contract RuleEngineOwnableShared is ERC2771ModuleStandalone, RuleEngineBase, ERC165 { +abstract contract RuleEngineOwnableShared is RuleEngineBase, ERC165 { /** - * @notice Sets the trusted forwarder and optionally binds an initial token. - * @param forwarderIrrevocable Address of the trusted ERC-2771 forwarder, immutable after construction. + * @notice Optionally binds an initial token and emits the initial rule cap. * @param tokenContract Token to bind at deployment, or the zero address to bind none. */ - constructor(address forwarderIrrevocable, address tokenContract) ERC2771ModuleStandalone(forwarderIrrevocable) { + constructor(address tokenContract) { if (tokenContract != address(0)) { _bindToken(tokenContract); } @@ -48,36 +45,6 @@ abstract contract RuleEngineOwnableShared is ERC2771ModuleStandalone, RuleEngine * @param newOwner The candidate new owner; must not be a configured rule. */ function _checkOwnershipTransferTarget(address newOwner) internal view virtual { - if (containsRule(IRule(newOwner))) { - revert RuleEngine_RulesManagementModule_RuleAccountCannotReceivePrivileges(); - } - } - - /*////////////////////////////////////////////////////////////// - ERC-2771 - //////////////////////////////////////////////////////////////*/ - - /** - * @dev This surcharge is not necessary if you do not use the MetaTxModule - * @return sender The transaction sender, unwrapped from the forwarder calldata when relayed. - */ - function _msgSender() internal view virtual override(ERC2771Context, Context) returns (address sender) { - return ERC2771Context._msgSender(); - } - - /** - * @dev This surcharge is not necessary if you do not use the MetaTxModule - * @return The transaction calldata, with the appended sender stripped when relayed. - */ - function _msgData() internal view virtual override(ERC2771Context, Context) returns (bytes calldata) { - return ERC2771Context._msgData(); - } - - /** - * @dev This surcharge is not necessary if you do not use the MetaTxModule - * @return The length of the ERC-2771 calldata suffix. - */ - function _contextSuffixLength() internal view virtual override(ERC2771Context, Context) returns (uint256) { - return ERC2771Context._contextSuffixLength(); + require(!containsRule(IRule(newOwner)), RuleEngine_RulesManagementModule_RuleAccountCannotReceivePrivileges()); } } diff --git a/src/deployment/RuleEngineOwnable.sol b/src/deployment/RuleEngineOwnable.sol deleted file mode 100644 index e81ac60e..00000000 --- a/src/deployment/RuleEngineOwnable.sol +++ /dev/null @@ -1,72 +0,0 @@ -// SPDX-License-Identifier: MPL-2.0 - -pragma solidity ^0.8.20; - -import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; -import {Context} from "@openzeppelin/contracts/utils/Context.sol"; -import {RuleEngineOwnableShared} from "../RuleEngineOwnableShared.sol"; - -/** - * @title Implementation of a ruleEngine with ERC-173 Ownable access control - */ -contract RuleEngineOwnable is RuleEngineOwnableShared, Ownable { - /** - * @param owner_ Address of the contract owner (ERC-173) - * @param forwarderIrrevocable Address of the forwarder, required for the gasless support - * @param tokenContract Address of the token contract to bind (can be zero address) - */ - constructor(address owner_, address forwarderIrrevocable, address tokenContract) - RuleEngineOwnableShared(forwarderIrrevocable, tokenContract) - Ownable(owner_) - {} - - /** - * @notice Transfers ownership of the contract to a new account (`newOwner`). - * @dev Reverts when `newOwner` is already configured as a rule. - * @param newOwner The address of the new owner. - */ - function transferOwnership(address newOwner) public virtual override onlyOwner { - RuleEngineOwnableShared._checkOwnershipTransferTarget(newOwner); - Ownable.transferOwnership(newOwner); - } - - /* ============ ACCESS CONTROL ============ */ - /** - * @dev Access control check using Ownable pattern - */ - function _onlyRulesManager() internal virtual override onlyOwner {} - - /** - * @dev Access control check using Ownable pattern - */ - function _onlyRulesLimitManager() internal virtual override onlyOwner {} - - /** - * @dev Access control check using Ownable pattern - */ - function _onlyComplianceManager() internal virtual override onlyOwner {} - - /** - * @dev This surcharge is not necessary if you do not use the MetaTxModule - * @return sender The transaction sender, unwrapped from the forwarder calldata when relayed. - */ - function _msgSender() internal view virtual override(RuleEngineOwnableShared, Context) returns (address sender) { - return RuleEngineOwnableShared._msgSender(); - } - - /** - * @dev This surcharge is not necessary if you do not use the MetaTxModule - * @return The transaction calldata, with the appended sender stripped when relayed. - */ - function _msgData() internal view virtual override(RuleEngineOwnableShared, Context) returns (bytes calldata) { - return RuleEngineOwnableShared._msgData(); - } - - /** - * @dev This surcharge is not necessary if you do not use the MetaTxModule - * @return The length of the ERC-2771 calldata suffix. - */ - function _contextSuffixLength() internal view virtual override(RuleEngineOwnableShared, Context) returns (uint256) { - return RuleEngineOwnableShared._contextSuffixLength(); - } -} diff --git a/src/deployment/RuleEngine.sol b/src/deployment/accessControl/RuleEngine.sol similarity index 65% rename from src/deployment/RuleEngine.sol rename to src/deployment/accessControl/RuleEngine.sol index bcaf7d5a..3722a0bb 100644 --- a/src/deployment/RuleEngine.sol +++ b/src/deployment/accessControl/RuleEngine.sol @@ -1,26 +1,25 @@ // SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.20; +pragma solidity ^0.8.27; /* ==== OpenZeppelin === */ -import {Context} from "@openzeppelin/contracts/utils/Context.sol"; import {IAccessControl} from "@openzeppelin/contracts/access/IAccessControl.sol"; import {AccessControl} from "@openzeppelin/contracts/access/AccessControl.sol"; import {AccessControlEnumerable} from "@openzeppelin/contracts/access/extensions/AccessControlEnumerable.sol"; import {IERC165} from "@openzeppelin/contracts/utils/introspection/ERC165.sol"; import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; /* ==== Modules === */ -import {ERC2771ModuleStandalone, ERC2771Context} from "../modules/ERC2771ModuleStandalone.sol"; -import {ERC3643ComplianceRolesStorage} from "../modules/library/ERC3643ComplianceRolesStorage.sol"; -import {RulesManagementModuleRolesStorage} from "../modules/library/RulesManagementModuleRolesStorage.sol"; +import {ERC3643ComplianceRolesStorage} from "../../modules/library/ERC3643ComplianceRolesStorage.sol"; +import {RulesManagementModuleRolesStorage} from "../../modules/library/RulesManagementModuleRolesStorage.sol"; /* ==== Base contract === */ -import {RuleEngineBase} from "../RuleEngineBase.sol"; +import {RuleEngineBase} from "../../RuleEngineBase.sol"; /** - * @title Implementation of a ruleEngine as defined by the CMTAT + * @title Implementation of a ruleEngine as defined by the CMTAT, with RBAC access control + * @dev No ERC-2771 support: every caller is the raw `msg.sender`. Deploy {RuleEngine2771}, which + * extends this contract, to administer the engine through a trusted forwarder (gasless transactions). */ contract RuleEngine is - ERC2771ModuleStandalone, RuleEngineBase, AccessControlEnumerable, ERC3643ComplianceRolesStorage, @@ -29,17 +28,12 @@ contract RuleEngine is using EnumerableSet for EnumerableSet.AddressSet; /** - * @notice Deploys the RBAC RuleEngine. - * @param admin Address of the contract (Access Control) - * @param forwarderIrrevocable Address of the forwarder, required for the gasless support + * @notice Deploys the RBAC RuleEngine, grants the admin role and optionally binds an initial token. + * @param admin Address receiving `DEFAULT_ADMIN_ROLE`; must not be the zero address. * @param tokenContract Token to bind at deployment, or the zero address to bind none. */ - constructor(address admin, address forwarderIrrevocable, address tokenContract) - ERC2771ModuleStandalone(forwarderIrrevocable) - { - if (admin == address(0)) { - revert RuleEngine_AdminWithAddressZeroNotAllowed(); - } + constructor(address admin, address tokenContract) { + require(admin != address(0), RuleEngine_AdminWithAddressZeroNotAllowed()); if (tokenContract != address(0)) { _bindToken(tokenContract); } @@ -60,9 +54,7 @@ contract RuleEngine is * @param account The account receiving the role. */ function grantRole(bytes32 role, address account) public virtual override(AccessControl, IAccessControl) { - if (_rules.contains(account)) { - revert RuleEngine_RulesManagementModule_RuleAccountCannotReceivePrivileges(); - } + require(!_rules.contains(account), RuleEngine_RulesManagementModule_RuleAccountCannotReceivePrivileges()); AccessControl.grantRole(role, account); } @@ -104,7 +96,7 @@ contract RuleEngine is } /*////////////////////////////////////////////////////////////// - ERC-2771 + ACCESS CONTROL HOOKS //////////////////////////////////////////////////////////////*/ /** * @dev Access control check restricting compliance operations to COMPLIANCE_MANAGER_ROLE. @@ -120,28 +112,4 @@ contract RuleEngine is * @dev Access control check restricting the rule cap update to DEFAULT_ADMIN_ROLE. */ function _onlyRulesLimitManager() internal virtual override onlyRole(DEFAULT_ADMIN_ROLE) {} - - /** - * @dev This surcharge is not necessary if you do not use the MetaTxModule - * @return sender The transaction sender, unwrapped from the forwarder calldata when relayed. - */ - function _msgSender() internal view virtual override(ERC2771Context, Context) returns (address sender) { - return ERC2771Context._msgSender(); - } - - /** - * @dev This surcharge is not necessary if you do not use the MetaTxModule - * @return The transaction calldata, with the appended sender stripped when relayed. - */ - function _msgData() internal view virtual override(ERC2771Context, Context) returns (bytes calldata) { - return ERC2771Context._msgData(); - } - - /** - * @dev This surcharge is not necessary if you do not use the MetaTxModule - * @return The length of the ERC-2771 calldata suffix. - */ - function _contextSuffixLength() internal view virtual override(ERC2771Context, Context) returns (uint256) { - return ERC2771Context._contextSuffixLength(); - } } diff --git a/src/deployment/accessControl/RuleEngine2771.sol b/src/deployment/accessControl/RuleEngine2771.sol new file mode 100644 index 00000000..a9a69f97 --- /dev/null +++ b/src/deployment/accessControl/RuleEngine2771.sol @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: MPL-2.0 + +pragma solidity ^0.8.27; + +/* ==== OpenZeppelin === */ +import {Context} from "@openzeppelin/contracts/utils/Context.sol"; +/* ==== Modules === */ +import {ERC2771ModuleStandalone, ERC2771Context} from "../../modules/ERC2771ModuleStandalone.sol"; +/* ==== Base contract === */ +import {RuleEngine} from "./RuleEngine.sol"; + +/** + * @title Implementation of a ruleEngine as defined by the CMTAT, with RBAC access control and ERC-2771 + * @dev Administrative calls may be relayed by the immutable trusted forwarder (gasless transactions). + * Token identity is never resolved through the forwarder: the bound-token gate and token self-binding + * compare the raw `msg.sender`. + */ +contract RuleEngine2771 is ERC2771ModuleStandalone, RuleEngine { + /** + * @notice Deploys the RBAC RuleEngine with a trusted forwarder. + * @param admin Address receiving `DEFAULT_ADMIN_ROLE`; must not be the zero address. + * @param forwarderIrrevocable Address of the trusted ERC-2771 forwarder, immutable after construction. + * @param tokenContract Token to bind at deployment, or the zero address to bind none. + */ + constructor(address admin, address forwarderIrrevocable, address tokenContract) + ERC2771ModuleStandalone(forwarderIrrevocable) + RuleEngine(admin, tokenContract) + {} + + /*////////////////////////////////////////////////////////////// + ERC-2771 + //////////////////////////////////////////////////////////////*/ + /** + * @dev Resolves the sender through ERC-2771 when the call comes from the trusted forwarder. + * @return sender The transaction sender, unwrapped from the forwarder calldata when relayed. + */ + function _msgSender() internal view virtual override(ERC2771Context, Context) returns (address sender) { + return ERC2771Context._msgSender(); + } + + /** + * @dev Resolves the calldata through ERC-2771 when the call comes from the trusted forwarder. + * @return The transaction calldata, with the appended sender stripped when relayed. + */ + function _msgData() internal view virtual override(ERC2771Context, Context) returns (bytes calldata) { + return ERC2771Context._msgData(); + } + + /** + * @dev Length of the sender suffix appended by the trusted forwarder. + * @return The length of the ERC-2771 calldata suffix. + */ + function _contextSuffixLength() internal view virtual override(ERC2771Context, Context) returns (uint256) { + return ERC2771Context._contextSuffixLength(); + } +} diff --git a/src/deployment/ownable/RuleEngineOwnable.sol b/src/deployment/ownable/RuleEngineOwnable.sol new file mode 100644 index 00000000..c212d4ae --- /dev/null +++ b/src/deployment/ownable/RuleEngineOwnable.sol @@ -0,0 +1,46 @@ +// SPDX-License-Identifier: MPL-2.0 + +pragma solidity ^0.8.27; + +import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; +import {RuleEngineOwnableShared} from "../../RuleEngineOwnableShared.sol"; + +/** + * @title Implementation of a ruleEngine with ERC-173 Ownable access control + * @dev No ERC-2771 support: every caller is the raw `msg.sender`. Deploy {RuleEngineOwnable2771} to + * administer the engine through a trusted forwarder (gasless transactions). + */ +contract RuleEngineOwnable is RuleEngineOwnableShared, Ownable { + /** + * @notice Deploys a RuleEngine with ERC-173 ownership, without a trusted forwarder. + * @param owner_ Address of the contract owner (ERC-173) + * @param tokenContract Address of the token contract to bind (can be zero address) + */ + constructor(address owner_, address tokenContract) RuleEngineOwnableShared(tokenContract) Ownable(owner_) {} + + /** + * @notice Transfers ownership of the contract to a new account (`newOwner`). + * @dev Reverts when `newOwner` is already configured as a rule. + * @param newOwner The address of the new owner. + */ + function transferOwnership(address newOwner) public virtual override onlyOwner { + RuleEngineOwnableShared._checkOwnershipTransferTarget(newOwner); + Ownable.transferOwnership(newOwner); + } + + /* ============ ACCESS CONTROL ============ */ + /** + * @dev Access control check using Ownable pattern + */ + function _onlyRulesManager() internal virtual override onlyOwner {} + + /** + * @dev Access control check using Ownable pattern + */ + function _onlyRulesLimitManager() internal virtual override onlyOwner {} + + /** + * @dev Access control check using Ownable pattern + */ + function _onlyComplianceManager() internal virtual override onlyOwner {} +} diff --git a/src/deployment/ownable/RuleEngineOwnable2771.sol b/src/deployment/ownable/RuleEngineOwnable2771.sol new file mode 100644 index 00000000..11b9ca83 --- /dev/null +++ b/src/deployment/ownable/RuleEngineOwnable2771.sol @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: MPL-2.0 + +pragma solidity ^0.8.27; + +/* ==== OpenZeppelin === */ +import {Context} from "@openzeppelin/contracts/utils/Context.sol"; +/* ==== Modules === */ +import {ERC2771ModuleStandalone, ERC2771Context} from "../../modules/ERC2771ModuleStandalone.sol"; +/* ==== Base contract === */ +import {RuleEngineOwnable} from "./RuleEngineOwnable.sol"; + +/** + * @title Implementation of a ruleEngine with ERC-173 Ownable access control and ERC-2771 + * @dev {RuleEngineOwnable} plus an immutable trusted forwarder: administrative calls (owner-only functions) may be + * relayed by the forwarder (gasless transactions). Token identity is never resolved through the + * forwarder: the bound-token gate and token self-binding compare the raw `msg.sender`. + */ +contract RuleEngineOwnable2771 is ERC2771ModuleStandalone, RuleEngineOwnable { + /** + * @notice Deploys a RuleEngine with ERC-173 Ownable access control and a trusted forwarder. + * @param owner_ Address of the initial contract owner (ERC-173). + * @param forwarderIrrevocable Address of the trusted ERC-2771 forwarder, immutable after construction. + * @param tokenContract Token to bind at deployment, or the zero address to bind none. + */ + constructor(address owner_, address forwarderIrrevocable, address tokenContract) + ERC2771ModuleStandalone(forwarderIrrevocable) + RuleEngineOwnable(owner_, tokenContract) + {} + + /*////////////////////////////////////////////////////////////// + ERC-2771 + //////////////////////////////////////////////////////////////*/ + /** + * @dev Resolves the sender through ERC-2771 when the call comes from the trusted forwarder. + * @return sender The transaction sender, unwrapped from the forwarder calldata when relayed. + */ + function _msgSender() internal view virtual override(ERC2771Context, Context) returns (address sender) { + return ERC2771Context._msgSender(); + } + + /** + * @dev Resolves the calldata through ERC-2771 when the call comes from the trusted forwarder. + * @return The transaction calldata, with the appended sender stripped when relayed. + */ + function _msgData() internal view virtual override(ERC2771Context, Context) returns (bytes calldata) { + return ERC2771Context._msgData(); + } + + /** + * @dev Length of the sender suffix appended by the trusted forwarder. + * @return The length of the ERC-2771 calldata suffix. + */ + function _contextSuffixLength() internal view virtual override(ERC2771Context, Context) returns (uint256) { + return ERC2771Context._contextSuffixLength(); + } +} diff --git a/src/deployment/RuleEngineOwnable2Step.sol b/src/deployment/ownable/RuleEngineOwnable2Step.sol similarity index 56% rename from src/deployment/RuleEngineOwnable2Step.sol rename to src/deployment/ownable/RuleEngineOwnable2Step.sol index d334ec21..a8b9e825 100644 --- a/src/deployment/RuleEngineOwnable2Step.sol +++ b/src/deployment/ownable/RuleEngineOwnable2Step.sol @@ -1,28 +1,25 @@ // SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.20; +pragma solidity ^0.8.27; /* ==== OpenZeppelin === */ import {Ownable2Step} from "@openzeppelin/contracts/access/Ownable2Step.sol"; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; -import {Context} from "@openzeppelin/contracts/utils/Context.sol"; -import {RuleEngineOwnableShared} from "../RuleEngineOwnableShared.sol"; -import {Ownable2StepInterfaceId} from "../modules/library/Ownable2StepInterfaceId.sol"; +import {RuleEngineOwnableShared} from "../../RuleEngineOwnableShared.sol"; +import {Ownable2StepInterfaceId} from "../../modules/library/Ownable2StepInterfaceId.sol"; /** * @title Implementation of a ruleEngine with ERC-173 Ownable2Step access control + * @dev No ERC-2771 support: every caller is the raw `msg.sender`. Deploy {RuleEngineOwnable2Step2771} to + * administer the engine through a trusted forwarder (gasless transactions). */ contract RuleEngineOwnable2Step is RuleEngineOwnableShared, Ownable2Step { /** - * @notice Deploys a RuleEngine with ERC-173 two-step ownership transfer. + * @notice Deploys a RuleEngine with ERC-173 two-step ownership transfer, without a trusted forwarder. * @param owner_ Address of the initial contract owner (ERC-173). - * @param forwarderIrrevocable Address of the ERC-2771 trusted forwarder (use zero address to disable gasless). * @param tokenContract Address of the token contract to bind at deployment (use zero address to skip). */ - constructor(address owner_, address forwarderIrrevocable, address tokenContract) - RuleEngineOwnableShared(forwarderIrrevocable, tokenContract) - Ownable(owner_) - {} + constructor(address owner_, address tokenContract) RuleEngineOwnableShared(tokenContract) Ownable(owner_) {} /** * @notice Starts ownership transfer to `newOwner`. @@ -34,6 +31,16 @@ contract RuleEngineOwnable2Step is RuleEngineOwnableShared, Ownable2Step { Ownable2Step.transferOwnership(newOwner); } + /** + * @notice Completes the ownership transfer; callable by the pending owner only. + * @dev Repeats the rule-account check of {transferOwnership}: an address nominated while it was not a rule, + * then added as a rule, cannot accept until it is removed from the rule set. + */ + function acceptOwnership() public virtual override { + RuleEngineOwnableShared._checkOwnershipTransferTarget(_msgSender()); + Ownable2Step.acceptOwnership(); + } + /* ============ ERC-165 ============ */ /** * @notice ERC-165 interface detection. @@ -66,28 +73,4 @@ contract RuleEngineOwnable2Step is RuleEngineOwnableShared, Ownable2Step { * @dev Access control check using Ownable pattern */ function _onlyComplianceManager() internal virtual override onlyOwner {} - - /** - * @dev This surcharge is not necessary if you do not use the MetaTxModule - * @return sender The transaction sender, unwrapped from the forwarder calldata when relayed. - */ - function _msgSender() internal view virtual override(RuleEngineOwnableShared, Context) returns (address sender) { - return RuleEngineOwnableShared._msgSender(); - } - - /** - * @dev This surcharge is not necessary if you do not use the MetaTxModule - * @return The transaction calldata, with the appended sender stripped when relayed. - */ - function _msgData() internal view virtual override(RuleEngineOwnableShared, Context) returns (bytes calldata) { - return RuleEngineOwnableShared._msgData(); - } - - /** - * @dev This surcharge is not necessary if you do not use the MetaTxModule - * @return The length of the ERC-2771 calldata suffix. - */ - function _contextSuffixLength() internal view virtual override(RuleEngineOwnableShared, Context) returns (uint256) { - return RuleEngineOwnableShared._contextSuffixLength(); - } } diff --git a/src/deployment/ownable/RuleEngineOwnable2Step2771.sol b/src/deployment/ownable/RuleEngineOwnable2Step2771.sol new file mode 100644 index 00000000..7bc77038 --- /dev/null +++ b/src/deployment/ownable/RuleEngineOwnable2Step2771.sol @@ -0,0 +1,56 @@ +// SPDX-License-Identifier: MPL-2.0 + +pragma solidity ^0.8.27; + +/* ==== OpenZeppelin === */ +import {Context} from "@openzeppelin/contracts/utils/Context.sol"; +/* ==== Modules === */ +import {ERC2771ModuleStandalone, ERC2771Context} from "../../modules/ERC2771ModuleStandalone.sol"; +/* ==== Base contract === */ +import {RuleEngineOwnable2Step} from "./RuleEngineOwnable2Step.sol"; + +/** + * @title Implementation of a ruleEngine with ERC-173 Ownable2Step access control and ERC-2771 + * @dev {RuleEngineOwnable2Step} plus an immutable trusted forwarder: administrative calls (owner-only functions) may be + * relayed by the forwarder (gasless transactions). Token identity is never resolved through the + * forwarder: the bound-token gate and token self-binding compare the raw `msg.sender`. + */ +contract RuleEngineOwnable2Step2771 is ERC2771ModuleStandalone, RuleEngineOwnable2Step { + /** + * @notice Deploys a RuleEngine with ERC-173 Ownable2Step access control and a trusted forwarder. + * @param owner_ Address of the initial contract owner (ERC-173). + * @param forwarderIrrevocable Address of the trusted ERC-2771 forwarder, immutable after construction. + * @param tokenContract Token to bind at deployment, or the zero address to bind none. + */ + constructor(address owner_, address forwarderIrrevocable, address tokenContract) + ERC2771ModuleStandalone(forwarderIrrevocable) + RuleEngineOwnable2Step(owner_, tokenContract) + {} + + /*////////////////////////////////////////////////////////////// + ERC-2771 + //////////////////////////////////////////////////////////////*/ + /** + * @dev Resolves the sender through ERC-2771 when the call comes from the trusted forwarder. + * @return sender The transaction sender, unwrapped from the forwarder calldata when relayed. + */ + function _msgSender() internal view virtual override(ERC2771Context, Context) returns (address sender) { + return ERC2771Context._msgSender(); + } + + /** + * @dev Resolves the calldata through ERC-2771 when the call comes from the trusted forwarder. + * @return The transaction calldata, with the appended sender stripped when relayed. + */ + function _msgData() internal view virtual override(ERC2771Context, Context) returns (bytes calldata) { + return ERC2771Context._msgData(); + } + + /** + * @dev Length of the sender suffix appended by the trusted forwarder. + * @return The length of the ERC-2771 calldata suffix. + */ + function _contextSuffixLength() internal view virtual override(ERC2771Context, Context) returns (uint256) { + return ERC2771Context._contextSuffixLength(); + } +} diff --git a/src/interfaces/IERC3643Compliance.sol b/src/interfaces/IERC3643Compliance.sol index 2f698d07..8475052b 100644 --- a/src/interfaces/IERC3643Compliance.sol +++ b/src/interfaces/IERC3643Compliance.sol @@ -1,6 +1,6 @@ //SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.20; +pragma solidity ^0.8.27; /* ==== CMTAT === */ import {IERC3643ComplianceRead, IERC3643IComplianceContract} from "CMTAT/interfaces/tokenization/IERC3643Partial.sol"; diff --git a/src/interfaces/IERC3643ComplianceExtended.sol b/src/interfaces/IERC3643ComplianceExtended.sol index 74bf25a2..b483adcc 100644 --- a/src/interfaces/IERC3643ComplianceExtended.sol +++ b/src/interfaces/IERC3643ComplianceExtended.sol @@ -1,6 +1,6 @@ //SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.20; +pragma solidity ^0.8.27; import {IERC3643Compliance} from "./IERC3643Compliance.sol"; import {ITokenBindingExtended} from "./ITokenBindingExtended.sol"; diff --git a/src/interfaces/IRule.sol b/src/interfaces/IRule.sol index 647da17a..6c3d7279 100644 --- a/src/interfaces/IRule.sol +++ b/src/interfaces/IRule.sol @@ -1,17 +1,43 @@ //SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.20; +pragma solidity ^0.8.27; +/* ==== OpenZeppelin === */ +import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; /* ==== CMTAT === */ -import {IRuleEngineERC1404} from "CMTAT/interfaces/engine/IRuleEngine.sol"; - -/* ==== Interfaces === */ +import {IERC1404Extend} from "CMTAT/interfaces/tokenization/draft-IERC1404.sol"; +import {IERC3643IComplianceContract} from "CMTAT/interfaces/tokenization/IERC3643Partial.sol"; /** * @title IRule * @notice Interface every rule must implement to be usable by a RuleEngine. + * @dev Declares exactly the functions the engine calls on a rule, plus ERC-165: + * - `transferred(from, to, value)` from {IERC3643IComplianceContract} and the 4-argument + * `transferred(spender, from, to, value)` declared below (state-changing callbacks); + * - `detectTransferRestriction` and `messageForTransferRestriction` from {IERC1404}, and + * `detectTransferRestrictionFrom` from {IERC1404Extend} (views); + * - `canReturnTransferRestrictionCode`, declared below. + * + * It does not require `canTransfer` / `canTransferFrom` (ERC-3643 / ERC-7551 compliance reads): the engine + * never calls them on a rule, it derives its own answer from `detectTransferRestriction*`. A rule that + * also wants to be set directly as a token's rule engine (no RuleEngine in between) implements CMTAT's + * `IRuleEngineERC1404` as well and advertises `RULE_ENGINE_INTERFACE_ID`; that role is opt-in per rule. */ -interface IRule is IRuleEngineERC1404 { +interface IRule is IERC1404Extend, IERC3643IComplianceContract, IERC165 { + /** + * @notice Applies the rule to an operation that carries a spender: `transferFrom`, and since CMTAT + * v3.3.0 mint, burn and the minter `batchTransfer`, with the operator as `spender`. + * @dev Must revert if the operation is not allowed. Same function as CMTAT's + * `IRuleEngine.transferred(spender, from, to, value)`, declared here so that `IRule` does not inherit + * the compliance reads of `IRuleEngine`. A zero `value` carries no economic meaning: a stateful rule + * must treat it as a no-op (see the warning in CMTAT's `IRuleEngine`). + * @param spender The account that initiated the operation. + * @param from The origin address, zero on a mint. + * @param to The destination address, zero on a burn. + * @param value The number of tokens involved. + */ + function transferred(address spender, address from, address to, uint256 value) external; + /** * @notice Tells whether a restriction code belongs to this rule. * @dev Returns true if the restriction code exists, and false otherwise. diff --git a/src/interfaces/IRulesManagementModule.sol b/src/interfaces/IRulesManagementModule.sol index 4c6866b9..366a5f33 100644 --- a/src/interfaces/IRulesManagementModule.sol +++ b/src/interfaces/IRulesManagementModule.sol @@ -1,6 +1,6 @@ //SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.20; +pragma solidity ^0.8.27; /* ==== Interfaces === */ import {IRule} from "./IRule.sol"; diff --git a/src/interfaces/ITokenBinding.sol b/src/interfaces/ITokenBinding.sol index 760f5e18..76fcc09b 100644 --- a/src/interfaces/ITokenBinding.sol +++ b/src/interfaces/ITokenBinding.sol @@ -1,6 +1,6 @@ //SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.20; +pragma solidity ^0.8.27; /** * @title ITokenBinding @@ -15,12 +15,17 @@ interface ITokenBinding { /* ============ Events ============ */ /** * @notice Emitted when a token is successfully bound. + * @dev Same declaration as ERC-3643 `TokenBound(address _token)`, which does not index the token. Keep it + * non-indexed: `indexed` would move `token` from the data to a topic and break consumers decoding with + * the standard ERC-3643 ABI. * @param token The address of the token that was bound. */ event TokenBound(address token); /** * @notice Emitted when a token is successfully unbound. + * @dev Same declaration as ERC-3643 `TokenUnbound(address _token)`; kept non-indexed for the same reason as + * {TokenBound}. * @param token The address of the token that was unbound. */ event TokenUnbound(address token); @@ -35,6 +40,9 @@ interface ITokenBinding { * when all bound tokens are equally trusted and governed together, since the * bound-token entry points do not necessarily carry the calling token address to the * downstream logic. + * Trust note: a bound address can drive every stateful downstream check without moving any + * token, and the registry cannot tell a token contract from an EOA or another contract. Bind only + * the token contracts the host is meant to serve. * Complexity: O(1). * @param token The address of the token to bind. */ diff --git a/src/interfaces/ITokenBindingExtended.sol b/src/interfaces/ITokenBindingExtended.sol index eadfab7f..00706700 100644 --- a/src/interfaces/ITokenBindingExtended.sol +++ b/src/interfaces/ITokenBindingExtended.sol @@ -1,6 +1,6 @@ //SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.20; +pragma solidity ^0.8.27; import {ITokenBinding} from "./ITokenBinding.sol"; @@ -14,15 +14,24 @@ import {ITokenBinding} from "./ITokenBinding.sol"; interface ITokenBindingExtended is ITokenBinding { /* ============ Events ============ */ /** - * @notice Emitted when self-binding permission is updated for a token. - * @param token The token address whose self-binding permission changed. + * @notice Emitted by {setTokenSelfBindingApproval} when self-binding permission is set for a token. + * @dev Emitted on every call, also when `approved` equals the current value. Not emitted by + * {setTokenSelfBindingApprovalBatch}, which emits {TokenSelfBindingApprovalBatchSet} instead: a consumer + * reconstructing the approvals, or filtering on `token`, must handle both events, or read + * {isTokenSelfBindingApproved}, which is authoritative. + * @param token The token address whose self-binding permission was set. * @param approved True if token self-bind/unbind is allowed, false otherwise. */ event TokenSelfBindingApprovalSet(address indexed token, bool approved); /** - * @notice Emitted when self-binding permission is updated in batch. - * @param tokens The token addresses whose self-binding permission changed. + * @notice Emitted once by {setTokenSelfBindingApprovalBatch}, with the input array. + * @dev `tokens` is the array as passed: it may contain tokens already at `approved` and duplicates, and is + * empty for an empty batch, so it lists the tokens that were set, not only those that changed. No + * {TokenSelfBindingApprovalSet} is emitted per token, so a filter on that event's indexed `token` does not + * see batch updates. `tokens` is not indexed: an indexed array is stored as a hash and cannot be filtered + * per token. + * @param tokens The token addresses whose self-binding permission was set, as passed to the call. * @param approved True if token self-bind/unbind is allowed, false otherwise. */ event TokenSelfBindingApprovalBatchSet(address[] tokens, bool approved); @@ -31,7 +40,10 @@ interface ITokenBindingExtended is ITokenBinding { /** * @notice Binds several token contracts in a single call. * @dev Must be restricted by implementation-specific access control. - * Reverts if any token is invalid or already bound. + * Atomic: reverts if any token is invalid or already bound (or listed twice), and then binds none of them. + * This deliberately departs from the usual batch convention of skipping elements already in the target + * state: a binding change is security-relevant, and a token that is already bound in the list is most + * likely an operator mistake that should stop the whole operation. An empty array is a no-op. * @param tokens The token addresses to bind. */ function bindTokens(address[] calldata tokens) external; @@ -39,7 +51,10 @@ interface ITokenBindingExtended is ITokenBinding { /** * @notice Unbinds several token contracts in a single call. * @dev Must be restricted by implementation-specific access control. - * Reverts if any token is not currently bound. + * Atomic: reverts if any token is not currently bound, and then unbinds none of them. Deliberately not + * the skip-if-already-done batch convention, for the same reason as {bindTokens}. An empty array is a no-op. + * Like a manager's {unbindToken}, revokes each token's self-binding approval (see + * {setTokenSelfBindingApproval}). * @param tokens The token addresses to unbind. */ function unbindTokens(address[] calldata tokens) external; @@ -47,6 +62,9 @@ interface ITokenBindingExtended is ITokenBinding { /** * @notice Sets whether a token is allowed to bind and unbind itself. * @dev Must be restricted by implementation-specific access control. + * An approval stays in force until it is revoked here or until the binding manager unbinds the token + * ({unbindToken} or {unbindTokens}), which revokes it and emits {TokenSelfBindingApprovalSet} with `false`. + * A token that unbinds itself keeps its approval, so it can bind itself again later. * @param token The token address to configure. * @param approved Whether self-binding is approved for `token`. */ @@ -55,7 +73,8 @@ interface ITokenBindingExtended is ITokenBinding { /** * @notice Sets self-binding approval for multiple tokens in one transaction. * @dev Must be restricted by implementation-specific access control. - * Reverts if any token in `tokens` is the zero address. + * Reverts if any token in `tokens` is the zero address. Emits a single {TokenSelfBindingApprovalBatchSet} + * with the input array, not one {TokenSelfBindingApprovalSet} per token. * @param tokens The token addresses to configure. * @param approved Whether self-binding is approved for all provided tokens. */ diff --git a/src/mocks/ERC3643TokenMock.sol b/src/mocks/ERC3643TokenMock.sol index 4af841d5..c23ed5a8 100644 --- a/src/mocks/ERC3643TokenMock.sol +++ b/src/mocks/ERC3643TokenMock.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.20; +pragma solidity ^0.8.27; /* ==== Interface and other library === */ import {IERC3643Compliance} from "../interfaces/IERC3643Compliance.sol"; @@ -10,17 +10,19 @@ import {IERC3643Compliance} from "../interfaces/IERC3643Compliance.sol"; * @notice Minimal ERC-3643 (T-REX) style token that drives a compliance contract exactly as the * reference implementation does, used to test the RuleEngine through the ERC-3643 entry points. * @dev The compliance interaction is modelled on `Token.sol` from the ERC-3643 reference - * implementation (submodule `lib/ERC-3643`, tag 4.1.3): + * implementation (submodule `lib/ERC-3643`, T-REX 4.2.0-beta1): * * - `setCompliance` unbinds the previous compliance, then binds itself to the new one * - `transfer` calls `canTransfer(msg.sender, to, amount)` then `transferred(msg.sender, to, amount)` * - `mint` calls `canTransfer(address(0), to, amount)` then `created(to, amount)` * - `burn` calls `destroyed(from, amount)` * - * NOTE: the reference token itself cannot be compiled into this test suite. It pins - * `pragma solidity 0.8.17` (this project compiles with 0.8.36), depends on OpenZeppelin 4.8.x - * (this project uses 5.7.0) and on the `onchain-id/solidity` package, which is not installed here. - * This mock therefore reproduces the compliance-facing behaviour rather than vendoring the token. + * NOTE: the real token is tested too, in `test/ERC3643Real/` under the `erc3643` Foundry profile: it pins + * `pragma solidity 0.8.30` while this project builds with 0.8.37, and imports the `onchain-id/solidity` + * package, which that profile maps to local stubs. This mock stays because it runs in the default profile, with no identity + * registry, and keeps the compliance-facing calls in one small, readable contract. Like the real token, it + * updates balances before calling `created` / `destroyed`, so a rule reading the token's state sees the + * post-mint / post-burn values (see `RuleEngine-with-ERC3643.md` §4.9). * * ERC-3643 compliance callbacks carry no spender, so this token never reaches the 4-argument * `transferred(spender, from, to, value)` overload. diff --git a/src/mocks/ICompliance.sol b/src/mocks/ICompliance.sol index 4385bdfc..c299da25 100644 --- a/src/mocks/ICompliance.sol +++ b/src/mocks/ICompliance.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.20; +pragma solidity ^0.8.27; /** * @title ICompliance diff --git a/src/mocks/IERC1404Subset.sol b/src/mocks/IERC1404Subset.sol index 3b954049..cbbcbb2a 100644 --- a/src/mocks/IERC1404Subset.sol +++ b/src/mocks/IERC1404Subset.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.20; +pragma solidity ^0.8.27; /** * @dev Test-only subset matching IERC1404 for interfaceId checks. diff --git a/src/mocks/IERC173Subset.sol b/src/mocks/IERC173Subset.sol index 960d3dcb..00022a99 100644 --- a/src/mocks/IERC173Subset.sol +++ b/src/mocks/IERC173Subset.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.20; +pragma solidity ^0.8.27; /** * @dev Test-only subset matching ERC-173 for interfaceId checks. diff --git a/src/mocks/IERC3643ComplianceExtendedSubset.sol b/src/mocks/IERC3643ComplianceExtendedSubset.sol index 28cd92a5..09785416 100644 --- a/src/mocks/IERC3643ComplianceExtendedSubset.sol +++ b/src/mocks/IERC3643ComplianceExtendedSubset.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.20; +pragma solidity ^0.8.27; /** * @title IERC3643ComplianceExtendedSubset diff --git a/src/mocks/IERC7551ComplianceSubset.sol b/src/mocks/IERC7551ComplianceSubset.sol index 7e73125c..c546fc06 100644 --- a/src/mocks/IERC7551ComplianceSubset.sol +++ b/src/mocks/IERC7551ComplianceSubset.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.20; +pragma solidity ^0.8.27; /** * @dev Test-only subset interface used to validate the advertised ERC-165 ID. diff --git a/src/mocks/IOwnable2StepSubset.sol b/src/mocks/IOwnable2StepSubset.sol index a322fc84..975ec76c 100644 --- a/src/mocks/IOwnable2StepSubset.sol +++ b/src/mocks/IOwnable2StepSubset.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.20; +pragma solidity ^0.8.27; /** * @dev Test-only subset for Ownable2Step-specific ERC-165 checks. diff --git a/src/mocks/IRuleInterfaceIdHelper.sol b/src/mocks/IRuleInterfaceIdHelper.sol index 3f037693..2ab5319f 100644 --- a/src/mocks/IRuleInterfaceIdHelper.sol +++ b/src/mocks/IRuleInterfaceIdHelper.sol @@ -1,11 +1,9 @@ // SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.20; +pragma solidity ^0.8.27; import {IRule} from "../interfaces/IRule.sol"; -import {IRuleEngineERC1404, IRuleEngine} from "CMTAT/interfaces/engine/IRuleEngine.sol"; import {IERC1404, IERC1404Extend} from "CMTAT/interfaces/tokenization/draft-IERC1404.sol"; -import {IERC3643ComplianceRead, IERC3643IComplianceContract} from "CMTAT/interfaces/tokenization/IERC3643Partial.sol"; -import {IERC7551Compliance} from "CMTAT/interfaces/tokenization/draft-IERC7551.sol"; +import {IERC3643IComplianceContract} from "CMTAT/interfaces/tokenization/IERC3643Partial.sol"; import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; import {RuleInterfaceId} from "../modules/library/RuleInterfaceId.sol"; @@ -18,7 +16,7 @@ import {RuleInterfaceId} from "../modules/library/RuleInterfaceId.sol"; */ interface IRuleAllFunctions { /** - * @notice From IRuleEngine: applies the rule to a transfer carrying a spender. + * @notice From IRule: applies the rule to a transfer carrying a spender. * @param spender The account moving the tokens on behalf of `from`. * @param from The origin address. * @param to The destination address. @@ -70,25 +68,6 @@ interface IRuleAllFunctions { view returns (uint8); - /** - * @notice From IERC3643ComplianceRead: tells whether a transfer is allowed. - * @param from The origin address. - * @param to The destination address. - * @param value The number of tokens to transfer. - * @return True if the transfer is allowed, false otherwise. - */ - function canTransfer(address from, address to, uint256 value) external view returns (bool); - - /** - * @notice From IERC7551Compliance: tells whether a spender-initiated transfer is allowed. - * @param spender The account moving the tokens on behalf of `from`. - * @param from The origin address. - * @param to The destination address. - * @param value The number of tokens to transfer. - * @return True if the transfer is allowed, false otherwise. - */ - function canTransferFrom(address spender, address from, address to, uint256 value) external view returns (bool); - /** * @notice From IERC165: ERC-165 interface detection. * @param interfaceId The interface identifier to check. @@ -128,14 +107,10 @@ contract IRuleInterfaceIdHelper { /** * @notice Returns individual interface IDs from each parent interface - * @return iRuleId The interface ID of IRule. - * @return iRuleEngineERC1404Id The interface ID of IRuleEngineERC1404. - * @return iRuleEngineId The interface ID of IRuleEngine. + * @return iRuleId The interface ID of IRule (its two own functions). * @return iERC1404Id The interface ID of IERC1404. * @return iERC1404ExtendId The interface ID of IERC1404Extend. - * @return iERC3643ComplianceReadId The interface ID of IERC3643ComplianceRead. * @return iERC3643IComplianceContractId The interface ID of IERC3643IComplianceContract. - * @return iERC7551ComplianceId The interface ID of IERC7551Compliance. * @return iERC165Id The interface ID of IERC165. */ function getParentInterfaceIds() @@ -143,24 +118,16 @@ contract IRuleInterfaceIdHelper { pure returns ( bytes4 iRuleId, - bytes4 iRuleEngineERC1404Id, - bytes4 iRuleEngineId, bytes4 iERC1404Id, bytes4 iERC1404ExtendId, - bytes4 iERC3643ComplianceReadId, bytes4 iERC3643IComplianceContractId, - bytes4 iERC7551ComplianceId, bytes4 iERC165Id ) { iRuleId = type(IRule).interfaceId; - iRuleEngineERC1404Id = type(IRuleEngineERC1404).interfaceId; - iRuleEngineId = type(IRuleEngine).interfaceId; iERC1404Id = type(IERC1404).interfaceId; iERC1404ExtendId = type(IERC1404Extend).interfaceId; - iERC3643ComplianceReadId = type(IERC3643ComplianceRead).interfaceId; iERC3643IComplianceContractId = type(IERC3643IComplianceContract).interfaceId; - iERC7551ComplianceId = type(IERC7551Compliance).interfaceId; iERC165Id = type(IERC165).interfaceId; } @@ -172,8 +139,7 @@ contract IRuleInterfaceIdHelper { function computeManualXOR() external pure returns (bytes4) { return IRule.canReturnTransferRestrictionCode.selector ^ IERC1404.detectTransferRestriction.selector ^ IERC1404.messageForTransferRestriction.selector ^ IERC1404Extend.detectTransferRestrictionFrom.selector - ^ IRuleEngine.transferred.selector ^ IERC3643IComplianceContract.transferred.selector - ^ IERC3643ComplianceRead.canTransfer.selector ^ IERC7551Compliance.canTransferFrom.selector - ^ IERC165.supportsInterface.selector; + ^ bytes4(keccak256("transferred(address,address,address,uint256)")) + ^ IERC3643IComplianceContract.transferred.selector ^ IERC165.supportsInterface.selector; } } diff --git a/src/mocks/RuleEngineExposed.sol b/src/mocks/RuleEngineExposed.sol index ba565e4e..f80b3b05 100644 --- a/src/mocks/RuleEngineExposed.sol +++ b/src/mocks/RuleEngineExposed.sol @@ -1,22 +1,22 @@ // SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.20; +pragma solidity ^0.8.27; -import {RuleEngine} from "../deployment/RuleEngine.sol"; -import {RuleEngineOwnable} from "../deployment/RuleEngineOwnable.sol"; -import {RuleEngineOwnable2Step} from "../deployment/RuleEngineOwnable2Step.sol"; +import {RuleEngine2771} from "../deployment/accessControl/RuleEngine2771.sol"; +import {RuleEngineOwnable2771} from "../deployment/ownable/RuleEngineOwnable2771.sol"; +import {RuleEngineOwnable2Step2771} from "../deployment/ownable/RuleEngineOwnable2Step2771.sol"; /** - * @title RuleEngineExposed + * @title RuleEngine2771Exposed * @dev Exposes internal functions for testing coverage */ -contract RuleEngineExposed is RuleEngine { +contract RuleEngine2771Exposed is RuleEngine2771 { /** * @notice Deploys the exposed engine. * @param admin Address receiving the initial privileges. * @param forwarder Address of the trusted ERC-2771 forwarder. * @param token Token to bind at deployment, or the zero address to bind none. */ - constructor(address admin, address forwarder, address token) RuleEngine(admin, forwarder, token) {} + constructor(address admin, address forwarder, address token) RuleEngine2771(admin, forwarder, token) {} /** * @notice Exposes the internal {_msgData} for testing. @@ -28,17 +28,17 @@ contract RuleEngineExposed is RuleEngine { } /** - * @title RuleEngineOwnableExposed + * @title RuleEngineOwnable2771Exposed * @dev Exposes internal functions for testing coverage */ -contract RuleEngineOwnableExposed is RuleEngineOwnable { +contract RuleEngineOwnable2771Exposed is RuleEngineOwnable2771 { /** * @notice Deploys the exposed engine. * @param owner_ Address receiving the initial privileges. * @param forwarder Address of the trusted ERC-2771 forwarder. * @param token Token to bind at deployment, or the zero address to bind none. */ - constructor(address owner_, address forwarder, address token) RuleEngineOwnable(owner_, forwarder, token) {} + constructor(address owner_, address forwarder, address token) RuleEngineOwnable2771(owner_, forwarder, token) {} /** * @notice Exposes the internal {_msgData} for testing. @@ -50,17 +50,19 @@ contract RuleEngineOwnableExposed is RuleEngineOwnable { } /** - * @title RuleEngineOwnable2StepExposed + * @title RuleEngineOwnable2Step2771Exposed * @dev Exposes internal functions for testing coverage */ -contract RuleEngineOwnable2StepExposed is RuleEngineOwnable2Step { +contract RuleEngineOwnable2Step2771Exposed is RuleEngineOwnable2Step2771 { /** * @notice Deploys the exposed engine. * @param owner_ Address receiving the initial privileges. * @param forwarder Address of the trusted ERC-2771 forwarder. * @param token Token to bind at deployment, or the zero address to bind none. */ - constructor(address owner_, address forwarder, address token) RuleEngineOwnable2Step(owner_, forwarder, token) {} + constructor(address owner_, address forwarder, address token) + RuleEngineOwnable2Step2771(owner_, forwarder, token) + {} /** * @notice Exposes the internal {_msgData} for testing. diff --git a/src/mocks/RuleInvalidMock.sol b/src/mocks/RuleInvalidMock.sol index e30ccecf..53980fba 100644 --- a/src/mocks/RuleInvalidMock.sol +++ b/src/mocks/RuleInvalidMock.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.20; +pragma solidity ^0.8.27; import {ERC165} from "@openzeppelin/contracts/utils/introspection/ERC165.sol"; diff --git a/src/mocks/TokenBindingStandaloneMock.sol b/src/mocks/TokenBindingStandaloneMock.sol index 658a2175..65d8629b 100644 --- a/src/mocks/TokenBindingStandaloneMock.sol +++ b/src/mocks/TokenBindingStandaloneMock.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.20; +pragma solidity ^0.8.27; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; import {TokenBindingModule} from "../modules/TokenBindingModule.sol"; diff --git a/src/mocks/rules/operation/RuleConditionalTransferLightMock.sol b/src/mocks/rules/operation/RuleConditionalTransferLightMock.sol index 0606e58c..9d310432 100644 --- a/src/mocks/rules/operation/RuleConditionalTransferLightMock.sol +++ b/src/mocks/rules/operation/RuleConditionalTransferLightMock.sol @@ -1,12 +1,14 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; +pragma solidity ^0.8.27; -import {IRuleEngine} from "CMTAT/interfaces/engine/IRuleEngine.sol"; +import {IRuleEngine, IRuleEngineERC1404} from "CMTAT/interfaces/engine/IRuleEngine.sol"; import { RuleConditionalTransferLightInvariantStorage } from "./abstract/RuleConditionalTransferLightInvariantStorage.sol"; import {IRule} from "../../../interfaces/IRule.sol"; import {RuleInterfaceId} from "../../../modules/library/RuleInterfaceId.sol"; +import {RuleEngineInterfaceId} from "CMTAT/library/RuleEngineInterfaceId.sol"; +import {ERC1404ExtendInterfaceId} from "CMTAT/library/ERC1404ExtendInterfaceId.sol"; import {AccessControl} from "@openzeppelin/contracts/access/AccessControl.sol"; import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; @@ -15,15 +17,12 @@ import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; * @dev Requires operator approval for each ERC20 transfer. * Same transfer (from, to, value) can be approved multiple times. */ -contract RuleConditionalTransferLightMock is AccessControl, RuleConditionalTransferLightInvariantStorage, IRule { - /** - * @notice ERC-165 interface ID of the CMTAT RuleEngine interface. - */ - bytes4 private constant RULE_ENGINE_INTERFACE_ID = 0x20c49ce7; - /** - * @notice ERC-165 interface ID of the extended ERC-1404 interface. - */ - bytes4 private constant ERC1404EXTEND_INTERFACE_ID = 0x78a8de7d; +contract RuleConditionalTransferLightMock is + AccessControl, + RuleConditionalTransferLightInvariantStorage, + IRule, + IRuleEngineERC1404 +{ // Mapping from transfer hash to approval count /** * @notice Number of outstanding approvals per transfer hash. @@ -117,6 +116,7 @@ contract RuleConditionalTransferLightMock is AccessControl, RuleConditionalTrans uint256 value ) public + override(IRule, IRuleEngine) { transferred(from, to, value); } @@ -127,7 +127,8 @@ contract RuleConditionalTransferLightMock is AccessControl, RuleConditionalTrans * @return True if the interface is supported, false otherwise. */ function supportsInterface(bytes4 interfaceId) public view virtual override(AccessControl, IERC165) returns (bool) { - return interfaceId == RULE_ENGINE_INTERFACE_ID || interfaceId == ERC1404EXTEND_INTERFACE_ID + return interfaceId == RuleEngineInterfaceId.RULE_ENGINE_INTERFACE_ID + || interfaceId == ERC1404ExtendInterfaceId.ERC1404EXTEND_INTERFACE_ID || interfaceId == RuleInterfaceId.IRULE_INTERFACE_ID || AccessControl.supportsInterface(interfaceId); } @@ -149,7 +150,7 @@ contract RuleConditionalTransferLightMock is AccessControl, RuleConditionalTrans * @param from the origin address * @param to the destination address * @param value the amount to transfer - * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK + * @return The restriction code or REJECTED_CODE_BASE.TRANSFER_OK * */ function detectTransferRestriction(address from, address to, uint256 value) public view override returns (uint8) { @@ -167,7 +168,7 @@ contract RuleConditionalTransferLightMock is AccessControl, RuleConditionalTrans * @param from the origin address * @param to the destination address * @param value the amount to transfer - * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK + * @return The restriction code or REJECTED_CODE_BASE.TRANSFER_OK * */ function detectTransferRestrictionFrom( diff --git a/src/mocks/rules/operation/RuleMintAllowanceMock.sol b/src/mocks/rules/operation/RuleMintAllowanceMock.sol index 74e2f7e3..d6a3a507 100644 --- a/src/mocks/rules/operation/RuleMintAllowanceMock.sol +++ b/src/mocks/rules/operation/RuleMintAllowanceMock.sol @@ -1,10 +1,13 @@ // SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.20; +pragma solidity ^0.8.27; import {AccessControl} from "@openzeppelin/contracts/access/AccessControl.sol"; import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; import {IRule} from "../../../interfaces/IRule.sol"; +import {IRuleEngine, IRuleEngineERC1404} from "CMTAT/interfaces/engine/IRuleEngine.sol"; import {RuleInterfaceId} from "../../../modules/library/RuleInterfaceId.sol"; +import {RuleEngineInterfaceId} from "CMTAT/library/RuleEngineInterfaceId.sol"; +import {ERC1404ExtendInterfaceId} from "CMTAT/library/ERC1404ExtendInterfaceId.sol"; import {RuleMintAllowanceInvariantStorage} from "./abstract/RuleMintAllowanceInvariantStorage.sol"; /** @@ -14,16 +17,7 @@ import {RuleMintAllowanceInvariantStorage} from "./abstract/RuleMintAllowanceInv * Each mint deducts from the minter's remaining allowance. * Burns and regular transfers are unrestricted by this rule. */ -contract RuleMintAllowanceMock is AccessControl, RuleMintAllowanceInvariantStorage, IRule { - /** - * @notice ERC-165 interface ID of the CMTAT RuleEngine interface. - */ - bytes4 private constant RULE_ENGINE_INTERFACE_ID = 0x20c49ce7; - /** - * @notice ERC-165 interface ID of the extended ERC-1404 interface. - */ - bytes4 private constant ERC1404EXTEND_INTERFACE_ID = 0x78a8de7d; - +contract RuleMintAllowanceMock is AccessControl, RuleMintAllowanceInvariantStorage, IRule, IRuleEngineERC1404 { /** * @notice Remaining mint allowance per minter. */ @@ -103,12 +97,11 @@ contract RuleMintAllowanceMock is AccessControl, RuleMintAllowanceInvariantStora uint256 value ) public + override(IRule, IRuleEngine) { if (from == address(0)) { uint256 allowance = mintAllowance[spender]; - if (allowance < value) { - revert RuleMintAllowance_InsufficientAllowance(spender, allowance, value); - } + require(allowance >= value, RuleMintAllowance_InsufficientAllowance(spender, allowance, value)); mintAllowance[spender] = allowance - value; emit MintAllowanceConsumed(spender, value, mintAllowance[spender]); } @@ -122,7 +115,8 @@ contract RuleMintAllowanceMock is AccessControl, RuleMintAllowanceInvariantStora * @return True if the interface is supported, false otherwise. */ function supportsInterface(bytes4 interfaceId) public view virtual override(AccessControl, IERC165) returns (bool) { - return interfaceId == RULE_ENGINE_INTERFACE_ID || interfaceId == ERC1404EXTEND_INTERFACE_ID + return interfaceId == RuleEngineInterfaceId.RULE_ENGINE_INTERFACE_ID + || interfaceId == ERC1404ExtendInterfaceId.ERC1404EXTEND_INTERFACE_ID || interfaceId == RuleInterfaceId.IRULE_INTERFACE_ID || AccessControl.supportsInterface(interfaceId); } diff --git a/src/mocks/rules/operation/RuleOperationRevertMock.sol b/src/mocks/rules/operation/RuleOperationRevertMock.sol index 97a584a2..1cda0651 100644 --- a/src/mocks/rules/operation/RuleOperationRevertMock.sol +++ b/src/mocks/rules/operation/RuleOperationRevertMock.sol @@ -1,9 +1,12 @@ // SPDX-License-Identifier: MIT -pragma solidity ^0.8.20; +pragma solidity ^0.8.27; import {RuleCommonInvariantStorage} from "../validation/abstract/RuleCommonInvariantStorage.sol"; import {IRule} from "../../../interfaces/IRule.sol"; +import {IRuleEngine, IRuleEngineERC1404} from "CMTAT/interfaces/engine/IRuleEngine.sol"; import {RuleInterfaceId} from "../../../modules/library/RuleInterfaceId.sol"; +import {RuleEngineInterfaceId} from "CMTAT/library/RuleEngineInterfaceId.sol"; +import {ERC1404ExtendInterfaceId} from "CMTAT/library/ERC1404ExtendInterfaceId.sol"; import {AccessControl} from "@openzeppelin/contracts/access/AccessControl.sol"; import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; @@ -12,7 +15,7 @@ import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; * @dev Requires operator approval for each ERC20 transfer. * Same transfer (from, to, value) can be approved multiple times. */ -contract RuleOperationRevertMock is AccessControl, IRule, RuleCommonInvariantStorage { +contract RuleOperationRevertMock is AccessControl, IRule, IRuleEngineERC1404, RuleCommonInvariantStorage { error RuleConditionalTransferLight_InvalidTransfer(); // It is very important that each rule uses an unique code /** @@ -20,15 +23,6 @@ contract RuleOperationRevertMock is AccessControl, IRule, RuleCommonInvariantSto */ uint8 public constant CODE_TRANSFER_REQUEST_NOT_APPROVED = 71; - /** - * @notice ERC-165 interface ID of the CMTAT RuleEngine interface. - */ - bytes4 private constant RULE_ENGINE_INTERFACE_ID = 0x20c49ce7; - /** - * @notice ERC-165 interface ID of the extended ERC-1404 interface. - */ - bytes4 private constant ERC1404EXTEND_INTERFACE_ID = 0x78a8de7d; - /** * @notice To know if the restriction code is valid for this rule or not. * @param restrictionCode The target restriction code @@ -61,7 +55,8 @@ contract RuleOperationRevertMock is AccessControl, IRule, RuleCommonInvariantSto * @return True if the interface is supported, false otherwise. */ function supportsInterface(bytes4 interfaceId) public view virtual override(AccessControl, IERC165) returns (bool) { - return interfaceId == RULE_ENGINE_INTERFACE_ID || interfaceId == ERC1404EXTEND_INTERFACE_ID + return interfaceId == RuleEngineInterfaceId.RULE_ENGINE_INTERFACE_ID + || interfaceId == ERC1404ExtendInterfaceId.ERC1404EXTEND_INTERFACE_ID || interfaceId == RuleInterfaceId.IRULE_INTERFACE_ID || AccessControl.supportsInterface(interfaceId); } @@ -96,13 +91,14 @@ contract RuleOperationRevertMock is AccessControl, IRule, RuleCommonInvariantSto ) public pure + override(IRule, IRuleEngine) { revert RuleConditionalTransferLight_InvalidTransfer(); } /** * @notice Check if the transfer is valid - * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK + * @return The restriction code or REJECTED_CODE_BASE.TRANSFER_OK * */ function detectTransferRestriction( @@ -125,7 +121,7 @@ contract RuleOperationRevertMock is AccessControl, IRule, RuleCommonInvariantSto * @param from the origin address * @param to the destination address * @param value the amount to transfer - * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK + * @return The restriction code or REJECTED_CODE_BASE.TRANSFER_OK * */ function detectTransferRestrictionFrom( diff --git a/src/mocks/rules/operation/abstract/RuleConditionalTransferLightInvariantStorage.sol b/src/mocks/rules/operation/abstract/RuleConditionalTransferLightInvariantStorage.sol index 8a34ec73..5802d16f 100644 --- a/src/mocks/rules/operation/abstract/RuleConditionalTransferLightInvariantStorage.sol +++ b/src/mocks/rules/operation/abstract/RuleConditionalTransferLightInvariantStorage.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.20; +pragma solidity ^0.8.27; import {RuleCommonInvariantStorage} from "../../validation/abstract/RuleCommonInvariantStorage.sol"; diff --git a/src/mocks/rules/operation/abstract/RuleMintAllowanceInvariantStorage.sol b/src/mocks/rules/operation/abstract/RuleMintAllowanceInvariantStorage.sol index ca3a0ba1..83e01b2e 100644 --- a/src/mocks/rules/operation/abstract/RuleMintAllowanceInvariantStorage.sol +++ b/src/mocks/rules/operation/abstract/RuleMintAllowanceInvariantStorage.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.20; +pragma solidity ^0.8.27; import {RuleCommonInvariantStorage} from "../../validation/abstract/RuleCommonInvariantStorage.sol"; diff --git a/src/mocks/rules/validation/RuleWhitelistMock.sol b/src/mocks/rules/validation/RuleWhitelistMock.sol index 19d12a68..eeae30ca 100644 --- a/src/mocks/rules/validation/RuleWhitelistMock.sol +++ b/src/mocks/rules/validation/RuleWhitelistMock.sol @@ -1,26 +1,22 @@ // SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.20; +pragma solidity ^0.8.27; import {RuleAddressList} from "./abstract/RuleAddressList/RuleAddressList.sol"; import {RuleWhitelistCommon} from "./abstract/RuleWhitelistCommon.sol"; +import {IRuleEngine, IRuleEngineERC1404} from "CMTAT/interfaces/engine/IRuleEngine.sol"; +import {IRule} from "../../../interfaces/IRule.sol"; import {AccessControl} from "@openzeppelin/contracts/access/AccessControl.sol"; import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; import {RuleInterfaceId} from "../../../modules/library/RuleInterfaceId.sol"; +import {RuleEngineInterfaceId} from "CMTAT/library/RuleEngineInterfaceId.sol"; +import {ERC1404ExtendInterfaceId} from "CMTAT/library/ERC1404ExtendInterfaceId.sol"; //import {ERC165, IERC165} from "@OZ/utils/introspection/ERC165.sol"; /** * @title a whitelist manager */ -contract RuleWhitelistMock is RuleAddressList, RuleWhitelistCommon { - /** - * @notice ERC-165 interface ID of the CMTAT RuleEngine interface. - */ - bytes4 private constant RULE_ENGINE_INTERFACE_ID = 0x20c49ce7; - /** - * @notice ERC-165 interface ID of the extended ERC-1404 interface. - */ - bytes4 private constant ERC1404EXTEND_INTERFACE_ID = 0x78a8de7d; +contract RuleWhitelistMock is RuleAddressList, RuleWhitelistCommon, IRuleEngineERC1404 { error RuleWhitelist_InvalidTransfer(address from, address to, uint256 value, uint8 code); /** @@ -48,7 +44,7 @@ contract RuleWhitelistMock is RuleAddressList, RuleWhitelistCommon { * @param to the destination address * @param value the amount to transfer */ - function transferred(address spender, address from, address to, uint256 value) public { + function transferred(address spender, address from, address to, uint256 value) public override(IRule, IRuleEngine) { uint8 code = detectTransferRestrictionFrom(spender, from, to, value); require(code == uint8(REJECTED_CODE_BASE.TRANSFER_OK), RuleWhitelist_InvalidTransfer(from, to, value, code)); } @@ -59,7 +55,8 @@ contract RuleWhitelistMock is RuleAddressList, RuleWhitelistCommon { * @return True if the interface is supported, false otherwise. */ function supportsInterface(bytes4 interfaceId) public view virtual override(AccessControl, IERC165) returns (bool) { - return interfaceId == RULE_ENGINE_INTERFACE_ID || interfaceId == ERC1404EXTEND_INTERFACE_ID + return interfaceId == RuleEngineInterfaceId.RULE_ENGINE_INTERFACE_ID + || interfaceId == ERC1404ExtendInterfaceId.ERC1404EXTEND_INTERFACE_ID || interfaceId == RuleInterfaceId.IRULE_INTERFACE_ID || AccessControl.supportsInterface(interfaceId); } @@ -97,7 +94,7 @@ contract RuleWhitelistMock is RuleAddressList, RuleWhitelistCommon { * @notice Check if an addres is in the whitelist or not * @param from the origin address * @param to the destination address - * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK + * @return The restriction code or REJECTED_CODE_BASE.TRANSFER_OK * */ function detectTransferRestriction( diff --git a/src/mocks/rules/validation/abstract/RuleAddressList/RuleAddressList.sol b/src/mocks/rules/validation/abstract/RuleAddressList/RuleAddressList.sol index 9956414a..097d984c 100644 --- a/src/mocks/rules/validation/abstract/RuleAddressList/RuleAddressList.sol +++ b/src/mocks/rules/validation/abstract/RuleAddressList/RuleAddressList.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.20; +pragma solidity ^0.8.27; import {AccessControl} from "@openzeppelin/contracts/access/AccessControl.sol"; import {Context} from "@openzeppelin/contracts/utils/Context.sol"; @@ -30,9 +30,7 @@ abstract contract RuleAddressList is * @param forwarderIrrevocable Address of the forwarder, required for the gasless support */ constructor(address admin, address forwarderIrrevocable) ERC2771ModuleStandalone(forwarderIrrevocable) { - if (admin == address(0)) { - revert RuleAddressList_AdminWithAddressZeroNotAllowed(); - } + require(admin != address(0), RuleAddressList_AdminWithAddressZeroNotAllowed()); _grantRole(DEFAULT_ADMIN_ROLE, admin); } diff --git a/src/mocks/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol b/src/mocks/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol index 824ba825..af9406bb 100644 --- a/src/mocks/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol +++ b/src/mocks/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.20; +pragma solidity ^0.8.27; /** * @title a list manager @@ -59,9 +59,7 @@ abstract contract RuleAddressListInternal { * @param targetAddress The address to list */ function _addAddressToThelist(address targetAddress) internal virtual { - if (list[targetAddress]) { - revert Rulelist_AddressAlreadylisted(); - } + require(!list[targetAddress], Rulelist_AddressAlreadylisted()); list[targetAddress] = true; ++numAddressesList; } @@ -73,9 +71,7 @@ abstract contract RuleAddressListInternal { * */ function _removeAddressFromThelist(address targetAddress) internal virtual { - if (!list[targetAddress]) { - revert Rulelist_AddressNotPresent(); - } + require(list[targetAddress], Rulelist_AddressNotPresent()); list[targetAddress] = false; --numAddressesList; } diff --git a/src/mocks/rules/validation/abstract/RuleAddressList/invariantStorage/RuleAddressListInvariantStorage.sol b/src/mocks/rules/validation/abstract/RuleAddressList/invariantStorage/RuleAddressListInvariantStorage.sol index 6ff44a52..8c62c3d8 100644 --- a/src/mocks/rules/validation/abstract/RuleAddressList/invariantStorage/RuleAddressListInvariantStorage.sol +++ b/src/mocks/rules/validation/abstract/RuleAddressList/invariantStorage/RuleAddressListInvariantStorage.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.20; +pragma solidity ^0.8.27; /** * @title RuleAddressListInvariantStorage diff --git a/src/mocks/rules/validation/abstract/RuleAddressList/invariantStorage/RuleBlacklistInvariantStorage.sol b/src/mocks/rules/validation/abstract/RuleAddressList/invariantStorage/RuleBlacklistInvariantStorage.sol index b7f4b0f6..ac373cf6 100644 --- a/src/mocks/rules/validation/abstract/RuleAddressList/invariantStorage/RuleBlacklistInvariantStorage.sol +++ b/src/mocks/rules/validation/abstract/RuleAddressList/invariantStorage/RuleBlacklistInvariantStorage.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.20; +pragma solidity ^0.8.27; import {RuleCommonInvariantStorage} from "../../RuleCommonInvariantStorage.sol"; diff --git a/src/mocks/rules/validation/abstract/RuleAddressList/invariantStorage/RuleWhitelistInvariantStorage.sol b/src/mocks/rules/validation/abstract/RuleAddressList/invariantStorage/RuleWhitelistInvariantStorage.sol index 65685bbe..ecaf762c 100644 --- a/src/mocks/rules/validation/abstract/RuleAddressList/invariantStorage/RuleWhitelistInvariantStorage.sol +++ b/src/mocks/rules/validation/abstract/RuleAddressList/invariantStorage/RuleWhitelistInvariantStorage.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.20; +pragma solidity ^0.8.27; import {RuleCommonInvariantStorage} from "../../RuleCommonInvariantStorage.sol"; diff --git a/src/mocks/rules/validation/abstract/RuleCommonInvariantStorage.sol b/src/mocks/rules/validation/abstract/RuleCommonInvariantStorage.sol index 1929f87c..7de3b861 100644 --- a/src/mocks/rules/validation/abstract/RuleCommonInvariantStorage.sol +++ b/src/mocks/rules/validation/abstract/RuleCommonInvariantStorage.sol @@ -1,5 +1,5 @@ // SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.20; +pragma solidity ^0.8.27; /** * @title RuleCommonInvariantStorage diff --git a/src/mocks/rules/validation/abstract/RuleWhitelistCommon.sol b/src/mocks/rules/validation/abstract/RuleWhitelistCommon.sol index 03a4838a..fdd569be 100644 --- a/src/mocks/rules/validation/abstract/RuleWhitelistCommon.sol +++ b/src/mocks/rules/validation/abstract/RuleWhitelistCommon.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.20; +pragma solidity ^0.8.27; import {RuleWhitelistInvariantStorage} from "./RuleAddressList/invariantStorage/RuleWhitelistInvariantStorage.sol"; import {IRule} from "../../../../interfaces/IRule.sol"; diff --git a/src/modules/ERC2771ModuleStandalone.sol b/src/modules/ERC2771ModuleStandalone.sol index 5570e100..21c4e7fe 100644 --- a/src/modules/ERC2771ModuleStandalone.sol +++ b/src/modules/ERC2771ModuleStandalone.sol @@ -1,6 +1,6 @@ //SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.20; +pragma solidity ^0.8.27; /* ==== OpenZeppelin === */ import {ERC2771Context} from "@openzeppelin/contracts/metatx/ERC2771Context.sol"; diff --git a/src/modules/ERC3643ComplianceExtendedModule.sol b/src/modules/ERC3643ComplianceExtendedModule.sol index ed80d62a..84ff48bd 100644 --- a/src/modules/ERC3643ComplianceExtendedModule.sol +++ b/src/modules/ERC3643ComplianceExtendedModule.sol @@ -1,6 +1,6 @@ //SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.20; +pragma solidity ^0.8.27; /* ==== Modules === */ import {ERC3643ComplianceModule} from "./ERC3643ComplianceModule.sol"; @@ -36,4 +36,14 @@ abstract contract ERC3643ComplianceExtendedModule is { TokenBindingExtendedModule._authorizeTokenBindingChange(token); } + + /** + * @dev Disambiguates {_unbindToken}, inherited through {TokenBindingExtendedModule} and through + * {ERC3643ComplianceModule}. The extended behaviour wins: a manager unbind also revokes the token's + * self-binding approval. + * @param token The token to unbind. + */ + function _unbindToken(address token) internal virtual override(TokenBindingModule, TokenBindingExtendedModule) { + TokenBindingExtendedModule._unbindToken(token); + } } diff --git a/src/modules/ERC3643ComplianceModule.sol b/src/modules/ERC3643ComplianceModule.sol index 81b7c48f..78d06520 100644 --- a/src/modules/ERC3643ComplianceModule.sol +++ b/src/modules/ERC3643ComplianceModule.sol @@ -1,6 +1,6 @@ //SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.20; +pragma solidity ^0.8.27; /* ==== OpenZeppelin === */ import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; @@ -33,7 +33,7 @@ abstract contract ERC3643ComplianceModule is TokenBindingModule, IERC3643Complia using EnumerableSet for EnumerableSet.AddressSet; /*////////////////////////////////////////////////////////////// - PUBLIC/public FUNCTIONS + PUBLIC/EXTERNAL FUNCTIONS //////////////////////////////////////////////////////////////*/ /* ============ View functions ============ */ diff --git a/src/modules/RulesManagementModule.sol b/src/modules/RulesManagementModule.sol index 317199fa..12d60f71 100644 --- a/src/modules/RulesManagementModule.sol +++ b/src/modules/RulesManagementModule.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.20; +pragma solidity ^0.8.27; /* ==== OpenZeppelin === */ import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; @@ -10,7 +10,9 @@ import {IRule} from "../interfaces/IRule.sol"; import {RulesManagementModuleInvariantStorage} from "./library/RulesManagementModuleInvariantStorage.sol"; /** - * @title RuleEngine - part + * @title RulesManagementModule + * @notice Rule set of the RuleEngine: add, remove, replace and clear rules under a configurable cap, and + * apply every rule to a token operation. */ abstract contract RulesManagementModule is RulesManagementModuleInvariantStorage, IRulesManagementModule { modifier onlyRulesManager() { @@ -50,12 +52,8 @@ abstract contract RulesManagementModule is RulesManagementModuleInvariantStorage * but should not also be granted {RULES_MANAGEMENT_ROLE}. */ function setRules(IRule[] calldata rules_) public virtual override(IRulesManagementModule) onlyRulesManager { - if (rules_.length == 0) { - revert RuleEngine_RulesManagementModule_ArrayIsEmpty(); - } - if (rules_.length > _maxRules) { - revert RuleEngine_RulesManagementModule_MaxRulesExceeded(_maxRules); - } + require(rules_.length != 0, RuleEngine_RulesManagementModule_ArrayIsEmpty()); + require(rules_.length <= _maxRules, RuleEngine_RulesManagementModule_MaxRulesExceeded(_maxRules)); if (_rules.length() > 0) { _clearRules(); } @@ -77,9 +75,9 @@ abstract contract RulesManagementModule is RulesManagementModuleInvariantStorage * Security convention: do not grant {RULES_MANAGEMENT_ROLE} to rule contracts. */ function addRule(IRule rule_) public virtual override(IRulesManagementModule) onlyRulesManager { - if (_rules.length() >= _maxRules) { - revert RuleEngine_RulesManagementModule_MaxRulesExceeded(_maxRules); - } + // `require` evaluates the error arguments even when the check passes: cache the cap to read it once + uint256 maxRules_ = _maxRules; + require(_rules.length() < maxRules_, RuleEngine_RulesManagementModule_MaxRulesExceeded(maxRules_)); _addRule(rule_); } @@ -94,7 +92,6 @@ abstract contract RulesManagementModule is RulesManagementModuleInvariantStorage * @inheritdoc IRulesManagementModule */ function removeRule(IRule rule_) public virtual override(IRulesManagementModule) onlyRulesManager { - require(_rules.contains(address(rule_)), RuleEngine_RulesManagementModule_RuleDoNotMatch()); _removeRule(rule_); } @@ -161,9 +158,7 @@ abstract contract RulesManagementModule is RulesManagementModuleInvariantStorage * @param maxRules_ New maximum number of rules; must not be zero. */ function _setMaxRules(uint256 maxRules_) internal virtual { - if (maxRules_ == 0) { - revert RuleEngine_RulesManagementModule_MaxRulesZeroNotAllowed(); - } + require(maxRules_ != 0, RuleEngine_RulesManagementModule_MaxRulesZeroNotAllowed()); _maxRules = maxRules_; emit SetMaxRules(maxRules_); } @@ -177,28 +172,27 @@ abstract contract RulesManagementModule is RulesManagementModuleInvariantStorage */ function _addRule(IRule rule_) internal virtual { _checkRule(address(rule_)); - // Should never revert because we check the presence of the rule before - require(_rules.add(address(rule_)), RuleEngine_RulesManagementModule_OperationNotSuccessful()); + // The set rejects a duplicate: `add` returns false when the rule is already present + require(_rules.add(address(rule_)), RuleEngine_RulesManagementModule_RuleAlreadyExists()); emit AddRule(rule_); } /** - * @notice Remove a rule from the array of rules - * Revert if the rule found at the specified index does not match the rule in argument + * @notice Remove a rule from the array of rules and emit the corresponding event + * @dev Reverts with {RuleEngine_RulesManagementModule_RuleDoNotMatch} if the rule is not in the set. * @param rule_ address of the target rule - * - * */ function _removeRule(IRule rule_) internal virtual { - // Should never revert because we check the presence of the rule before - require(_rules.remove(address(rule_)), RuleEngine_RulesManagementModule_OperationNotSuccessful()); + // `remove` returns false when the rule is not in the set + require(_rules.remove(address(rule_)), RuleEngine_RulesManagementModule_RuleDoNotMatch()); emit RemoveRule(rule_); } /* ============ Transferred functions ============ */ /** - * @notice Go through all the rule to know if a restriction exists on the transfer + * @notice Applies every rule, in order, to an operation without a spender; reverts as soon as one rule + * rejects it (each rule's `transferred` reverts on a disallowed operation). * @dev Complexity is O(number of configured rules). Large rule sets can make * transfers too expensive on chains with lower block gas limits. * Security convention: rule contracts are expected to be trusted and must not @@ -216,7 +210,8 @@ abstract contract RulesManagementModule is RulesManagementModuleInvariantStorage } /** - * @notice Go through all the rule to know if a restriction exists on the transfer + * @notice Applies every rule, in order, to an operation with a spender; reverts as soon as one rule + * rejects it (each rule's `transferred` reverts on a disallowed operation). * @dev Complexity is O(number of configured rules). Large rule sets can make * transfers too expensive on chains with lower block gas limits. * Security convention: rule contracts are expected to be trusted and must not @@ -245,15 +240,11 @@ abstract contract RulesManagementModule is RulesManagementModuleInvariantStorage function _onlyRulesLimitManager() internal virtual; /** - * @dev check if a rule is valid, revert otherwise + * @dev check if a rule is valid, revert otherwise. + * Duplicates are not checked here: {_addRule} rejects them through the return value of the set insertion. * @param rule_ The candidate rule address to validate. */ function _checkRule(address rule_) internal view virtual { - if (rule_ == address(0x0)) { - revert RuleEngine_RulesManagementModule_RuleAddressZeroNotAllowed(); - } - if (_rules.contains(rule_)) { - revert RuleEngine_RulesManagementModule_RuleAlreadyExists(); - } + require(rule_ != address(0), RuleEngine_RulesManagementModule_RuleAddressZeroNotAllowed()); } } diff --git a/src/modules/TokenBindingExtendedModule.sol b/src/modules/TokenBindingExtendedModule.sol index f0eb976d..3ec890b1 100644 --- a/src/modules/TokenBindingExtendedModule.sol +++ b/src/modules/TokenBindingExtendedModule.sol @@ -1,6 +1,6 @@ //SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.20; +pragma solidity ^0.8.27; /* ==== OpenZeppelin === */ import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; @@ -25,7 +25,7 @@ abstract contract TokenBindingExtendedModule is TokenBindingModule, ITokenBindin mapping(address token => bool approved) private _tokenSelfBindingApproval; /*////////////////////////////////////////////////////////////// - PUBLIC/public FUNCTIONS + PUBLIC/EXTERNAL FUNCTIONS //////////////////////////////////////////////////////////////*/ /* ============ State functions ============ */ @@ -51,8 +51,7 @@ abstract contract TokenBindingExtendedModule is TokenBindingModule, ITokenBindin /// @inheritdoc ITokenBindingExtended function setTokenSelfBindingApproval(address token, bool approved) public virtual override onlyTokenBindingManager { require(token != address(0), TokenBinding_InvalidTokenAddress()); - _tokenSelfBindingApproval[token] = approved; - emit TokenSelfBindingApprovalSet(token, approved); + _setTokenSelfBindingApproval(token, approved); } /// @inheritdoc ITokenBindingExtended @@ -85,13 +84,45 @@ abstract contract TokenBindingExtendedModule is TokenBindingModule, ITokenBindin INTERNAL/PRIVATE FUNCTIONS //////////////////////////////////////////////////////////////*/ + /** + * @dev Removes a token from the bound set and, when the caller is not the token itself, revokes its + * self-binding approval. Without the revocation, a token approved for self-binding could bind itself again + * right after the binding manager unbound it, overriding the manager's decision. A token unbinding itself + * (ERC-3643 `setCompliance` moving to another compliance contract) keeps its approval, so it can come back. + * Covers both {unbindToken} and {unbindTokens}. Like the token self-binding check, the caller is the raw + * `msg.sender`, so a manager call relayed by the ERC-2771 forwarder also revokes the approval. + * @param token The token to unbind; reverts when it is not currently bound. + */ + function _unbindToken(address token) internal virtual override { + TokenBindingModule._unbindToken(token); + if (msg.sender != token && _tokenSelfBindingApproval[token]) { + _setTokenSelfBindingApproval(token, false); + } + } + + /** + * @dev Writes a token's self-binding approval and emits {TokenSelfBindingApprovalSet}. Single write path for + * the per-token event; the batch setter emits {TokenSelfBindingApprovalBatchSet} instead. + * @param token The token whose approval is set. + * @param approved Whether the token may bind and unbind itself. + */ + function _setTokenSelfBindingApproval(address token, bool approved) internal virtual { + _tokenSelfBindingApproval[token] = approved; + emit TokenSelfBindingApprovalSet(token, approved); + } + /** * @dev Authorizes bind/unbind operations. * Allows the binding manager, or approved token self-calls (used by ERC-3643 `setCompliance`). + * IMPORTANT: the token self-call is identified by the raw `msg.sender`, not the ERC-2771 + * `_msgSender()`: a token calls `bindToken` / `unbindToken` on itself directly from + * `setCompliance`, never through a forwarder. Otherwise the trusted forwarder could append an + * approved token's address and unbind it. The manager path (`_onlyTokenBindingManager`) keeps + * `_msgSender()`, so binding administration remains relayable. * @param token The token being bound or unbound. */ function _authorizeTokenBindingChange(address token) internal virtual override { - if (_msgSender() == token && _tokenSelfBindingApproval[token]) { + if (msg.sender == token && _tokenSelfBindingApproval[token]) { return; } _onlyTokenBindingManager(); diff --git a/src/modules/TokenBindingModule.sol b/src/modules/TokenBindingModule.sol index f42d0857..4cafaa9c 100644 --- a/src/modules/TokenBindingModule.sol +++ b/src/modules/TokenBindingModule.sol @@ -1,6 +1,6 @@ //SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.20; +pragma solidity ^0.8.27; /* ==== OpenZeppelin === */ import {EnumerableSet} from "@openzeppelin/contracts/utils/structs/EnumerableSet.sol"; @@ -54,7 +54,7 @@ abstract contract TokenBindingModule is Context, ITokenBinding, TokenBindingModu } /*////////////////////////////////////////////////////////////// - PUBLIC/public FUNCTIONS + PUBLIC/EXTERNAL FUNCTIONS //////////////////////////////////////////////////////////////*/ /* ============ State functions ============ */ @@ -95,16 +95,29 @@ abstract contract TokenBindingModule is Context, ITokenBinding, TokenBindingModu /** * @dev Adds a token to the bound set. - * @param token The token to bind; reverts on the zero address or when already bound. + * A bound address is trusted to report token operations: it can drive every stateful downstream check + * without moving any token, and the registry cannot tell a token contract from any other address. Bind only + * the token contracts the host is meant to serve. + * @param token The token to bind; reverts on the zero address, when already bound, or when + * {_checkBindingTarget} rejects it. */ function _bindToken(address token) internal virtual { require(token != address(0), TokenBinding_InvalidTokenAddress()); + _checkBindingTarget(token); // add() returns false when the token is already bound, so a separate // contains() lookup is unnecessary. require(_boundTokens.add(token), TokenBinding_TokenAlreadyBound()); emit TokenBound(token); } + /** + * @dev Hook for host-specific restrictions on which addresses may be bound; reverts to reject `token`. + * Empty here, so the registry stays standalone. Every binding path ({bindToken}, the batch and the token + * self-binding paths) reaches it through {_bindToken}. + * @param token The address about to be bound. + */ + function _checkBindingTarget(address token) internal view virtual {} + /** * @dev Removes a token from the bound set. * @param token The token to unbind; reverts when it is not currently bound. @@ -139,10 +152,13 @@ abstract contract TokenBindingModule is Context, ITokenBinding, TokenBindingModu /** * @dev Reverts when the caller is not a bound token. + * IMPORTANT: compares the raw `msg.sender`, not the ERC-2771 `_msgSender()`. A token always + * calls the engine directly from its own transfer, mint or burn, never through a forwarder, so + * the two are equal for every legitimate call. Resolving the caller through `_msgSender()` would + * let the trusted forwarder append a bound token's address and drive the rule callbacks with no + * token movement. Administrative functions keep `_msgSender()`, so they remain relayable. */ function _checkBoundToken() internal view virtual { - if (!_boundTokens.contains(_msgSender())) { - revert TokenBinding_UnauthorizedCaller(); - } + require(_boundTokens.contains(msg.sender), TokenBinding_UnauthorizedCaller()); } } diff --git a/src/modules/VersionModule.sol b/src/modules/VersionModule.sol index 975f11b7..6933e0c5 100644 --- a/src/modules/VersionModule.sol +++ b/src/modules/VersionModule.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.20; +pragma solidity ^0.8.27; /* ==== CMTAT === */ import {IERC3643Version} from "CMTAT/interfaces/tokenization/IERC3643Partial.sol"; @@ -15,9 +15,8 @@ abstract contract VersionModule is IERC3643Version { * @dev * Get the current version of the smart contract */ - string internal constant VERSION = "3.0.0"; + string internal constant VERSION = "3.0.0-rc7"; - /* ============ Events ============ */ /*////////////////////////////////////////////////////////////// PUBLIC/EXTERNAL FUNCTIONS //////////////////////////////////////////////////////////////*/ diff --git a/src/modules/library/ComplianceInterfaceId.sol b/src/modules/library/ComplianceInterfaceId.sol index 40ec0084..f41e4e1e 100644 --- a/src/modules/library/ComplianceInterfaceId.sol +++ b/src/modules/library/ComplianceInterfaceId.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.20; +pragma solidity ^0.8.27; /* ==== CMTAT === */ import {IERC3643ComplianceRead, IERC3643IComplianceContract} from "CMTAT/interfaces/tokenization/IERC3643Partial.sol"; @@ -31,9 +31,9 @@ library ComplianceInterfaceId { * `ITokenBinding` (bindToken, unbindToken, isTokenBound), `IERC3643ComplianceRead` (canTransfer) * and `IERC3643IComplianceContract` (transferred). Equals `0x3144991c`. */ - bytes4 public constant ERC3643_COMPLIANCE_INTERFACE_ID = - type(IERC3643Compliance).interfaceId ^ type(ITokenBinding).interfaceId - ^ type(IERC3643ComplianceRead).interfaceId ^ type(IERC3643IComplianceContract).interfaceId; + bytes4 public constant ERC3643_COMPLIANCE_INTERFACE_ID = type(IERC3643Compliance).interfaceId + ^ type(ITokenBinding).interfaceId ^ type(IERC3643ComplianceRead).interfaceId + ^ type(IERC3643IComplianceContract).interfaceId; /** * @notice ERC-165 interface ID of the extended ERC-3643 compliance interface. diff --git a/src/modules/library/ERC1404InterfaceId.sol b/src/modules/library/ERC1404InterfaceId.sol index b92e8ac5..293ea2df 100644 --- a/src/modules/library/ERC1404InterfaceId.sol +++ b/src/modules/library/ERC1404InterfaceId.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.20; +pragma solidity ^0.8.27; /* ==== CMTAT === */ import {IERC1404} from "CMTAT/interfaces/tokenization/draft-IERC1404.sol"; diff --git a/src/modules/library/ERC3643ComplianceRolesStorage.sol b/src/modules/library/ERC3643ComplianceRolesStorage.sol index 1149b563..ef027990 100644 --- a/src/modules/library/ERC3643ComplianceRolesStorage.sol +++ b/src/modules/library/ERC3643ComplianceRolesStorage.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.20; +pragma solidity ^0.8.27; /** * @title ERC3643ComplianceRolesStorage diff --git a/src/modules/library/Ownable2StepInterfaceId.sol b/src/modules/library/Ownable2StepInterfaceId.sol index 9d1c80ff..4eb74ce2 100644 --- a/src/modules/library/Ownable2StepInterfaceId.sol +++ b/src/modules/library/Ownable2StepInterfaceId.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.20; +pragma solidity ^0.8.27; /** * @title Ownable2StepInterfaceId diff --git a/src/modules/library/OwnableInterfaceId.sol b/src/modules/library/OwnableInterfaceId.sol index d66e8185..6dfa45ab 100644 --- a/src/modules/library/OwnableInterfaceId.sol +++ b/src/modules/library/OwnableInterfaceId.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.20; +pragma solidity ^0.8.27; /** * @title OwnableInterfaceId diff --git a/src/modules/library/RuleEngineInvariantStorage.sol b/src/modules/library/RuleEngineInvariantStorage.sol index cc58ef65..cec1455c 100644 --- a/src/modules/library/RuleEngineInvariantStorage.sol +++ b/src/modules/library/RuleEngineInvariantStorage.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.20; +pragma solidity ^0.8.27; /** * @title RuleEngineInvariantStorage diff --git a/src/modules/library/RuleInterfaceId.sol b/src/modules/library/RuleInterfaceId.sol index 31998b59..e9253b52 100644 --- a/src/modules/library/RuleInterfaceId.sol +++ b/src/modules/library/RuleInterfaceId.sol @@ -1,14 +1,13 @@ // SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.20; +pragma solidity ^0.8.27; /* ==== OpenZeppelin === */ import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; /* ==== CMTAT === */ -import {IRuleEngine} from "CMTAT/interfaces/engine/IRuleEngine.sol"; import {IERC1404, IERC1404Extend} from "CMTAT/interfaces/tokenization/draft-IERC1404.sol"; -import {IERC7551Compliance} from "CMTAT/interfaces/tokenization/draft-IERC7551.sol"; import {IERC3643ComplianceRead, IERC3643IComplianceContract} from "CMTAT/interfaces/tokenization/IERC3643Partial.sol"; +import {IERC7551Compliance} from "CMTAT/interfaces/tokenization/draft-IERC7551.sol"; /* ==== Interfaces === */ import {IRule} from "../../interfaces/IRule.sol"; @@ -17,25 +16,27 @@ import {IRule} from "../../interfaces/IRule.sol"; * @dev ERC-165 interface ID for the full IRule hierarchy (XOR of all function selectors). * * Computed from the interfaces themselves rather than hardcoded. `type(IRule).interfaceId` alone - * covers only `canReturnTransferRestrictionCode`, the single function `IRule` declares directly, so - * the flattened ID XORs in every parent of the hierarchy. `IRuleEngineERC1404` contributes nothing - * of its own — it declares no function, and its `type(...).interfaceId` is `0x00000000` — so it does - * not appear below; its parents do. - * - * The value is unchanged from the hardcoded literal it replaces, and is pinned by the tests against - * both the flattened `IRuleAllFunctions` helper and the literal wire value. + * covers only the two functions `IRule` declares directly (the 4-argument `transferred` and + * `canReturnTransferRestrictionCode`), so the flattened ID XORs in every parent of the hierarchy. + * Pinned by the tests against the flattened `IRuleAllFunctions` helper and the literal wire value. */ library RuleInterfaceId { /** - * @notice ERC-165 interface ID advertised by every rule usable by the RuleEngine. - * @dev Flattened over: `IRule` (canReturnTransferRestrictionCode), `IRuleEngine` - * (transferred with spender), `IERC7551Compliance` (canTransferFrom), `IERC3643ComplianceRead` - * (canTransfer), `IERC3643IComplianceContract` (transferred), `IERC1404` - * (detectTransferRestriction, messageForTransferRestriction), `IERC1404Extend` - * (detectTransferRestrictionFrom) and `IERC165` (supportsInterface). Equals `0x2497d6cb`. + * @notice ERC-165 interface ID every rule must advertise to be accepted by the RuleEngine. + * @dev Flattened over: `IRule` (4-argument transferred, canReturnTransferRestrictionCode), + * `IERC3643IComplianceContract` (3-argument transferred), `IERC1404` (detectTransferRestriction, + * messageForTransferRestriction), `IERC1404Extend` (detectTransferRestrictionFrom) and `IERC165` + * (supportsInterface). Equals `0xb1a69752`. */ - bytes4 public constant IRULE_INTERFACE_ID = - type(IRule).interfaceId ^ type(IRuleEngine).interfaceId ^ type(IERC7551Compliance).interfaceId - ^ type(IERC3643ComplianceRead).interfaceId ^ type(IERC3643IComplianceContract).interfaceId + bytes4 public constant IRULE_INTERFACE_ID = type(IRule).interfaceId ^ type(IERC3643IComplianceContract).interfaceId ^ type(IERC1404).interfaceId ^ type(IERC1404Extend).interfaceId ^ type(IERC165).interfaceId; + + /** + * @notice Legacy ERC-165 interface ID of `IRule`, before v3.0.0-rc7 narrowed it. + * @dev The current ID plus `canTransfer` ({IERC3643ComplianceRead}) and `canTransferFrom` + * ({IERC7551Compliance}), which the engine never calls on a rule. Equals `0x2497d6cb`. Still accepted by + * the engine, so rules built against the previous interface keep working. + */ + bytes4 public constant IRULE_LEGACY_INTERFACE_ID = + IRULE_INTERFACE_ID ^ type(IERC3643ComplianceRead).interfaceId ^ type(IERC7551Compliance).interfaceId; } diff --git a/src/modules/library/RulesManagementModuleInvariantStorage.sol b/src/modules/library/RulesManagementModuleInvariantStorage.sol index 19432d39..62deb46c 100644 --- a/src/modules/library/RulesManagementModuleInvariantStorage.sol +++ b/src/modules/library/RulesManagementModuleInvariantStorage.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.20; +pragma solidity ^0.8.27; import {IRule} from "../../interfaces/IRule.sol"; @@ -20,7 +20,6 @@ abstract contract RulesManagementModuleInvariantStorage { error RuleEngine_RulesManagementModule_RuleAlreadyExists(); error RuleEngine_RulesManagementModule_RuleDoNotMatch(); error RuleEngine_RulesManagementModule_ArrayIsEmpty(); - error RuleEngine_RulesManagementModule_OperationNotSuccessful(); error RuleEngine_RulesManagementModule_MaxRulesExceeded(uint256 maxRules); error RuleEngine_RulesManagementModule_MaxRulesZeroNotAllowed(); error RuleEngine_RulesManagementModule_RuleAccountCannotReceivePrivileges(); diff --git a/src/modules/library/RulesManagementModuleRolesStorage.sol b/src/modules/library/RulesManagementModuleRolesStorage.sol index 9da0ade6..4c8c10a9 100644 --- a/src/modules/library/RulesManagementModuleRolesStorage.sol +++ b/src/modules/library/RulesManagementModuleRolesStorage.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.20; +pragma solidity ^0.8.27; /** * @title RulesManagementModuleRolesStorage diff --git a/src/modules/library/TokenBindingModuleInvariantStorage.sol b/src/modules/library/TokenBindingModuleInvariantStorage.sol index e96f83d4..e99e4857 100644 --- a/src/modules/library/TokenBindingModuleInvariantStorage.sol +++ b/src/modules/library/TokenBindingModuleInvariantStorage.sol @@ -1,6 +1,6 @@ // SPDX-License-Identifier: MPL-2.0 -pragma solidity ^0.8.20; +pragma solidity ^0.8.27; /** * @title TokenBindingModuleInvariantStorage diff --git a/test/ERC3643Real/ERC3643RealTokenRuleEngine.t.sol b/test/ERC3643Real/ERC3643RealTokenRuleEngine.t.sol new file mode 100644 index 00000000..44c7b5fd --- /dev/null +++ b/test/ERC3643Real/ERC3643RealTokenRuleEngine.t.sol @@ -0,0 +1,262 @@ +// SPDX-License-Identifier: MPL-2.0 +pragma solidity 0.8.30; + +import {Test} from "forge-std/Test.sol"; +import {IAccessControl} from "@openzeppelin/contracts/access/IAccessControl.sol"; +import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import {ComplianceNotFollowed, Token, TransferNotPossible} from "ERC3643/token/Token.sol"; +import {RuleEngine} from "src/deployment/accessControl/RuleEngine.sol"; +import {IRule} from "src/interfaces/IRule.sol"; +import {RuleWhitelistMock} from "src/mocks/rules/validation/RuleWhitelistMock.sol"; +import {TokenBindingModuleInvariantStorage} from "src/modules/library/TokenBindingModuleInvariantStorage.sol"; +import {IdentityRegistryStub} from "./IdentityRegistryStub.sol"; +import {SupplyCapProbeRule} from "./SupplyCapProbeRule.sol"; + +/** + * @title ERC3643RealTokenRuleEngineTest + * @notice Integration tests against the REAL vendored ERC-3643 token (`lib/ERC-3643`, T-REX 4.2.0-beta1). + * `test/RuleEngine/ERC3643TokenIntegration.t.sol` drives `ERC3643TokenMock`, whose compliance calls are + * transcribed from `Token.sol`; this suite deploys the genuine `Token`, so a change upstream in when or how the + * token calls compliance breaks these tests instead of silently invalidating the mock. + * @dev Built by the `erc3643` profile, because `Token.sol` pins `pragma solidity 0.8.30` exactly: + * + * FOUNDRY_PROFILE=erc3643 forge test + * + * `test/ERC3643Real/**` is in the default profile's `skip` list, so a plain `forge test` is unaffected. + */ +contract ERC3643RealTokenRuleEngineTest is Test, TokenBindingModuleInvariantStorage { + address constant ADMIN = address(1); + address constant AGENT = address(10); + address constant ALICE = address(11); + address constant BOB = address(12); + address constant CAROL = address(13); + + IdentityRegistryStub registry; + RuleWhitelistMock whitelist; + RuleEngine engine; + Token token; + + function setUp() public { + registry = new IdentityRegistryStub(); + // Everyone is identity-verified, so every rejection below comes from the RuleEngine. + registry.setVerified(ALICE, true); + registry.setVerified(BOB, true); + registry.setVerified(CAROL, true); + + vm.startPrank(ADMIN); + engine = new RuleEngine(ADMIN, address(0)); + whitelist = new RuleWhitelistMock(ADMIN, address(0)); + address[] memory listed = new address[](3); + listed[0] = ALICE; + listed[1] = BOB; + // The mint pre-check is canTransfer(address(0), to, amount) and the whitelist treats the zero address + // as an ordinary participant, so it must be listed for mint and burn to pass. + listed[2] = address(0); + whitelist.addAddressesToTheList(listed); + engine.addRule(IRule(address(whitelist))); + vm.stopPrank(); + + token = new Token(); + // `init` calls setCompliance, which self-binds the token: approval is required first. + vm.prank(ADMIN); + engine.setTokenSelfBindingApproval(address(token), true); + token.init(address(registry), address(engine), "Real ERC-3643", "R3643", 0, address(0)); + + // `init` leaves the token paused and makes this contract its owner. + token.addAgent(AGENT); + vm.prank(AGENT); + token.unpause(); + } + + /* ============ Binding ============ */ + + /// @notice `init` -> `setCompliance` binds the real token to the engine through self-binding. + function testInitSelfBindsTheToken() public view { + assertTrue(engine.isTokenBound(address(token)), "token should be bound after init"); + assertEq(engine.getTokenBound(), address(token)); + assertEq(address(token.compliance()), address(engine)); + } + + /// @notice Without self-binding approval, `init` reverts on the engine's binding manager check. + function testInitRevertsWithoutSelfBindingApproval() public { + vm.prank(ADMIN); + RuleEngine engine2 = new RuleEngine(ADMIN, address(0)); + Token token2 = new Token(); + + vm.expectRevert( + abi.encodeWithSelector( + IAccessControl.AccessControlUnauthorizedAccount.selector, + address(token2), + engine2.COMPLIANCE_MANAGER_ROLE() + ) + ); + token2.init(address(registry), address(engine2), "Real ERC-3643", "R3643", 0, address(0)); + } + + /// @notice Re-pointing the token at a second engine unbinds it from the first (`unbindToken(this)`). + function testSetComplianceMovesTheBinding() public { + vm.startPrank(ADMIN); + RuleEngine engine2 = new RuleEngine(ADMIN, address(0)); + engine2.setTokenSelfBindingApproval(address(token), true); + vm.stopPrank(); + + token.setCompliance(address(engine2)); + + assertFalse(engine.isTokenBound(address(token)), "old engine should no longer be bound"); + assertTrue(engine2.isTokenBound(address(token)), "new engine should be bound"); + } + + /* ============ Mint / burn: created / destroyed ============ */ + + /// @notice Mint is pre-checked with canTransfer(address(0), ...) then notified through created(), which the + /// engine forwards to the rules as the 3-argument transferred(address(0), to, value). + function testMintRoutesThroughCreated() public { + vm.expectCall(address(engine), abi.encodeCall(engine.canTransfer, (address(0), BOB, 25))); + vm.expectCall(address(engine), abi.encodeCall(engine.created, (BOB, 25))); + vm.expectCall( + address(whitelist), abi.encodeWithSignature("transferred(address,address,uint256)", address(0), BOB, 25) + ); + + vm.prank(AGENT); + token.mint(BOB, 25); + + assertEq(token.balanceOf(BOB), 25); + } + + /// @notice A mint to an address the rule rejects fails at the token's pre-check. + function testMintToUnlistedAddressReverts() public { + vm.prank(AGENT); + vm.expectRevert(ComplianceNotFollowed.selector); + token.mint(CAROL, 1); + } + + /// @notice If address(0) is not listed, the whitelist blocks every mint (from == address(0)). + function testMintIsBlockedWhenZeroAddressNotListed() public { + vm.prank(ADMIN); + whitelist.removeAddressFromTheList(address(0)); + + vm.prank(AGENT); + vm.expectRevert(ComplianceNotFollowed.selector); + token.mint(ALICE, 1); + } + + /// @notice Burn is notified through destroyed(), forwarded as transferred(from, address(0), value). + function testBurnRoutesThroughDestroyed() public { + vm.startPrank(AGENT); + token.mint(ALICE, 100); + + vm.expectCall(address(engine), abi.encodeCall(engine.destroyed, (ALICE, 40))); + vm.expectCall( + address(whitelist), abi.encodeWithSignature("transferred(address,address,uint256)", ALICE, address(0), 40) + ); + token.burn(ALICE, 40); + vm.stopPrank(); + + assertEq(token.balanceOf(ALICE), 60); + } + + /* ============ Transfers: transferred(from, to, value) ============ */ + + /// @notice A transfer between listed addresses succeeds and notifies the engine with no spender. + function testTransferRoutesThroughThreeArgumentTransferred() public { + vm.prank(AGENT); + token.mint(ALICE, 100); + + vm.expectCall(address(engine), abi.encodeWithSignature("transferred(address,address,uint256)", ALICE, BOB, 40)); + vm.prank(ALICE); + token.transfer(BOB, 40); + + assertEq(token.balanceOf(ALICE), 60); + assertEq(token.balanceOf(BOB), 40); + } + + /// @notice transferFrom also uses the 3-argument overload: ERC-3643 never forwards the spender. + function testTransferFromCarriesNoSpender() public { + vm.prank(AGENT); + token.mint(ALICE, 100); + vm.prank(ALICE); + token.approve(CAROL, 30); + + // CAROL (the spender) is not whitelisted: the transfer still passes, because the engine never sees her. + vm.expectCall(address(engine), abi.encodeWithSignature("transferred(address,address,uint256)", ALICE, BOB, 30)); + vm.prank(CAROL); + token.transferFrom(ALICE, BOB, 30); + + assertEq(token.balanceOf(BOB), 30); + } + + /// @notice A transfer to an address the rule rejects fails at the token's canTransfer pre-check. + function testTransferToUnlistedAddressReverts() public { + vm.prank(AGENT); + token.mint(ALICE, 100); + + vm.prank(ALICE); + vm.expectRevert(TransferNotPossible.selector); + token.transfer(CAROL, 10); + } + + /// @notice Unlike CMTAT, T-REX's forcedTransfer notifies compliance, so a rule can block it: the token skips + /// the canTransfer pre-check but the engine's transferred() still runs the rules and reverts. + function testForcedTransferNotifiesComplianceAndCanBeBlocked() public { + vm.startPrank(AGENT); + token.mint(ALICE, 100); + + vm.expectRevert( + abi.encodeWithSelector( + RuleWhitelistMock.RuleWhitelist_InvalidTransfer.selector, + ALICE, + CAROL, + 10, + whitelist.CODE_ADDRESS_TO_NOT_WHITELISTED() + ) + ); + token.forcedTransfer(ALICE, CAROL, 10); + + vm.expectCall(address(engine), abi.encodeWithSignature("transferred(address,address,uint256)", ALICE, BOB, 10)); + token.forcedTransfer(ALICE, BOB, 10); + vm.stopPrank(); + + assertEq(token.balanceOf(BOB), 10); + } + + /* ============ Access ============ */ + + /// @notice Only the bound token may call the compliance callbacks. + function testUnboundCallerCannotCallCallbacks() public { + vm.startPrank(CAROL); + vm.expectRevert(TokenBinding_UnauthorizedCaller.selector); + engine.transferred(ALICE, BOB, 1); + vm.expectRevert(TokenBinding_UnauthorizedCaller.selector); + engine.created(BOB, 1); + vm.expectRevert(TokenBinding_UnauthorizedCaller.selector); + engine.destroyed(ALICE, 1); + vm.stopPrank(); + } + + /* ============ Notification order ============ */ + + /// @notice T-REX notifies compliance AFTER the state change (`_mint` then `created`). A CMTAT-style cap + /// (`totalSupply() + value <= cap`) passes the pre-check, which runs before `_mint`, but counts the amount + /// twice in `created`, and the mint reverts although it reaches the cap exactly. + /// See doc/technical/RuleEngine-with-ERC3643.md section 4.9. + function testComplianceIsNotifiedAfterTheMint() public { + SupplyCapProbeRule probe = new SupplyCapProbeRule(IERC20(address(token)), 100); + vm.prank(ADMIN); + engine.addRule(IRule(address(probe))); + + // Before the mint, the engine's view projects the amount once: 0 + 100 <= 100. + assertTrue(engine.canTransfer(address(0), BOB, 100), "pre-check should accept a mint up to the cap"); + + // In created(), totalSupply() already includes the 100: 100 + 100 > 100. + vm.prank(AGENT); + vm.expectRevert( + abi.encodeWithSelector(SupplyCapProbeRule.SupplyCapProbeRule_CapExceeded.selector, 100, 100, 100) + ); + token.mint(BOB, 100); + + // Half the cap is the effective limit on T-REX for such a rule. + vm.prank(AGENT); + token.mint(BOB, 50); + assertEq(token.totalSupply(), 50); + } +} diff --git a/test/ERC3643Real/IdentityRegistryStub.sol b/test/ERC3643Real/IdentityRegistryStub.sol new file mode 100644 index 00000000..81ed8318 --- /dev/null +++ b/test/ERC3643Real/IdentityRegistryStub.sol @@ -0,0 +1,33 @@ +// SPDX-License-Identifier: MPL-2.0 +pragma solidity 0.8.30; + +/** + * @title IdentityRegistryStub + * @notice Minimal identity registry for the real ERC-3643 token: answers `isVerified` from a flag set by the + * test, so every rejection observed in the suite comes from the RuleEngine rather than from identity checks. + * @dev `Token` stores the registry as `IERC3643IdentityRegistry` but only calls `isVerified` on the transfer, + * mint and forced-transfer paths exercised here. `recoveryAddress` would also need `contains` / + * `registerIdentity` / `deleteIdentity`; it is not exercised. + * WARNING: test-only. No access control. + */ +contract IdentityRegistryStub { + mapping(address => bool) private _verified; + + /** + * @notice Sets the verification flag of a wallet. + * @param wallet The wallet. + * @param verified True to mark the wallet as verified. + */ + function setVerified(address wallet, bool verified) external { + _verified[wallet] = verified; + } + + /** + * @notice Returns whether a wallet is verified. + * @param wallet The wallet. + * @return True when the wallet is verified. + */ + function isVerified(address wallet) external view returns (bool) { + return _verified[wallet]; + } +} diff --git a/test/ERC3643Real/SupplyCapProbeRule.sol b/test/ERC3643Real/SupplyCapProbeRule.sol new file mode 100644 index 00000000..0e089c3c --- /dev/null +++ b/test/ERC3643Real/SupplyCapProbeRule.sol @@ -0,0 +1,86 @@ +// SPDX-License-Identifier: MPL-2.0 +pragma solidity 0.8.30; + +import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol"; +import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; +import {IRule} from "src/interfaces/IRule.sol"; +import {RuleInterfaceId} from "src/modules/library/RuleInterfaceId.sol"; + +/** + * @title SupplyCapProbeRule + * @notice CMTAT-style supply cap (`totalSupply() + value <= cap` on mint), used to observe *when* the real + * ERC-3643 token notifies compliance. CMTAT calls the engine before the mint, so the check projects the + * pending amount once. T-REX calls `created` after `_mint`, so the same check counts the amount twice. + * @dev Test-only probe, not a production rule. + */ +contract SupplyCapProbeRule is IRule { + uint8 public constant CODE_CAP_EXCEEDED = 50; + + IERC20 public immutable TOKEN; + uint256 public immutable CAP; + + error SupplyCapProbeRule_CapExceeded(uint256 supply, uint256 value, uint256 cap); + + /** + * @param token_ The token whose supply is read. + * @param cap_ The maximum total supply. + */ + constructor(IERC20 token_, uint256 cap_) { + TOKEN = token_; + CAP = cap_; + } + + /* ============ State-changing ============ */ + + /// @dev See {IRule}. + function transferred(address from, address to, uint256 value) external view override { + _revertIfRestricted(from, to, value); + } + + /// @dev See {IRule}. + function transferred(address, address from, address to, uint256 value) external view override { + _revertIfRestricted(from, to, value); + } + + /* ============ View ============ */ + + /// @dev See {IRule}. + function canReturnTransferRestrictionCode(uint8 restrictionCode) external pure override returns (bool) { + return restrictionCode == CODE_CAP_EXCEEDED; + } + + /// @dev See {IRule}. + function messageForTransferRestriction(uint8 restrictionCode) external pure override returns (string memory) { + return restrictionCode == CODE_CAP_EXCEEDED ? "SupplyCapProbeRule: cap exceeded" : "No restriction"; + } + + /// @dev See {IRule}. + function detectTransferRestrictionFrom(address, address from, address to, uint256 value) + external + view + override + returns (uint8) + { + return detectTransferRestriction(from, to, value); + } + + /// @dev See {IERC165}. + function supportsInterface(bytes4 interfaceId) external pure override returns (bool) { + return interfaceId == RuleInterfaceId.IRULE_INTERFACE_ID || interfaceId == type(IERC165).interfaceId; + } + + /// @dev See {IRule}. + function detectTransferRestriction(address from, address, uint256 value) public view override returns (uint8) { + if (from == address(0) && TOKEN.totalSupply() + value > CAP) { + return CODE_CAP_EXCEEDED; + } + return 0; + } + + function _revertIfRestricted(address from, address to, uint256 value) internal view virtual { + require( + detectTransferRestriction(from, to, value) == 0, + SupplyCapProbeRule_CapExceeded(TOKEN.totalSupply(), value, CAP) + ); + } +} diff --git a/test/HelperContract.sol b/test/HelperContract.sol index 4a62f936..7f2b95bf 100644 --- a/test/HelperContract.sol +++ b/test/HelperContract.sol @@ -9,7 +9,7 @@ import {RuleEngineInvariantStorage} from "src/modules/library/RuleEngineInvarian import {RulesManagementModuleInvariantStorage} from "src/modules/library/RulesManagementModuleInvariantStorage.sol"; import {RulesManagementModuleRolesStorage} from "src/modules/library/RulesManagementModuleRolesStorage.sol"; // RuleEngine -import {RuleEngine} from "src/deployment/RuleEngine.sol"; +import {RuleEngine} from "src/deployment/accessControl/RuleEngine.sol"; // forge-lint: disable-next-line(unused-import) import {RulesManagementModule} from "src/RuleEngineBase.sol"; // forge-lint: disable-next-line(unused-import) diff --git a/test/HelperContractOwnable.sol b/test/HelperContractOwnable.sol index ee1acced..d776728b 100644 --- a/test/HelperContractOwnable.sol +++ b/test/HelperContractOwnable.sol @@ -8,7 +8,7 @@ import {CMTATStandardStandalone} from "CMTAT/deployment/CMTATStandardStandalone. import {RuleEngineInvariantStorage} from "src/modules/library/RuleEngineInvariantStorage.sol"; import {RulesManagementModuleInvariantStorage} from "src/modules/library/RulesManagementModuleInvariantStorage.sol"; // RuleEngineOwnable -import {RuleEngineOwnable} from "src/deployment/RuleEngineOwnable.sol"; +import {RuleEngineOwnable} from "src/deployment/ownable/RuleEngineOwnable.sol"; // forge-lint: disable-next-line(unused-import) import {RulesManagementModule} from "src/RuleEngineBase.sol"; // forge-lint: disable-next-line(unused-import) diff --git a/test/HelperContractOwnable2Step.sol b/test/HelperContractOwnable2Step.sol index a5ad93ae..fd95f1ac 100644 --- a/test/HelperContractOwnable2Step.sol +++ b/test/HelperContractOwnable2Step.sol @@ -1,7 +1,7 @@ //SPDX-License-Identifier: MPL-2.0 pragma solidity ^0.8.20; -import {RuleEngineOwnable2Step} from "src/deployment/RuleEngineOwnable2Step.sol"; +import {RuleEngineOwnable2Step} from "src/deployment/ownable/RuleEngineOwnable2Step.sol"; import {RuleConditionalTransferLightMock} from "src/mocks/rules/operation/RuleConditionalTransferLightMock.sol"; /** diff --git a/test/RuleEngine/AccessControl/RuleEngineAccessControl.sol b/test/RuleEngine/AccessControl/RuleEngineAccessControl.sol index 4cc83a19..654bb926 100644 --- a/test/RuleEngine/AccessControl/RuleEngineAccessControl.sol +++ b/test/RuleEngine/AccessControl/RuleEngineAccessControl.sol @@ -16,7 +16,7 @@ contract RuleEngineTest is Test, HelperContract { function setUp() public { ruleWhitelist = new RuleWhitelistMock(WHITELIST_OPERATOR_ADDRESS, ZERO_ADDRESS); vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - ruleEngineMock = new RuleEngine(RULE_ENGINE_OPERATOR_ADDRESS, ZERO_ADDRESS, ZERO_ADDRESS); + ruleEngineMock = new RuleEngine(RULE_ENGINE_OPERATOR_ADDRESS, ZERO_ADDRESS); resUint256 = ruleEngineMock.rulesCount(); vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); diff --git a/test/RuleEngine/AccessControl/RuleEngineAccessControlOZ.t.sol b/test/RuleEngine/AccessControl/RuleEngineAccessControlOZ.t.sol index 02f4223a..f2ed3594 100644 --- a/test/RuleEngine/AccessControl/RuleEngineAccessControlOZ.t.sol +++ b/test/RuleEngine/AccessControl/RuleEngineAccessControlOZ.t.sol @@ -14,7 +14,7 @@ contract RuleEngineTest is Test, HelperContract, AccessControl { function setUp() public { ruleWhitelist = new RuleWhitelistMock(WHITELIST_OPERATOR_ADDRESS, ZERO_ADDRESS); vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - ruleEngineMock = new RuleEngine(RULE_ENGINE_OPERATOR_ADDRESS, ZERO_ADDRESS, ZERO_ADDRESS); + ruleEngineMock = new RuleEngine(RULE_ENGINE_OPERATOR_ADDRESS, ZERO_ADDRESS); resUint256 = ruleEngineMock.rulesCount(); vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); diff --git a/test/RuleEngine/ERC3643Compliance.t.sol b/test/RuleEngine/ERC3643Compliance.t.sol index 1457b472..ee5d1a80 100644 --- a/test/RuleEngine/ERC3643Compliance.t.sol +++ b/test/RuleEngine/ERC3643Compliance.t.sol @@ -1,6 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.20; +import {ITokenBindingExtended} from "src/interfaces/ITokenBindingExtended.sol"; import {Test} from "forge-std/Test.sol"; import {Vm} from "forge-std/Vm.sol"; // forge-lint: disable-next-line(unaliased-plain-import) @@ -68,7 +69,7 @@ contract RuleEngineTest is Test, HelperContract { function setUp() public { // Deploy RuleEngine with admin - ruleEngine = new RuleEngine(admin, ZERO_ADDRESS, ZERO_ADDRESS); + ruleEngine = new RuleEngine(admin, ZERO_ADDRESS); // Deploy multiple mock tokens token1 = new ERC3643MockToken(address(ruleEngine)); @@ -268,6 +269,18 @@ contract RuleEngineTest is Test, HelperContract { ruleEngine.setTokenSelfBindingApproval(address(token1), true); } + function testSetTokenSelfBindingApprovalEmitsEvent() public { + vm.expectEmit(true, false, false, true, address(ruleEngine)); + emit ITokenBindingExtended.TokenSelfBindingApprovalSet(address(0x7070), true); + vm.prank(operator); + ruleEngine.setTokenSelfBindingApproval(address(0x7070), true); + + vm.expectEmit(true, false, false, true, address(ruleEngine)); + emit ITokenBindingExtended.TokenSelfBindingApprovalSet(address(0x7070), false); + vm.prank(operator); + ruleEngine.setTokenSelfBindingApproval(address(0x7070), false); + } + function testCannotSetTokenSelfBindingApprovalForZeroAddress() public { vm.expectRevert(TokenBindingModuleInvariantStorage.TokenBinding_InvalidTokenAddress.selector); vm.prank(operator); @@ -388,10 +401,12 @@ contract RuleEngineTest is Test, HelperContract { ruleEngine.bindTokens(tokens); } + /// @notice Batch binding is atomic on purpose (rc7 code-quality review `C-3`): one token already bound + /// reverts the whole batch, including the tokens bound before it in the same call. function testCannotBindTokensBatchWithAlreadyBoundToken() public { address[] memory tokens = new address[](2); - tokens[0] = address(token1); - tokens[1] = address(token2); + tokens[0] = address(token2); + tokens[1] = address(token1); vm.prank(operator); ruleEngine.bindToken(address(token1)); @@ -399,6 +414,23 @@ contract RuleEngineTest is Test, HelperContract { vm.expectRevert(TokenBindingModuleInvariantStorage.TokenBinding_TokenAlreadyBound.selector); vm.prank(operator); ruleEngine.bindTokens(tokens); + + assertFalse(ruleEngine.isTokenBound(address(token2)), "the token before the failing one is rolled back"); + } + + /// @notice A token listed twice in one batch reverts on its second occurrence, and the whole batch rolls back. + function testCannotBindTokensBatchWithDuplicateToken() public { + address[] memory tokens = new address[](3); + tokens[0] = address(token1); + tokens[1] = address(token2); + tokens[2] = address(token1); + + vm.expectRevert(TokenBindingModuleInvariantStorage.TokenBinding_TokenAlreadyBound.selector); + vm.prank(operator); + ruleEngine.bindTokens(tokens); + + assertFalse(ruleEngine.isTokenBound(address(token1))); + assertFalse(ruleEngine.isTokenBound(address(token2))); } function testCannotUnbindTokensBatchWithTokenNotBound() public { @@ -412,6 +444,23 @@ contract RuleEngineTest is Test, HelperContract { vm.expectRevert(TokenBindingModuleInvariantStorage.TokenBinding_TokenNotBound.selector); vm.prank(operator); ruleEngine.unbindTokens(tokens); + + assertTrue(ruleEngine.isTokenBound(address(token1)), "the token before the failing one stays bound"); + } + + /// @notice An empty batch is a no-op: no revert, no event, no state change (rc7 code-quality review `C-3`). + function testEmptyBindAndUnbindBatchesAreNoOps() public { + address[] memory empty = new address[](0); + uint256 before = ruleEngine.getTokenBounds().length; + + vm.recordLogs(); + vm.startPrank(operator); + ruleEngine.bindTokens(empty); + ruleEngine.unbindTokens(empty); + vm.stopPrank(); + + assertEq(vm.getRecordedLogs().length, 0); + assertEq(ruleEngine.getTokenBounds().length, before); } function testCannotCreatedIfNotBound() public { @@ -430,7 +479,7 @@ contract RuleEngineTest is Test, HelperContract { } function testTokenSetComplianceCanMigrateBetweenRuleEngines() public { - RuleEngine ruleEngine2 = new RuleEngine(admin, ZERO_ADDRESS, ZERO_ADDRESS); + RuleEngine ruleEngine2 = new RuleEngine(admin, ZERO_ADDRESS); ERC3643MockTokenWithSetCompliance trexLikeToken = new ERC3643MockTokenWithSetCompliance(user1); vm.startPrank(admin); diff --git a/test/RuleEngine/ERC3643TokenIntegration.t.sol b/test/RuleEngine/ERC3643TokenIntegration.t.sol index 0e8f2220..66ca4d44 100644 --- a/test/RuleEngine/ERC3643TokenIntegration.t.sol +++ b/test/RuleEngine/ERC3643TokenIntegration.t.sol @@ -3,7 +3,8 @@ pragma solidity ^0.8.20; import {Test} from "forge-std/Test.sol"; -import {RuleEngine} from "src/deployment/RuleEngine.sol"; +import {IAccessControl} from "@openzeppelin/contracts/access/IAccessControl.sol"; +import {RuleEngine} from "src/deployment/accessControl/RuleEngine.sol"; import {ERC3643TokenMock} from "src/mocks/ERC3643TokenMock.sol"; import {RuleWhitelistMock} from "src/mocks/rules/validation/RuleWhitelistMock.sol"; import {RuleMintAllowanceMock} from "src/mocks/rules/operation/RuleMintAllowanceMock.sol"; @@ -13,7 +14,8 @@ import {TokenBindingModuleInvariantStorage} from "src/modules/library/TokenBindi /** * @title ERC3643TokenIntegrationTest * @notice Drives the RuleEngine through the ERC-3643 entry points, using a token whose compliance - * interaction is modelled on `Token.sol` from the reference implementation in `lib/ERC-3643` (4.1.3). + * interaction is modelled on `Token.sol` from the ERC-3643 reference implementation (T-REX 4.1.3). The real + * token (T-REX 4.2.0-beta1, `lib/ERC-3643`) is exercised by `test/ERC3643Real/` under `FOUNDRY_PROFILE=erc3643`. * @dev Covers the entry points an ERC-3643 token actually uses: the `setCompliance` self-binding * dance, `transferred(from, to, value)` for transfers, and `created` / `destroyed` for mint and * burn. An ERC-3643 token never reaches the 4-argument `transferred(spender, ...)` overload, which @@ -31,7 +33,7 @@ contract ERC3643TokenIntegrationTest is Test, TokenBindingModuleInvariantStorage function setUp() public { vm.startPrank(ADMIN); - engine = new RuleEngine(ADMIN, address(0), address(0)); + engine = new RuleEngine(ADMIN, address(0)); token = new ERC3643TokenMock(); whitelist = new RuleWhitelistMock(ADMIN, address(0)); @@ -63,7 +65,7 @@ contract ERC3643TokenIntegrationTest is Test, TokenBindingModuleInvariantStorage /// @notice Re-pointing the token at a second engine unbinds it from the first. function testSetComplianceUnbindsThePreviousEngine() public { vm.startPrank(ADMIN); - RuleEngine engine2 = new RuleEngine(ADMIN, address(0), address(0)); + RuleEngine engine2 = new RuleEngine(ADMIN, address(0)); engine2.setTokenSelfBindingApproval(address(token), true); vm.stopPrank(); @@ -76,10 +78,16 @@ contract ERC3643TokenIntegrationTest is Test, TokenBindingModuleInvariantStorage /// @notice Without self-binding approval the token cannot bind itself. function testSetComplianceRevertsWithoutSelfBindingApproval() public { vm.prank(ADMIN); - RuleEngine engine2 = new RuleEngine(ADMIN, address(0), address(0)); + RuleEngine engine2 = new RuleEngine(ADMIN, address(0)); ERC3643TokenMock token2 = new ERC3643TokenMock(); - vm.expectRevert(); + vm.expectRevert( + abi.encodeWithSelector( + IAccessControl.AccessControlUnauthorizedAccount.selector, + address(token2), + engine2.COMPLIANCE_MANAGER_ROLE() + ) + ); token2.setCompliance(address(engine2)); } @@ -101,7 +109,7 @@ contract ERC3643TokenIntegrationTest is Test, TokenBindingModuleInvariantStorage token.mint(ALICE, 100); vm.prank(ALICE); - vm.expectRevert(); + vm.expectRevert(ERC3643TokenMock.ERC3643TokenMock_ComplianceNotFollowed.selector); token.transfer(CAROL, 10); } @@ -147,7 +155,7 @@ contract ERC3643TokenIntegrationTest is Test, TokenBindingModuleInvariantStorage */ function testMintIsBlockedWhenZeroAddressNotListed() public { vm.startPrank(ADMIN); - RuleEngine engine2 = new RuleEngine(ADMIN, address(0), address(0)); + RuleEngine engine2 = new RuleEngine(ADMIN, address(0)); RuleWhitelistMock whitelist2 = new RuleWhitelistMock(ADMIN, address(0)); address[] memory listed = new address[](1); listed[0] = BOB; // real holder only, zero address deliberately omitted diff --git a/test/RuleEngine/IRuleInterfaceId.t.sol b/test/RuleEngine/IRuleInterfaceId.t.sol index b97f30e1..3c972af0 100644 --- a/test/RuleEngine/IRuleInterfaceId.t.sol +++ b/test/RuleEngine/IRuleInterfaceId.t.sol @@ -33,7 +33,7 @@ contract IRuleInterfaceIdTest is Test { bytes4 iRuleId = helper.getIRuleInterfaceId(); bytes4 constant_ = helper.getRuleInterfaceIdConstant(); - // type(IRule).interfaceId only covers canReturnTransferRestrictionCode + // type(IRule).interfaceId only covers the two functions IRule declares directly assertTrue(iRuleId != constant_, "type(IRule).interfaceId should differ from full IRule ID"); } @@ -42,30 +42,17 @@ contract IRuleInterfaceIdTest is Test { bytes4 allFunctionsId = helper.getIRuleAllFunctionsInterfaceId(); bytes4 constant_ = helper.getRuleInterfaceIdConstant(); - emit log_named_bytes32("type(IRule).interfaceId (only canReturnTransferRestrictionCode)", bytes32(iRuleId)); + emit log_named_bytes32("type(IRule).interfaceId (own functions only)", bytes32(iRuleId)); emit log_named_bytes32("type(IRuleAllFunctions).interfaceId (full XOR)", bytes32(allFunctionsId)); emit log_named_bytes32("RuleInterfaceId.IRULE_INTERFACE_ID constant", bytes32(constant_)); - ( - bytes4 iRule, - bytes4 iRuleEngineERC1404, - bytes4 iRuleEngine, - bytes4 iERC1404, - bytes4 iERC1404Extend, - bytes4 iERC3643ComplianceRead, - bytes4 iERC3643IComplianceContract, - bytes4 iERC7551Compliance, - bytes4 iERC165 - ) = helper.getParentInterfaceIds(); + (bytes4 iRule, bytes4 iERC1404, bytes4 iERC1404Extend, bytes4 iERC3643IComplianceContract, bytes4 iERC165) = + helper.getParentInterfaceIds(); emit log_named_bytes32("IRule", bytes32(iRule)); - emit log_named_bytes32("IRuleEngineERC1404", bytes32(iRuleEngineERC1404)); - emit log_named_bytes32("IRuleEngine", bytes32(iRuleEngine)); emit log_named_bytes32("IERC1404", bytes32(iERC1404)); emit log_named_bytes32("IERC1404Extend", bytes32(iERC1404Extend)); - emit log_named_bytes32("IERC3643ComplianceRead", bytes32(iERC3643ComplianceRead)); emit log_named_bytes32("IERC3643IComplianceContract", bytes32(iERC3643IComplianceContract)); - emit log_named_bytes32("IERC7551Compliance", bytes32(iERC7551Compliance)); emit log_named_bytes32("IERC165", bytes32(iERC165)); } @@ -77,7 +64,7 @@ contract IRuleInterfaceIdTest is Test { * `supportsInterface` answers. These literals must never change without a major version. */ function testInterfaceIdConstantsMatchTheirWireValues() public pure { - assertEq(RuleInterfaceId.IRULE_INTERFACE_ID, bytes4(0x2497d6cb), "IRule"); + assertEq(RuleInterfaceId.IRULE_INTERFACE_ID, bytes4(0xb1a69752), "IRule"); assertEq(ComplianceInterfaceId.ERC3643_COMPLIANCE_INTERFACE_ID, bytes4(0x3144991c), "IERC3643Compliance"); assertEq( ComplianceInterfaceId.ERC3643_COMPLIANCE_EXTENDED_INTERFACE_ID, @@ -88,6 +75,22 @@ contract IRuleInterfaceIdTest is Test { assertEq(ERC1404InterfaceId.IERC1404_INTERFACE_ID, bytes4(0xab84a5c8), "IERC1404"); } + /** + * @notice Pins the narrowing of `IRule` (rc7 code-quality review `I-1`): the ID no longer includes + * `canTransfer` (ERC-3643) and `canTransferFrom` (ERC-7551), which the engine never calls on a rule. + * The pre-narrowing ID `0x2497d6cb` is exactly the current one XOR those two selectors. + */ + function testIRuleIdExcludesTheComplianceReads() public pure { + bytes4 canTransfer = bytes4(keccak256("canTransfer(address,address,uint256)")); + bytes4 canTransferFrom = bytes4(keccak256("canTransferFrom(address,address,address,uint256)")); + assertEq(canTransfer, bytes4(0xe46638e6), "canTransfer selector"); + assertEq(canTransferFrom, bytes4(0x7157797f), "canTransferFrom selector"); + assertEq( + RuleInterfaceId.IRULE_INTERFACE_ID ^ canTransfer ^ canTransferFrom, bytes4(0x2497d6cb), "pre-rc7 IRule id" + ); + assertEq(RuleInterfaceId.IRULE_LEGACY_INTERFACE_ID, bytes4(0x2497d6cb), "legacy constant"); + } + /** * @notice Pins the reason the extended compliance ID is computed from {ITokenBindingExtended}. * @dev `IERC3643ComplianceExtended` declares no function of its own, so `type(...).interfaceId` diff --git a/test/RuleEngine/NoForwarder.t.sol b/test/RuleEngine/NoForwarder.t.sol new file mode 100644 index 00000000..51d1f9dc --- /dev/null +++ b/test/RuleEngine/NoForwarder.t.sol @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: MPL-2.0 +pragma solidity ^0.8.20; + +import {IAccessControl} from "@openzeppelin/contracts/access/IAccessControl.sol"; +import {RuleEngine} from "src/deployment/accessControl/RuleEngine.sol"; +import {NoForwarderTestBase} from "../utils/NoForwarderTestBase.sol"; + +/** + * @title NoForwarderTest + * @notice The RBAC `RuleEngine` has no ERC-2771 support. + */ +contract NoForwarderTest is NoForwarderTestBase { + function _deployEngine(address admin, address token) internal override returns (address) { + return address(new RuleEngine(admin, token)); + } + + function _managerRevertData(address caller) internal view override returns (bytes memory) { + return abi.encodeWithSelector( + IAccessControl.AccessControlUnauthorizedAccount.selector, + caller, + RuleEngine(engine).COMPLIANCE_MANAGER_ROLE() + ); + } +} diff --git a/test/RuleEngine/RuleAggregation.t.sol b/test/RuleEngine/RuleAggregation.t.sol new file mode 100644 index 00000000..9a1a7192 --- /dev/null +++ b/test/RuleEngine/RuleAggregation.t.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: MPL-2.0 +pragma solidity ^0.8.20; + +import {RuleEngine} from "src/deployment/accessControl/RuleEngine.sol"; +import {RuleAggregationTestBase} from "../utils/RuleAggregationTestBase.sol"; + +/** + * @title RuleAggregationTest + * @notice Rule aggregation tests for the RBAC `RuleEngine`. + */ +contract RuleAggregationTest is RuleAggregationTestBase { + function _deployEngine(address admin, address token) internal override returns (address) { + return address(new RuleEngine(admin, token)); + } +} diff --git a/test/RuleEngine/RuleEngineCoverage.t.sol b/test/RuleEngine/RuleEngineCoverage.t.sol index 373f7c5f..7e18d085 100644 --- a/test/RuleEngine/RuleEngineCoverage.t.sol +++ b/test/RuleEngine/RuleEngineCoverage.t.sol @@ -5,7 +5,6 @@ import {Test} from "forge-std/Test.sol"; // forge-lint: disable-next-line(unaliased-plain-import) import "../HelperContract.sol"; -import {RuleEngineExposed} from "src/mocks/RuleEngineExposed.sol"; import {RuleInvalidMock} from "src/mocks/RuleInvalidMock.sol"; import {ICompliance} from "src/mocks/ICompliance.sol"; import {IERC3643ComplianceExtendedSubset} from "src/mocks/IERC3643ComplianceExtendedSubset.sol"; @@ -15,11 +14,9 @@ import {ComplianceInterfaceId} from "src/modules/library/ComplianceInterfaceId.s import {ERC1404InterfaceId} from "src/modules/library/ERC1404InterfaceId.sol"; /** - * @title Coverage tests for RuleEngine (supportsInterface, _msgData, ERC-165 rule check) + * @title Coverage tests for RuleEngine (supportsInterface, ERC-165 rule check) */ contract RuleEngineCoverageTest is Test, HelperContract { - RuleEngineExposed public ruleEngineExposed; - // Known interface IDs bytes4 constant RULE_ENGINE_ID = 0x20c49ce7; bytes4 constant ERC1404_EXTEND_ID = 0x78a8de7d; @@ -27,8 +24,7 @@ contract RuleEngineCoverageTest is Test, HelperContract { bytes4 constant INVALID_ID = 0xffffffff; function setUp() public { - ruleEngineMock = new RuleEngine(RULE_ENGINE_OPERATOR_ADDRESS, ZERO_ADDRESS, ZERO_ADDRESS); - ruleEngineExposed = new RuleEngineExposed(RULE_ENGINE_OPERATOR_ADDRESS, ZERO_ADDRESS, ZERO_ADDRESS); + ruleEngineMock = new RuleEngine(RULE_ENGINE_OPERATOR_ADDRESS, ZERO_ADDRESS); } /*////////////////////////////////////////////////////////////// @@ -69,18 +65,6 @@ contract RuleEngineCoverageTest is Test, HelperContract { assertFalse(ruleEngineMock.supportsInterface(INVALID_ID)); } - /*////////////////////////////////////////////////////////////// - MSG DATA - //////////////////////////////////////////////////////////////*/ - - function testMsgDataReturnsCalldata() public view { - bytes memory data = ruleEngineExposed.exposedMsgData(); - // Should return the calldata (selector of exposedMsgData) - assertEq(data.length, 4); - // forge-lint: disable-next-line(unsafe-typecast) - assertEq(bytes4(data), ruleEngineExposed.exposedMsgData.selector); - } - /*////////////////////////////////////////////////////////////// ERC-165 RULE INTERFACE CHECK //////////////////////////////////////////////////////////////*/ diff --git a/test/RuleEngine/RuleEngineDeployment.t.sol b/test/RuleEngine/RuleEngineDeployment.t.sol index d380c613..21e359c6 100644 --- a/test/RuleEngine/RuleEngineDeployment.t.sol +++ b/test/RuleEngine/RuleEngineDeployment.t.sol @@ -4,7 +4,6 @@ pragma solidity ^0.8.20; import {Test} from "forge-std/Test.sol"; // forge-lint: disable-next-line(unaliased-plain-import) import "../HelperContract.sol"; -import {MinimalForwarderMock} from "CMTAT/mocks/MinimalForwarderMock.sol"; import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; import {IAccessControl} from "@openzeppelin/contracts/access/IAccessControl.sol"; import {IAccessControlEnumerable} from "@openzeppelin/contracts/access/extensions/IAccessControlEnumerable.sol"; @@ -25,24 +24,17 @@ contract RuleEngineTest is Test, HelperContract { function setUp() public {} function testRightDeployment() public { - // Arrange - vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - MinimalForwarderMock forwarder = new MinimalForwarderMock(); - forwarder.initialize(ERC2771ForwarderDomain); - // Act - ruleEngineMock = new RuleEngine(RULE_ENGINE_OPERATOR_ADDRESS, address(forwarder), ZERO_ADDRESS); + ruleEngineMock = new RuleEngine(RULE_ENGINE_OPERATOR_ADDRESS, ZERO_ADDRESS); // assert resBool = ruleEngineMock.hasRole(RULES_MANAGEMENT_ROLE, RULE_ENGINE_OPERATOR_ADDRESS); assertEq(resBool, true); - resBool = ruleEngineMock.isTrustedForwarder(address(forwarder)); - assertEq(resBool, true); } function testReturnZeroAddressForRule() public { // Arrange - ruleEngineMock = new RuleEngine(RULE_ENGINE_OPERATOR_ADDRESS, address(0x0), ZERO_ADDRESS); + ruleEngineMock = new RuleEngine(RULE_ENGINE_OPERATOR_ADDRESS, ZERO_ADDRESS); // Act resAddr = ruleEngineMock.rule(0); // Assert @@ -51,15 +43,15 @@ contract RuleEngineTest is Test, HelperContract { function testHasRightVersion() public { // Act - ruleEngineMock = new RuleEngine(RULE_ENGINE_OPERATOR_ADDRESS, address(0x0), ZERO_ADDRESS); + ruleEngineMock = new RuleEngine(RULE_ENGINE_OPERATOR_ADDRESS, ZERO_ADDRESS); // Assert - assertEq(ruleEngineMock.version(), "3.0.0"); + assertEq(ruleEngineMock.version(), "3.0.0-rc7"); } function testSupportsInterfaces() public { // Arrange - ruleEngineMock = new RuleEngine(RULE_ENGINE_OPERATOR_ADDRESS, address(0x0), ZERO_ADDRESS); + ruleEngineMock = new RuleEngine(RULE_ENGINE_OPERATOR_ADDRESS, ZERO_ADDRESS); // Act & Assert assertTrue(ruleEngineMock.supportsInterface(type(IERC165).interfaceId)); @@ -76,12 +68,8 @@ contract RuleEngineTest is Test, HelperContract { } function testCannotDeployContractifAdminAddressIsZero() public { - // Arrange - vm.prank(WHITELIST_OPERATOR_ADDRESS); - MinimalForwarderMock forwarder = new MinimalForwarderMock(); - forwarder.initialize(ERC2771ForwarderDomain); vm.expectRevert(RuleEngine_AdminWithAddressZeroNotAllowed.selector); // Act - ruleEngineMock = new RuleEngine(address(0x0), address(forwarder), ZERO_ADDRESS); + ruleEngineMock = new RuleEngine(address(0x0), ZERO_ADDRESS); } } diff --git a/test/RuleEngine/RuleEngineInvariant.t.sol b/test/RuleEngine/RuleEngineInvariant.t.sol new file mode 100644 index 00000000..14d35a78 --- /dev/null +++ b/test/RuleEngine/RuleEngineInvariant.t.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: MPL-2.0 +pragma solidity ^0.8.20; + +import {RuleEngine} from "src/deployment/accessControl/RuleEngine.sol"; +import {RuleEngineInvariantTestBase} from "../utils/RuleEngineInvariantTestBase.sol"; + +/** + * @title RuleEngineInvariantTest + * @notice Invariant tests over the rule set and the bound tokens for the RBAC `RuleEngine`. + */ +contract RuleEngineInvariantTest is RuleEngineInvariantTestBase { + function _deployEngine(address admin) internal override returns (address) { + return address(new RuleEngine(admin, address(0))); + } +} diff --git a/test/RuleEngine/RuleEngineMaxRulesEvent.t.sol b/test/RuleEngine/RuleEngineMaxRulesEvent.t.sol index 4947a5e9..7012bb70 100644 --- a/test/RuleEngine/RuleEngineMaxRulesEvent.t.sol +++ b/test/RuleEngine/RuleEngineMaxRulesEvent.t.sol @@ -2,9 +2,12 @@ pragma solidity ^0.8.20; import {Test} from "forge-std/Test.sol"; -import {RuleEngine} from "src/deployment/RuleEngine.sol"; -import {RuleEngineOwnable} from "src/deployment/RuleEngineOwnable.sol"; -import {RuleEngineOwnable2Step} from "src/deployment/RuleEngineOwnable2Step.sol"; +import {RuleEngine} from "src/deployment/accessControl/RuleEngine.sol"; +import {RuleEngine2771} from "src/deployment/accessControl/RuleEngine2771.sol"; +import {RuleEngineOwnable} from "src/deployment/ownable/RuleEngineOwnable.sol"; +import {RuleEngineOwnable2771} from "src/deployment/ownable/RuleEngineOwnable2771.sol"; +import {RuleEngineOwnable2Step} from "src/deployment/ownable/RuleEngineOwnable2Step.sol"; +import {RuleEngineOwnable2Step2771} from "src/deployment/ownable/RuleEngineOwnable2Step2771.sol"; import {RulesManagementModuleInvariantStorage} from "src/modules/library/RulesManagementModuleInvariantStorage.sol"; /** @@ -20,18 +23,36 @@ contract RuleEngineMaxRulesEventTest is Test, RulesManagementModuleInvariantStor function testRuleEngineEmitsInitialMaxRulesOnDeployment() public { vm.expectEmit(true, true, true, true); emit SetMaxRules(DEFAULT_MAX_RULES); - new RuleEngine(ADMIN, FORWARDER, address(0)); + new RuleEngine(ADMIN, address(0)); + } + + function testRuleEngine2771EmitsInitialMaxRulesOnDeployment() public { + vm.expectEmit(true, true, true, true); + emit SetMaxRules(DEFAULT_MAX_RULES); + new RuleEngine2771(ADMIN, FORWARDER, address(0)); } function testRuleEngineOwnableEmitsInitialMaxRulesOnDeployment() public { vm.expectEmit(true, true, true, true); emit SetMaxRules(DEFAULT_MAX_RULES); - new RuleEngineOwnable(ADMIN, FORWARDER, address(0)); + new RuleEngineOwnable(ADMIN, address(0)); } function testRuleEngineOwnable2StepEmitsInitialMaxRulesOnDeployment() public { vm.expectEmit(true, true, true, true); emit SetMaxRules(DEFAULT_MAX_RULES); - new RuleEngineOwnable2Step(ADMIN, FORWARDER, address(0)); + new RuleEngineOwnable2Step(ADMIN, address(0)); + } + + function testRuleEngineOwnable2771EmitsInitialMaxRulesOnDeployment() public { + vm.expectEmit(true, true, true, true); + emit SetMaxRules(DEFAULT_MAX_RULES); + new RuleEngineOwnable2771(ADMIN, FORWARDER, address(0)); + } + + function testRuleEngineOwnable2Step2771EmitsInitialMaxRulesOnDeployment() public { + vm.expectEmit(true, true, true, true); + emit SetMaxRules(DEFAULT_MAX_RULES); + new RuleEngineOwnable2Step2771(ADMIN, FORWARDER, address(0)); } } diff --git a/test/RuleEngine/RulesManagementModuleTest/CMTATIntegrationBase.sol b/test/RuleEngine/RulesManagementModuleTest/CMTATIntegrationBase.sol index 64060e81..59661d4b 100644 --- a/test/RuleEngine/RulesManagementModuleTest/CMTATIntegrationBase.sol +++ b/test/RuleEngine/RulesManagementModuleTest/CMTATIntegrationBase.sol @@ -26,7 +26,7 @@ abstract contract RuleEngineCMTATIntegrationBase is Test, HelperContract { cmtatContract.mint(ADDRESS2, defaultValue); vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - ruleEngineMock = new RuleEngine(RULE_ENGINE_OPERATOR_ADDRESS, ZERO_ADDRESS, address(cmtatContract)); + ruleEngineMock = new RuleEngine(RULE_ENGINE_OPERATOR_ADDRESS, address(cmtatContract)); ruleConditionalTransferLight = new RuleConditionalTransferLightMock(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, ruleEngineMock); diff --git a/test/RuleEngine/RulesManagementModuleTest/CMTATOperationRoutingV3.t.sol b/test/RuleEngine/RulesManagementModuleTest/CMTATOperationRoutingV3.t.sol new file mode 100644 index 00000000..c8e14143 --- /dev/null +++ b/test/RuleEngine/RulesManagementModuleTest/CMTATOperationRoutingV3.t.sol @@ -0,0 +1,161 @@ +// SPDX-License-Identifier: MPL-2.0 +pragma solidity ^0.8.20; + +import {Test} from "forge-std/Test.sol"; +import {CMTATStandalone} from "CMTATv3.0.0/deployment/CMTATStandalone.sol"; +import {IRuleEngine} from "CMTATv3.0.0/interfaces/engine/IRuleEngine.sol"; +import {RuleEngine} from "src/deployment/accessControl/RuleEngine.sol"; +import {IRule} from "src/interfaces/IRule.sol"; +import {CMTATDeploymentV3} from "../../utils/CMTATDeploymentV3.sol"; +import {RuleCodeProbe} from "../../utils/RuleCodeProbe.sol"; + +/** + * @title Transfer, transferFrom, mint and burn of a CMTAT v3.0.0 token through the RuleEngine + * @notice Pins which `transferred` overload each operation reaches, on the engine and on the rule, with the exact + * arguments, and that a rule rejecting that overload blocks the operation. + * @dev CMTAT v3.0.0 (`0_CMTATBaseCommon.sol`) passes a spender only for `transferFrom`. Mint and burn call + * `_checkTransferred(address(0), ...)`, so they take the 3-argument overload with no operator: unlike CMTAT + * >= v3.3.0, a rule keyed on the 4-argument path (a per-minter allowance) never sees a mint or a burn. + */ +contract RuleEngineCMTATOperationRoutingV3Test is Test { + address internal constant TOKEN_ADMIN = address(1); // admin of CMTATDeploymentV3, holds every token role + address internal constant ENGINE_ADMIN = address(0xE1); + address internal constant HOLDER = address(0xA1); + address internal constant RECEIVER = address(0xA2); + address internal constant SPENDER = address(0xA3); + uint256 internal constant INITIAL_BALANCE = 100; + uint256 internal constant VALUE = 20; + uint8 internal constant CODE = 42; + + bytes4 internal constant TRANSFERRED_3 = bytes4(keccak256("transferred(address,address,uint256)")); + bytes4 internal constant TRANSFERRED_4 = bytes4(keccak256("transferred(address,address,address,uint256)")); + + CMTATStandalone internal token; + RuleEngine internal engine; + RuleCodeProbe internal probe; + + function setUp() public { + token = new CMTATDeploymentV3().cmtat(); + vm.prank(TOKEN_ADMIN); + token.mint(HOLDER, INITIAL_BALANCE); + + engine = new RuleEngine(ENGINE_ADMIN, address(token)); + probe = new RuleCodeProbe(CODE, "rejected"); + vm.prank(ENGINE_ADMIN); + engine.addRule(IRule(address(probe))); + + vm.prank(TOKEN_ADMIN); + token.setRuleEngine(IRuleEngine(address(engine))); + } + + /* ============ Helpers ============ */ + + /// @dev Expects exactly one 3-argument call on the engine and on the rule, and no 4-argument call. + function _expectThreeArgumentPath(address from, address to, uint256 value) internal { + bytes memory call3 = abi.encodeWithSelector(TRANSFERRED_3, from, to, value); + vm.expectCall(address(engine), call3, 1); + vm.expectCall(address(probe), call3, 1); + vm.expectCall(address(engine), abi.encodeWithSelector(TRANSFERRED_4), 0); + vm.expectCall(address(probe), abi.encodeWithSelector(TRANSFERRED_4), 0); + } + + /* ============ Transfer ============ */ + + function testTransferUsesThreeArgumentOverload() public { + _expectThreeArgumentPath(HOLDER, RECEIVER, VALUE); + vm.prank(HOLDER); + assertTrue(token.transfer(RECEIVER, VALUE)); + + assertEq(token.balanceOf(HOLDER), INITIAL_BALANCE - VALUE); + assertEq(token.balanceOf(RECEIVER), VALUE); + } + + function testRuleCanBlockTransfer() public { + probe.setCodes(CODE, 0); + vm.prank(HOLDER); + vm.expectRevert(abi.encodeWithSelector(RuleCodeProbe.RuleCodeProbe_Rejected.selector, CODE)); + token.transfer(RECEIVER, VALUE); + } + + /* ============ TransferFrom ============ */ + + function testTransferFromUsesFourArgumentOverloadWithSpender() public { + vm.prank(HOLDER); + token.approve(SPENDER, VALUE); + + bytes memory call4 = abi.encodeWithSelector(TRANSFERRED_4, SPENDER, HOLDER, RECEIVER, VALUE); + vm.expectCall(address(engine), call4, 1); + vm.expectCall(address(probe), call4, 1); + vm.expectCall(address(engine), abi.encodeWithSelector(TRANSFERRED_3), 0); + vm.expectCall(address(probe), abi.encodeWithSelector(TRANSFERRED_3), 0); + vm.prank(SPENDER); + assertTrue(token.transferFrom(HOLDER, RECEIVER, VALUE)); + + assertEq(token.balanceOf(HOLDER), INITIAL_BALANCE - VALUE); + assertEq(token.balanceOf(RECEIVER), VALUE); + assertEq(token.allowance(HOLDER, SPENDER), 0); + } + + function testRuleCanBlockTransferFrom() public { + vm.prank(HOLDER); + token.approve(SPENDER, VALUE); + probe.setCodes(0, CODE); + vm.prank(SPENDER); + vm.expectRevert(abi.encodeWithSelector(RuleCodeProbe.RuleCodeProbe_Rejected.selector, CODE)); + token.transferFrom(HOLDER, RECEIVER, VALUE); + } + + /* ============ Mint ============ */ + + function testMintUsesThreeArgumentOverloadWithoutMinter() public { + _expectThreeArgumentPath(address(0), RECEIVER, VALUE); + vm.prank(TOKEN_ADMIN); + token.mint(RECEIVER, VALUE); + + assertEq(token.balanceOf(RECEIVER), VALUE); + assertEq(token.totalSupply(), INITIAL_BALANCE + VALUE); + } + + function testRuleCanBlockMint() public { + probe.setCodes(CODE, 0); + vm.prank(TOKEN_ADMIN); + vm.expectRevert(abi.encodeWithSelector(RuleCodeProbe.RuleCodeProbe_Rejected.selector, CODE)); + token.mint(RECEIVER, VALUE); + } + + /// @notice A rule enforced only on the 4-argument path (a spender-keyed rule) does not see a v3.0.0 mint. + function testFourArgumentOnlyRuleDoesNotBlockMint() public { + probe.setCodes(0, CODE); + vm.prank(TOKEN_ADMIN); + token.mint(RECEIVER, VALUE); + + assertEq(token.balanceOf(RECEIVER), VALUE); + } + + /* ============ Burn ============ */ + + function testBurnUsesThreeArgumentOverloadWithoutBurner() public { + _expectThreeArgumentPath(HOLDER, address(0), VALUE); + vm.prank(TOKEN_ADMIN); + token.burn(HOLDER, VALUE); + + assertEq(token.balanceOf(HOLDER), INITIAL_BALANCE - VALUE); + assertEq(token.totalSupply(), INITIAL_BALANCE - VALUE); + } + + function testRuleCanBlockBurn() public { + probe.setCodes(CODE, 0); + vm.prank(TOKEN_ADMIN); + vm.expectRevert(abi.encodeWithSelector(RuleCodeProbe.RuleCodeProbe_Rejected.selector, CODE)); + token.burn(HOLDER, VALUE); + } + + /// @notice A rule enforced only on the 4-argument path does not see a v3.0.0 burn. + function testFourArgumentOnlyRuleDoesNotBlockBurn() public { + probe.setCodes(0, CODE); + vm.prank(TOKEN_ADMIN); + token.burn(HOLDER, VALUE); + + assertEq(token.balanceOf(HOLDER), INITIAL_BALANCE - VALUE); + } +} diff --git a/test/RuleEngine/RulesManagementModuleTest/RuleEngineOperation.t.sol b/test/RuleEngine/RulesManagementModuleTest/RuleEngineOperation.t.sol index 174d8fc6..4019f147 100644 --- a/test/RuleEngine/RulesManagementModuleTest/RuleEngineOperation.t.sol +++ b/test/RuleEngine/RulesManagementModuleTest/RuleEngineOperation.t.sol @@ -14,7 +14,7 @@ contract RulesManagementModuleInvariantStorageTest is Test, HelperContract { // Arrange function setUp() public { vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - ruleEngineMock = new RuleEngine(RULE_ENGINE_OPERATOR_ADDRESS, ZERO_ADDRESS, ZERO_ADDRESS); + ruleEngineMock = new RuleEngine(RULE_ENGINE_OPERATOR_ADDRESS, ZERO_ADDRESS); ruleConditionalTransferLight = new RuleConditionalTransferLightMock(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, ruleEngineMock); diff --git a/test/RuleEngine/RulesManagementModuleTest/RuleEngineOperationRevertBase.sol b/test/RuleEngine/RulesManagementModuleTest/RuleEngineOperationRevertBase.sol index 48cbc990..a9ca7db5 100644 --- a/test/RuleEngine/RulesManagementModuleTest/RuleEngineOperationRevertBase.sol +++ b/test/RuleEngine/RulesManagementModuleTest/RuleEngineOperationRevertBase.sol @@ -19,7 +19,7 @@ abstract contract RuleEngineOperationRevertBase is Test, HelperContract { cmtatContract = _deployCmtat(); vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - ruleEngineMock = new RuleEngine(RULE_ENGINE_OPERATOR_ADDRESS, ZERO_ADDRESS, address(cmtatContract)); + ruleEngineMock = new RuleEngine(RULE_ENGINE_OPERATOR_ADDRESS, address(cmtatContract)); RuleOperationRevertMock ruleOperationRevert = new RuleOperationRevertMock(); vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); diff --git a/test/RuleEngine/RulesManagementModuleTest/RuleEngineRestriction.t.sol b/test/RuleEngine/RulesManagementModuleTest/RuleEngineRestriction.t.sol index 39cc1732..db517642 100644 --- a/test/RuleEngine/RulesManagementModuleTest/RuleEngineRestriction.t.sol +++ b/test/RuleEngine/RulesManagementModuleTest/RuleEngineRestriction.t.sol @@ -15,7 +15,7 @@ contract RuleEngineTest is Test, HelperContract { // Arrange function setUp() public { vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - ruleEngineMock = new RuleEngine(RULE_ENGINE_OPERATOR_ADDRESS, ZERO_ADDRESS, ZERO_ADDRESS); + ruleEngineMock = new RuleEngine(RULE_ENGINE_OPERATOR_ADDRESS, ZERO_ADDRESS); ruleConditionalTransferLight = new RuleConditionalTransferLightMock(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, ruleEngineMock); diff --git a/test/RuleEngine/SecurityReview.t.sol b/test/RuleEngine/SecurityReview.t.sol new file mode 100644 index 00000000..e1f773d3 --- /dev/null +++ b/test/RuleEngine/SecurityReview.t.sol @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: MPL-2.0 +pragma solidity ^0.8.20; + +import {IAccessControl} from "@openzeppelin/contracts/access/IAccessControl.sol"; +import {RuleEngine} from "src/deployment/accessControl/RuleEngine.sol"; +import {SecurityReviewTestBase} from "../utils/SecurityReviewTestBase.sol"; + +/** + * @title SecurityReviewTest + * @notice v3.0.0-rc7 security review tests for the RBAC `RuleEngine`. + */ +contract SecurityReviewTest is SecurityReviewTestBase { + function _deployEngine(address admin, address token) internal override returns (address) { + return address(new RuleEngine(admin, token)); + } + + function _unauthorizedRevertData(address caller, bytes32 role) internal pure override returns (bytes memory) { + return abi.encodeWithSelector(IAccessControl.AccessControlUnauthorizedAccount.selector, caller, role); + } + + function _renounceAdministration() internal override { + vm.prank(ADMIN); + IAccessControl(address(engine)).renounceRole(DEFAULT_ADMIN_ROLE, ADMIN); + } +} diff --git a/test/RuleEngine/ruleEngineValidation/RuleEngineRestriction.sol b/test/RuleEngine/ruleEngineValidation/RuleEngineRestriction.sol index 9eb92b0a..fbdc8f28 100644 --- a/test/RuleEngine/ruleEngineValidation/RuleEngineRestriction.sol +++ b/test/RuleEngine/ruleEngineValidation/RuleEngineRestriction.sol @@ -15,7 +15,7 @@ contract RuleEngineRestrictionTest is Test, HelperContract { function setUp() public { ruleWhitelist = new RuleWhitelistMock(WHITELIST_OPERATOR_ADDRESS, ZERO_ADDRESS); vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - ruleEngineMock = new RuleEngine(RULE_ENGINE_OPERATOR_ADDRESS, ZERO_ADDRESS, ZERO_ADDRESS); + ruleEngineMock = new RuleEngine(RULE_ENGINE_OPERATOR_ADDRESS, ZERO_ADDRESS); vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); ruleEngineMock.addRule(ruleWhitelist); // Arrange - Assert diff --git a/test/RuleEngine/ruleEngineValidation/RuleEngineValidation.sol b/test/RuleEngine/ruleEngineValidation/RuleEngineValidation.sol index 90497d88..bb6e422c 100644 --- a/test/RuleEngine/ruleEngineValidation/RuleEngineValidation.sol +++ b/test/RuleEngine/ruleEngineValidation/RuleEngineValidation.sol @@ -15,7 +15,7 @@ contract RuleEngineTest is Test, HelperContract { function setUp() public { ruleWhitelist = new RuleWhitelistMock(WHITELIST_OPERATOR_ADDRESS, ZERO_ADDRESS); vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); - ruleEngineMock = new RuleEngine(RULE_ENGINE_OPERATOR_ADDRESS, ZERO_ADDRESS, ZERO_ADDRESS); + ruleEngineMock = new RuleEngine(RULE_ENGINE_OPERATOR_ADDRESS, ZERO_ADDRESS); vm.prank(RULE_ENGINE_OPERATOR_ADDRESS); ruleEngineMock.addRule(ruleWhitelist); diff --git a/test/RuleEngine2771/ERC2771TokenGate.t.sol b/test/RuleEngine2771/ERC2771TokenGate.t.sol new file mode 100644 index 00000000..b1aa1844 --- /dev/null +++ b/test/RuleEngine2771/ERC2771TokenGate.t.sol @@ -0,0 +1,24 @@ +// SPDX-License-Identifier: MPL-2.0 +pragma solidity ^0.8.20; + +import {IAccessControl} from "@openzeppelin/contracts/access/IAccessControl.sol"; +import {RuleEngine2771} from "src/deployment/accessControl/RuleEngine2771.sol"; +import {ERC2771TokenGateTestBase} from "../utils/ERC2771TokenGateTestBase.sol"; + +/** + * @title ERC2771TokenGateTest + * @notice ERC-2771 token-identity gate tests for the RBAC `RuleEngine2771`. + */ +contract ERC2771TokenGateTest is ERC2771TokenGateTestBase { + function _deployEngine(address admin, address forwarder, address token) internal override returns (address) { + return address(new RuleEngine2771(admin, forwarder, token)); + } + + function _managerRevertData(address caller) internal view override returns (bytes memory) { + return abi.encodeWithSelector( + IAccessControl.AccessControlUnauthorizedAccount.selector, + caller, + RuleEngine2771(engine).COMPLIANCE_MANAGER_ROLE() + ); + } +} diff --git a/test/RuleEngine2771/ERC2771Variant.t.sol b/test/RuleEngine2771/ERC2771Variant.t.sol new file mode 100644 index 00000000..20846516 --- /dev/null +++ b/test/RuleEngine2771/ERC2771Variant.t.sol @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: MPL-2.0 +pragma solidity ^0.8.20; + +import {RuleEngine} from "src/deployment/accessControl/RuleEngine.sol"; +import {RuleEngine2771} from "src/deployment/accessControl/RuleEngine2771.sol"; +import {RuleEngine2771Exposed} from "src/mocks/RuleEngineExposed.sol"; +import {RuleEngineInvariantStorage} from "src/modules/library/RuleEngineInvariantStorage.sol"; +import {ERC2771VariantTestBase} from "../utils/ERC2771VariantTestBase.sol"; + +/** + * @title ERC2771VariantTest + * @notice ERC-2771 variant tests for `RuleEngine2771`. + */ +contract ERC2771VariantTest is ERC2771VariantTestBase, RuleEngineInvariantStorage { + function _deploy2771(address admin, address forwarder, address token) internal override returns (address) { + return address(new RuleEngine2771(admin, forwarder, token)); + } + + function _deployWithoutForwarder(address admin, address token) internal override returns (address) { + return address(new RuleEngine(admin, token)); + } + + function _deployExposed(address admin, address forwarder) internal override returns (address) { + return address(new RuleEngine2771Exposed(admin, forwarder, address(0))); + } + + function _zeroAdminRevertData() internal pure override returns (bytes memory) { + return abi.encodeWithSelector(RuleEngine_AdminWithAddressZeroNotAllowed.selector); + } +} diff --git a/test/RuleEngine2771/RuleAggregation.t.sol b/test/RuleEngine2771/RuleAggregation.t.sol new file mode 100644 index 00000000..6256cf0a --- /dev/null +++ b/test/RuleEngine2771/RuleAggregation.t.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: MPL-2.0 +pragma solidity ^0.8.20; + +import {RuleEngine2771} from "src/deployment/accessControl/RuleEngine2771.sol"; +import {RuleAggregationTestBase} from "../utils/RuleAggregationTestBase.sol"; + +/** + * @title RuleAggregation2771Test + * @notice Rule aggregation tests for the RBAC `RuleEngine2771`. + */ +contract RuleAggregation2771Test is RuleAggregationTestBase { + function _deployEngine(address admin, address token) internal override returns (address) { + return address(new RuleEngine2771(admin, address(0), token)); + } +} diff --git a/test/RuleEngine2771/RuleEngine2771Deployment.t.sol b/test/RuleEngine2771/RuleEngine2771Deployment.t.sol new file mode 100644 index 00000000..ab7f01bc --- /dev/null +++ b/test/RuleEngine2771/RuleEngine2771Deployment.t.sol @@ -0,0 +1,58 @@ +// SPDX-License-Identifier: MPL-2.0 +pragma solidity ^0.8.20; + +import {Test} from "forge-std/Test.sol"; +import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; +import {IAccessControl} from "@openzeppelin/contracts/access/IAccessControl.sol"; +import {IAccessControlEnumerable} from "@openzeppelin/contracts/access/extensions/IAccessControlEnumerable.sol"; +import {MinimalForwarderMock} from "CMTAT/mocks/MinimalForwarderMock.sol"; +import {RuleEngineInterfaceId} from "CMTAT/library/RuleEngineInterfaceId.sol"; +import {ERC1404ExtendInterfaceId} from "CMTAT/library/ERC1404ExtendInterfaceId.sol"; +import {RuleEngine2771} from "src/deployment/accessControl/RuleEngine2771.sol"; +import {ComplianceInterfaceId} from "src/modules/library/ComplianceInterfaceId.sol"; +import {ERC1404InterfaceId} from "src/modules/library/ERC1404InterfaceId.sol"; +import {RuleEngineInvariantStorage} from "src/modules/library/RuleEngineInvariantStorage.sol"; + +/** + * @title RuleEngine2771DeploymentTest + * @notice Deployment and ERC-165 tests for the RBAC `RuleEngine2771`. The forwarder, `_msgData` and + * zero-admin checks shared with the ownable `*2771` variants are in `ERC2771Variant.t.sol`. + */ +contract RuleEngine2771DeploymentTest is Test, RuleEngineInvariantStorage { + address internal constant ADMIN = address(0xA11CE); + address internal constant TOKEN = address(0x7070); + + MinimalForwarderMock internal forwarder; + RuleEngine2771 internal engine; + + function setUp() public { + forwarder = new MinimalForwarderMock(); + forwarder.initialize("ERC2771ForwarderDomain"); + engine = new RuleEngine2771(ADMIN, address(forwarder), TOKEN); + } + + function testRightDeployment() public view { + assertTrue(engine.isTrustedForwarder(address(forwarder))); + assertFalse(engine.isTrustedForwarder(ADMIN)); + assertEq(engine.trustedForwarder(), address(forwarder)); + assertTrue(engine.hasRole(engine.DEFAULT_ADMIN_ROLE(), ADMIN)); + assertTrue(engine.hasRole(engine.RULES_MANAGEMENT_ROLE(), ADMIN)); + assertTrue(engine.hasRole(engine.COMPLIANCE_MANAGER_ROLE(), ADMIN)); + assertTrue(engine.isTokenBound(TOKEN)); + assertEq(engine.maxRules(), 10); + } + + /// @notice Same interfaces as `RuleEngine`: ERC-2771 adds no ERC-165 id. + function testSupportsInterfaces() public view { + assertTrue(engine.supportsInterface(type(IERC165).interfaceId)); + assertTrue(engine.supportsInterface(type(IAccessControl).interfaceId)); + assertTrue(engine.supportsInterface(type(IAccessControlEnumerable).interfaceId)); + assertTrue(engine.supportsInterface(RuleEngineInterfaceId.RULE_ENGINE_INTERFACE_ID)); + assertTrue(engine.supportsInterface(ERC1404InterfaceId.IERC1404_INTERFACE_ID)); + assertTrue(engine.supportsInterface(ERC1404ExtendInterfaceId.ERC1404EXTEND_INTERFACE_ID)); + assertTrue(engine.supportsInterface(ComplianceInterfaceId.ERC3643_COMPLIANCE_INTERFACE_ID)); + assertTrue(engine.supportsInterface(ComplianceInterfaceId.ERC3643_COMPLIANCE_EXTENDED_INTERFACE_ID)); + assertTrue(engine.supportsInterface(ComplianceInterfaceId.IERC7551_COMPLIANCE_INTERFACE_ID)); + assertFalse(engine.supportsInterface(0xffffffff)); + } +} diff --git a/test/RuleEngine2771/RuleEngineInvariant.t.sol b/test/RuleEngine2771/RuleEngineInvariant.t.sol new file mode 100644 index 00000000..d1d5d158 --- /dev/null +++ b/test/RuleEngine2771/RuleEngineInvariant.t.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: MPL-2.0 +pragma solidity ^0.8.20; + +import {RuleEngine2771} from "src/deployment/accessControl/RuleEngine2771.sol"; +import {RuleEngineInvariantTestBase} from "../utils/RuleEngineInvariantTestBase.sol"; + +/** + * @title RuleEngine2771InvariantTest + * @notice Invariant tests over the rule set and the bound tokens for `RuleEngine2771`. + */ +contract RuleEngine2771InvariantTest is RuleEngineInvariantTestBase { + function _deployEngine(address admin) internal override returns (address) { + return address(new RuleEngine2771(admin, address(0), address(0))); + } +} diff --git a/test/RuleEngine2771/SecurityReview.t.sol b/test/RuleEngine2771/SecurityReview.t.sol new file mode 100644 index 00000000..846dee77 --- /dev/null +++ b/test/RuleEngine2771/SecurityReview.t.sol @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: MPL-2.0 +pragma solidity ^0.8.20; + +import {IAccessControl} from "@openzeppelin/contracts/access/IAccessControl.sol"; +import {RuleEngine2771} from "src/deployment/accessControl/RuleEngine2771.sol"; +import {SecurityReviewTestBase} from "../utils/SecurityReviewTestBase.sol"; + +/** + * @title SecurityReview2771Test + * @notice v3.0.0-rc7 security review tests for `RuleEngine2771`. + */ +contract SecurityReview2771Test is SecurityReviewTestBase { + function _deployEngine(address admin, address token) internal override returns (address) { + return address(new RuleEngine2771(admin, FORWARDER, token)); + } + + function _unauthorizedRevertData(address caller, bytes32 role) internal pure override returns (bytes memory) { + return abi.encodeWithSelector(IAccessControl.AccessControlUnauthorizedAccount.selector, caller, role); + } + + function _renounceAdministration() internal override { + vm.prank(ADMIN); + IAccessControl(address(engine)).renounceRole(DEFAULT_ADMIN_ROLE, ADMIN); + } +} diff --git a/test/RuleEngineOwnable/AccessControl/RuleEngineOwnableAccessControl.t.sol b/test/RuleEngineOwnable/AccessControl/RuleEngineOwnableAccessControl.t.sol index dd3367d5..8554f72d 100644 --- a/test/RuleEngineOwnable/AccessControl/RuleEngineOwnableAccessControl.t.sol +++ b/test/RuleEngineOwnable/AccessControl/RuleEngineOwnableAccessControl.t.sol @@ -13,7 +13,7 @@ import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; contract RuleEngineOwnableAccessControlTest is Test, HelperContractOwnable { // Arrange function setUp() public { - ruleEngineMock = new RuleEngineOwnable(OWNER_ADDRESS, ZERO_ADDRESS, ZERO_ADDRESS); + ruleEngineMock = new RuleEngineOwnable(OWNER_ADDRESS, ZERO_ADDRESS); ruleConditionalTransferLight = new RuleConditionalTransferLightMock(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, ruleEngineMock); } diff --git a/test/RuleEngineOwnable/ERC3643Compliance.t.sol b/test/RuleEngineOwnable/ERC3643Compliance.t.sol index fbc0355d..307beabf 100644 --- a/test/RuleEngineOwnable/ERC3643Compliance.t.sol +++ b/test/RuleEngineOwnable/ERC3643Compliance.t.sol @@ -1,6 +1,7 @@ // SPDX-License-Identifier: MIT pragma solidity ^0.8.20; +import {ITokenBindingExtended} from "src/interfaces/ITokenBindingExtended.sol"; import {Test} from "forge-std/Test.sol"; import {Vm} from "forge-std/Vm.sol"; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; @@ -41,7 +42,7 @@ contract RuleEngineOwnableERC3643Test is Test, HelperContractOwnable { function setUp() public { // Deploy RuleEngineOwnable with owner - ruleEngineMock = new RuleEngineOwnable(OWNER_ADDRESS, ZERO_ADDRESS, ZERO_ADDRESS); + ruleEngineMock = new RuleEngineOwnable(OWNER_ADDRESS, ZERO_ADDRESS); // Deploy multiple mock tokens token1 = new ERC3643MockTokenOwnable(address(ruleEngineMock)); @@ -217,6 +218,18 @@ contract RuleEngineOwnableERC3643Test is Test, HelperContractOwnable { ruleEngineMock.setTokenSelfBindingApproval(address(token1), true); } + function testSetTokenSelfBindingApprovalEmitsEvent() public { + vm.expectEmit(true, false, false, true, address(ruleEngineMock)); + emit ITokenBindingExtended.TokenSelfBindingApprovalSet(address(0x7070), true); + vm.prank(OWNER_ADDRESS); + ruleEngineMock.setTokenSelfBindingApproval(address(0x7070), true); + + vm.expectEmit(true, false, false, true, address(ruleEngineMock)); + emit ITokenBindingExtended.TokenSelfBindingApprovalSet(address(0x7070), false); + vm.prank(OWNER_ADDRESS); + ruleEngineMock.setTokenSelfBindingApproval(address(0x7070), false); + } + function testCannotSetTokenSelfBindingApprovalForZeroAddress() public { vm.expectRevert(TokenBindingModuleInvariantStorage.TokenBinding_InvalidTokenAddress.selector); vm.prank(OWNER_ADDRESS); @@ -325,10 +338,12 @@ contract RuleEngineOwnableERC3643Test is Test, HelperContractOwnable { ruleEngineMock.bindTokens(tokens); } + /// @notice Batch binding is atomic on purpose (rc7 code-quality review `C-3`): one token already bound + /// reverts the whole batch, including the tokens bound before it in the same call. function testCannotBindTokensBatchWithAlreadyBoundToken() public { address[] memory tokens = new address[](2); - tokens[0] = address(token1); - tokens[1] = address(token2); + tokens[0] = address(token2); + tokens[1] = address(token1); vm.prank(OWNER_ADDRESS); ruleEngineMock.bindToken(address(token1)); @@ -336,6 +351,8 @@ contract RuleEngineOwnableERC3643Test is Test, HelperContractOwnable { vm.expectRevert(TokenBindingModuleInvariantStorage.TokenBinding_TokenAlreadyBound.selector); vm.prank(OWNER_ADDRESS); ruleEngineMock.bindTokens(tokens); + + assertFalse(ruleEngineMock.isTokenBound(address(token2)), "the token before the failing one is rolled back"); } function testCannotUnbindTokensBatchWithTokenNotBound() public { @@ -349,6 +366,23 @@ contract RuleEngineOwnableERC3643Test is Test, HelperContractOwnable { vm.expectRevert(TokenBindingModuleInvariantStorage.TokenBinding_TokenNotBound.selector); vm.prank(OWNER_ADDRESS); ruleEngineMock.unbindTokens(tokens); + + assertTrue(ruleEngineMock.isTokenBound(address(token1)), "the token before the failing one stays bound"); + } + + /// @notice An empty batch is a no-op: no revert, no event, no state change (rc7 code-quality review `C-3`). + function testEmptyBindAndUnbindBatchesAreNoOps() public { + address[] memory empty = new address[](0); + uint256 before = ruleEngineMock.getTokenBounds().length; + + vm.recordLogs(); + vm.startPrank(OWNER_ADDRESS); + ruleEngineMock.bindTokens(empty); + ruleEngineMock.unbindTokens(empty); + vm.stopPrank(); + + assertEq(vm.getRecordedLogs().length, 0); + assertEq(ruleEngineMock.getTokenBounds().length, before); } function testCannotCreatedIfNotBound() public { diff --git a/test/RuleEngineOwnable/NoForwarder.t.sol b/test/RuleEngineOwnable/NoForwarder.t.sol new file mode 100644 index 00000000..82530176 --- /dev/null +++ b/test/RuleEngineOwnable/NoForwarder.t.sol @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: MPL-2.0 +pragma solidity ^0.8.20; + +import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; +import {RuleEngineOwnable} from "src/deployment/ownable/RuleEngineOwnable.sol"; +import {NoForwarderTestBase} from "../utils/NoForwarderTestBase.sol"; + +/** + * @title NoForwarderOwnableTest + * @notice `RuleEngineOwnable` has no ERC-2771 support. + */ +contract NoForwarderOwnableTest is NoForwarderTestBase { + function _deployEngine(address admin, address token) internal override returns (address) { + return address(new RuleEngineOwnable(admin, token)); + } + + function _managerRevertData(address caller) internal pure override returns (bytes memory) { + return abi.encodeWithSelector(Ownable.OwnableUnauthorizedAccount.selector, caller); + } +} diff --git a/test/RuleEngineOwnable/RuleAggregation.t.sol b/test/RuleEngineOwnable/RuleAggregation.t.sol new file mode 100644 index 00000000..ed00392e --- /dev/null +++ b/test/RuleEngineOwnable/RuleAggregation.t.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: MPL-2.0 +pragma solidity ^0.8.20; + +import {RuleEngineOwnable} from "src/deployment/ownable/RuleEngineOwnable.sol"; +import {RuleAggregationTestBase} from "../utils/RuleAggregationTestBase.sol"; + +/** + * @title RuleAggregationOwnableTest + * @notice Rule aggregation tests for the `RuleEngineOwnable`. + */ +contract RuleAggregationOwnableTest is RuleAggregationTestBase { + function _deployEngine(address admin, address token) internal override returns (address) { + return address(new RuleEngineOwnable(admin, token)); + } +} diff --git a/test/RuleEngineOwnable/RuleEngineInvariant.t.sol b/test/RuleEngineOwnable/RuleEngineInvariant.t.sol new file mode 100644 index 00000000..886afd30 --- /dev/null +++ b/test/RuleEngineOwnable/RuleEngineInvariant.t.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: MPL-2.0 +pragma solidity ^0.8.20; + +import {RuleEngineOwnable} from "src/deployment/ownable/RuleEngineOwnable.sol"; +import {RuleEngineInvariantTestBase} from "../utils/RuleEngineInvariantTestBase.sol"; + +/** + * @title RuleEngineOwnableInvariantTest + * @notice Invariant tests over the rule set and the bound tokens for `RuleEngineOwnable`. + */ +contract RuleEngineOwnableInvariantTest is RuleEngineInvariantTestBase { + function _deployEngine(address admin) internal override returns (address) { + return address(new RuleEngineOwnable(admin, address(0))); + } +} diff --git a/test/RuleEngineOwnable/RuleEngineOwnableCoverage.t.sol b/test/RuleEngineOwnable/RuleEngineOwnableCoverage.t.sol index 9f45d203..b346891e 100644 --- a/test/RuleEngineOwnable/RuleEngineOwnableCoverage.t.sol +++ b/test/RuleEngineOwnable/RuleEngineOwnableCoverage.t.sol @@ -5,7 +5,6 @@ import {Test} from "forge-std/Test.sol"; // forge-lint: disable-next-line(unaliased-plain-import) import "../HelperContractOwnable.sol"; -import {RuleEngineOwnableExposed} from "src/mocks/RuleEngineExposed.sol"; import {RuleInvalidMock} from "src/mocks/RuleInvalidMock.sol"; import {IAccessControl} from "@openzeppelin/contracts/access/IAccessControl.sol"; import {ICompliance} from "src/mocks/ICompliance.sol"; @@ -21,8 +20,6 @@ import {OwnableInterfaceId} from "src/modules/library/OwnableInterfaceId.sol"; * @title Coverage tests for RuleEngineOwnable (_msgData, ERC-165 rule check) */ contract RuleEngineOwnableCoverageTest is Test, HelperContractOwnable { - RuleEngineOwnableExposed public ruleEngineOwnableExposed; - // Known interface IDs bytes4 constant RULE_ENGINE_ID = 0x20c49ce7; bytes4 constant ERC1404_EXTEND_ID = 0x78a8de7d; @@ -30,8 +27,7 @@ contract RuleEngineOwnableCoverageTest is Test, HelperContractOwnable { bytes4 constant INVALID_ID = 0xffffffff; function setUp() public { - ruleEngineMock = new RuleEngineOwnable(OWNER_ADDRESS, ZERO_ADDRESS, ZERO_ADDRESS); - ruleEngineOwnableExposed = new RuleEngineOwnableExposed(OWNER_ADDRESS, ZERO_ADDRESS, ZERO_ADDRESS); + ruleEngineMock = new RuleEngineOwnable(OWNER_ADDRESS, ZERO_ADDRESS); } /*////////////////////////////////////////////////////////////// @@ -85,14 +81,6 @@ contract RuleEngineOwnableCoverageTest is Test, HelperContractOwnable { MSG DATA //////////////////////////////////////////////////////////////*/ - function testMsgDataReturnsCalldata() public view { - bytes memory data = ruleEngineOwnableExposed.exposedMsgData(); - // Should return the calldata (selector of exposedMsgData) - assertEq(data.length, 4); - // forge-lint: disable-next-line(unsafe-typecast) - assertEq(bytes4(data), ruleEngineOwnableExposed.exposedMsgData.selector); - } - /*////////////////////////////////////////////////////////////// ERC-165 RULE INTERFACE CHECK //////////////////////////////////////////////////////////////*/ diff --git a/test/RuleEngineOwnable/RuleEngineOwnableDeployment.t.sol b/test/RuleEngineOwnable/RuleEngineOwnableDeployment.t.sol index 72d1a415..56fcf98d 100644 --- a/test/RuleEngineOwnable/RuleEngineOwnableDeployment.t.sol +++ b/test/RuleEngineOwnable/RuleEngineOwnableDeployment.t.sol @@ -4,7 +4,6 @@ pragma solidity ^0.8.20; import {Test} from "forge-std/Test.sol"; // forge-lint: disable-next-line(unaliased-plain-import) import "../HelperContractOwnable.sol"; -import {MinimalForwarderMock} from "CMTAT/mocks/MinimalForwarderMock.sol"; import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; import {ERC1404ExtendInterfaceId} from "CMTAT/library/ERC1404ExtendInterfaceId.sol"; import {RuleEngineInterfaceId} from "CMTAT/library/RuleEngineInterfaceId.sol"; @@ -25,23 +24,16 @@ contract RuleEngineOwnableDeploymentTest is Test, HelperContractOwnable { function setUp() public {} function testRightDeployment() public { - // Arrange - vm.prank(OWNER_ADDRESS); - MinimalForwarderMock forwarder = new MinimalForwarderMock(); - forwarder.initialize(ERC2771ForwarderDomain); - // Act - ruleEngineMock = new RuleEngineOwnable(OWNER_ADDRESS, address(forwarder), ZERO_ADDRESS); + ruleEngineMock = new RuleEngineOwnable(OWNER_ADDRESS, ZERO_ADDRESS); // Assert assertEq(ruleEngineMock.owner(), OWNER_ADDRESS); - resBool = ruleEngineMock.isTrustedForwarder(address(forwarder)); - assertEq(resBool, true); } function testReturnZeroAddressForRule() public { // Arrange - ruleEngineMock = new RuleEngineOwnable(OWNER_ADDRESS, address(0x0), ZERO_ADDRESS); + ruleEngineMock = new RuleEngineOwnable(OWNER_ADDRESS, ZERO_ADDRESS); // Act resAddr = ruleEngineMock.rule(0); // Assert @@ -50,25 +42,21 @@ contract RuleEngineOwnableDeploymentTest is Test, HelperContractOwnable { function testHasRightVersion() public { // Act - ruleEngineMock = new RuleEngineOwnable(OWNER_ADDRESS, address(0x0), ZERO_ADDRESS); + ruleEngineMock = new RuleEngineOwnable(OWNER_ADDRESS, ZERO_ADDRESS); // Assert - assertEq(ruleEngineMock.version(), "3.0.0"); + assertEq(ruleEngineMock.version(), "3.0.0-rc7"); } function testCannotDeployContractIfOwnerAddressIsZero() public { - // Arrange - vm.prank(WHITELIST_OPERATOR_ADDRESS); - MinimalForwarderMock forwarder = new MinimalForwarderMock(); - forwarder.initialize(ERC2771ForwarderDomain); vm.expectRevert(abi.encodeWithSignature("OwnableInvalidOwner(address)", ZERO_ADDRESS)); // Act - ruleEngineMock = new RuleEngineOwnable(address(0x0), address(forwarder), ZERO_ADDRESS); + ruleEngineMock = new RuleEngineOwnable(address(0x0), ZERO_ADDRESS); } function testSupportsInterfaces() public { // Arrange - ruleEngineMock = new RuleEngineOwnable(OWNER_ADDRESS, address(0x0), ZERO_ADDRESS); + ruleEngineMock = new RuleEngineOwnable(OWNER_ADDRESS, ZERO_ADDRESS); // Act & Assert assertTrue(ruleEngineMock.supportsInterface(type(IERC165).interfaceId)); @@ -89,7 +77,7 @@ contract RuleEngineOwnableDeploymentTest is Test, HelperContractOwnable { address tokenAddress = address(0x123); // Act - ruleEngineMock = new RuleEngineOwnable(OWNER_ADDRESS, address(0x0), tokenAddress); + ruleEngineMock = new RuleEngineOwnable(OWNER_ADDRESS, tokenAddress); // Assert assertTrue(ruleEngineMock.isTokenBound(tokenAddress)); diff --git a/test/RuleEngineOwnable/RulesManagementModuleTest/RuleEngineOwnableOperation.t.sol b/test/RuleEngineOwnable/RulesManagementModuleTest/RuleEngineOwnableOperation.t.sol index 7b8af814..63ba6258 100644 --- a/test/RuleEngineOwnable/RulesManagementModuleTest/RuleEngineOwnableOperation.t.sol +++ b/test/RuleEngineOwnable/RulesManagementModuleTest/RuleEngineOwnableOperation.t.sol @@ -14,7 +14,7 @@ contract RuleEngineOwnableOperationTest is Test, HelperContractOwnable { // Arrange function setUp() public { vm.prank(OWNER_ADDRESS); - ruleEngineMock = new RuleEngineOwnable(OWNER_ADDRESS, ZERO_ADDRESS, ZERO_ADDRESS); + ruleEngineMock = new RuleEngineOwnable(OWNER_ADDRESS, ZERO_ADDRESS); ruleConditionalTransferLight = new RuleConditionalTransferLightMock(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, ruleEngineMock); diff --git a/test/RuleEngineOwnable/SecurityReview.t.sol b/test/RuleEngineOwnable/SecurityReview.t.sol new file mode 100644 index 00000000..22a2c5a2 --- /dev/null +++ b/test/RuleEngineOwnable/SecurityReview.t.sol @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: MPL-2.0 +pragma solidity ^0.8.20; + +import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; +import {RuleEngineOwnable} from "src/deployment/ownable/RuleEngineOwnable.sol"; +import {SecurityReviewTestBase} from "../utils/SecurityReviewTestBase.sol"; + +/** + * @title SecurityReviewOwnableTest + * @notice v3.0.0-rc7 security review tests for `RuleEngineOwnable`. + */ +contract SecurityReviewOwnableTest is SecurityReviewTestBase { + function _deployEngine(address admin, address token) internal override returns (address) { + return address(new RuleEngineOwnable(admin, token)); + } + + function _unauthorizedRevertData(address caller, bytes32) internal pure override returns (bytes memory) { + return abi.encodeWithSelector(Ownable.OwnableUnauthorizedAccount.selector, caller); + } + + function _renounceAdministration() internal override { + vm.prank(ADMIN); + Ownable(address(engine)).renounceOwnership(); + } +} diff --git a/test/RuleEngineOwnable2771/ERC2771TokenGate.t.sol b/test/RuleEngineOwnable2771/ERC2771TokenGate.t.sol new file mode 100644 index 00000000..2610d124 --- /dev/null +++ b/test/RuleEngineOwnable2771/ERC2771TokenGate.t.sol @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: MPL-2.0 +pragma solidity ^0.8.20; + +import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; +import {RuleEngineOwnable2771} from "src/deployment/ownable/RuleEngineOwnable2771.sol"; +import {ERC2771TokenGateTestBase} from "../utils/ERC2771TokenGateTestBase.sol"; + +/** + * @title ERC2771TokenGateOwnableTest + * @notice ERC-2771 token-identity gate tests for `RuleEngineOwnable2771`. + */ +contract ERC2771TokenGateOwnableTest is ERC2771TokenGateTestBase { + function _deployEngine(address admin, address forwarder, address token) internal override returns (address) { + return address(new RuleEngineOwnable2771(admin, forwarder, token)); + } + + function _managerRevertData(address caller) internal pure override returns (bytes memory) { + return abi.encodeWithSelector(Ownable.OwnableUnauthorizedAccount.selector, caller); + } +} diff --git a/test/RuleEngineOwnable2771/ERC2771Variant.t.sol b/test/RuleEngineOwnable2771/ERC2771Variant.t.sol new file mode 100644 index 00000000..aa0cbe40 --- /dev/null +++ b/test/RuleEngineOwnable2771/ERC2771Variant.t.sol @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: MPL-2.0 +pragma solidity ^0.8.20; + +import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; +import {RuleEngineOwnable} from "src/deployment/ownable/RuleEngineOwnable.sol"; +import {RuleEngineOwnable2771} from "src/deployment/ownable/RuleEngineOwnable2771.sol"; +import {RuleEngineOwnable2771Exposed} from "src/mocks/RuleEngineExposed.sol"; +import {ERC2771VariantTestBase} from "../utils/ERC2771VariantTestBase.sol"; + +/** + * @title ERC2771VariantOwnableTest + * @notice ERC-2771 variant tests for `RuleEngineOwnable2771`. + */ +contract ERC2771VariantOwnableTest is ERC2771VariantTestBase { + function _deploy2771(address admin, address forwarder, address token) internal override returns (address) { + return address(new RuleEngineOwnable2771(admin, forwarder, token)); + } + + function _deployWithoutForwarder(address admin, address token) internal override returns (address) { + return address(new RuleEngineOwnable(admin, token)); + } + + function _deployExposed(address admin, address forwarder) internal override returns (address) { + return address(new RuleEngineOwnable2771Exposed(admin, forwarder, address(0))); + } + + function _zeroAdminRevertData() internal pure override returns (bytes memory) { + return abi.encodeWithSelector(Ownable.OwnableInvalidOwner.selector, address(0)); + } +} diff --git a/test/RuleEngineOwnable2771/RuleAggregation.t.sol b/test/RuleEngineOwnable2771/RuleAggregation.t.sol new file mode 100644 index 00000000..acaf503e --- /dev/null +++ b/test/RuleEngineOwnable2771/RuleAggregation.t.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: MPL-2.0 +pragma solidity ^0.8.20; + +import {RuleEngineOwnable2771} from "src/deployment/ownable/RuleEngineOwnable2771.sol"; +import {RuleAggregationTestBase} from "../utils/RuleAggregationTestBase.sol"; + +/** + * @title RuleAggregationOwnable2771Test + * @notice Rule aggregation tests for `RuleEngineOwnable2771`. + */ +contract RuleAggregationOwnable2771Test is RuleAggregationTestBase { + function _deployEngine(address admin, address token) internal override returns (address) { + return address(new RuleEngineOwnable2771(admin, address(0), token)); + } +} diff --git a/test/RuleEngineOwnable2771/RuleEngineInvariant.t.sol b/test/RuleEngineOwnable2771/RuleEngineInvariant.t.sol new file mode 100644 index 00000000..f7372547 --- /dev/null +++ b/test/RuleEngineOwnable2771/RuleEngineInvariant.t.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: MPL-2.0 +pragma solidity ^0.8.20; + +import {RuleEngineOwnable2771} from "src/deployment/ownable/RuleEngineOwnable2771.sol"; +import {RuleEngineInvariantTestBase} from "../utils/RuleEngineInvariantTestBase.sol"; + +/** + * @title RuleEngineOwnable2771InvariantTest + * @notice Invariant tests over the rule set and the bound tokens for `RuleEngineOwnable2771`. + */ +contract RuleEngineOwnable2771InvariantTest is RuleEngineInvariantTestBase { + function _deployEngine(address admin) internal override returns (address) { + return address(new RuleEngineOwnable2771(admin, address(0), address(0))); + } +} diff --git a/test/RuleEngineOwnable2771/SecurityReview.t.sol b/test/RuleEngineOwnable2771/SecurityReview.t.sol new file mode 100644 index 00000000..dead07b3 --- /dev/null +++ b/test/RuleEngineOwnable2771/SecurityReview.t.sol @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: MPL-2.0 +pragma solidity ^0.8.20; + +import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; +import {RuleEngineOwnable2771} from "src/deployment/ownable/RuleEngineOwnable2771.sol"; +import {SecurityReviewTestBase} from "../utils/SecurityReviewTestBase.sol"; + +/** + * @title SecurityReviewOwnable2771Test + * @notice v3.0.0-rc7 security review tests for `RuleEngineOwnable2771`. + */ +contract SecurityReviewOwnable2771Test is SecurityReviewTestBase { + function _deployEngine(address admin, address token) internal override returns (address) { + return address(new RuleEngineOwnable2771(admin, FORWARDER, token)); + } + + function _unauthorizedRevertData(address caller, bytes32) internal pure override returns (bytes memory) { + return abi.encodeWithSelector(Ownable.OwnableUnauthorizedAccount.selector, caller); + } + + function _renounceAdministration() internal override { + vm.prank(ADMIN); + Ownable(address(engine)).renounceOwnership(); + } +} diff --git a/test/RuleEngineOwnable2Step/NoForwarder.t.sol b/test/RuleEngineOwnable2Step/NoForwarder.t.sol new file mode 100644 index 00000000..da417353 --- /dev/null +++ b/test/RuleEngineOwnable2Step/NoForwarder.t.sol @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: MPL-2.0 +pragma solidity ^0.8.20; + +import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; +import {RuleEngineOwnable2Step} from "src/deployment/ownable/RuleEngineOwnable2Step.sol"; +import {NoForwarderTestBase} from "../utils/NoForwarderTestBase.sol"; + +/** + * @title NoForwarderOwnable2StepTest + * @notice `RuleEngineOwnable2Step` has no ERC-2771 support. + */ +contract NoForwarderOwnable2StepTest is NoForwarderTestBase { + function _deployEngine(address admin, address token) internal override returns (address) { + return address(new RuleEngineOwnable2Step(admin, token)); + } + + function _managerRevertData(address caller) internal pure override returns (bytes memory) { + return abi.encodeWithSelector(Ownable.OwnableUnauthorizedAccount.selector, caller); + } +} diff --git a/test/RuleEngineOwnable2Step/RuleAggregation.t.sol b/test/RuleEngineOwnable2Step/RuleAggregation.t.sol new file mode 100644 index 00000000..f9a76412 --- /dev/null +++ b/test/RuleEngineOwnable2Step/RuleAggregation.t.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: MPL-2.0 +pragma solidity ^0.8.20; + +import {RuleEngineOwnable2Step} from "src/deployment/ownable/RuleEngineOwnable2Step.sol"; +import {RuleAggregationTestBase} from "../utils/RuleAggregationTestBase.sol"; + +/** + * @title RuleAggregationOwnable2StepTest + * @notice Rule aggregation tests for the `RuleEngineOwnable2Step`. + */ +contract RuleAggregationOwnable2StepTest is RuleAggregationTestBase { + function _deployEngine(address admin, address token) internal override returns (address) { + return address(new RuleEngineOwnable2Step(admin, token)); + } +} diff --git a/test/RuleEngineOwnable2Step/RuleEngineInvariant.t.sol b/test/RuleEngineOwnable2Step/RuleEngineInvariant.t.sol new file mode 100644 index 00000000..e8daaa15 --- /dev/null +++ b/test/RuleEngineOwnable2Step/RuleEngineInvariant.t.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: MPL-2.0 +pragma solidity ^0.8.20; + +import {RuleEngineOwnable2Step} from "src/deployment/ownable/RuleEngineOwnable2Step.sol"; +import {RuleEngineInvariantTestBase} from "../utils/RuleEngineInvariantTestBase.sol"; + +/** + * @title RuleEngineOwnable2StepInvariantTest + * @notice Invariant tests over the rule set and the bound tokens for `RuleEngineOwnable2Step`. + */ +contract RuleEngineOwnable2StepInvariantTest is RuleEngineInvariantTestBase { + function _deployEngine(address admin) internal override returns (address) { + return address(new RuleEngineOwnable2Step(admin, address(0))); + } +} diff --git a/test/RuleEngineOwnable2Step/RuleEngineOwnable2Step.t.sol b/test/RuleEngineOwnable2Step/RuleEngineOwnable2Step.t.sol index 9f8dd691..99ca8883 100644 --- a/test/RuleEngineOwnable2Step/RuleEngineOwnable2Step.t.sol +++ b/test/RuleEngineOwnable2Step/RuleEngineOwnable2Step.t.sol @@ -1,10 +1,10 @@ // SPDX-License-Identifier: MPL-2.0 pragma solidity ^0.8.20; +import {ITokenBindingExtended} from "src/interfaces/ITokenBindingExtended.sol"; import {Test} from "forge-std/Test.sol"; import {Vm} from "forge-std/Vm.sol"; import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; -import {MinimalForwarderMock} from "CMTAT/mocks/MinimalForwarderMock.sol"; import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; import {ERC1404ExtendInterfaceId} from "CMTAT/library/ERC1404ExtendInterfaceId.sol"; import {RuleEngineInterfaceId} from "CMTAT/library/RuleEngineInterfaceId.sol"; @@ -20,7 +20,6 @@ import {OwnableInterfaceId} from "src/modules/library/OwnableInterfaceId.sol"; import {Ownable2StepInterfaceId} from "src/modules/library/Ownable2StepInterfaceId.sol"; import {TokenBindingModuleInvariantStorage} from "src/modules/library/TokenBindingModuleInvariantStorage.sol"; import {RulesManagementModuleInvariantStorage} from "src/modules/library/RulesManagementModuleInvariantStorage.sol"; -import {RuleEngineOwnable2StepExposed} from "src/mocks/RuleEngineExposed.sol"; // forge-lint: disable-next-line(unaliased-plain-import) import "../HelperContractOwnable2Step.sol"; @@ -30,11 +29,9 @@ import "../HelperContractOwnable2Step.sol"; contract RuleEngineOwnable2StepTest is Test, HelperContractOwnable2Step { address internal constant TOKEN_1 = address(0x1111); address internal constant TOKEN_2 = address(0x2222); - RuleEngineOwnable2StepExposed internal ruleEngineOwnable2StepExposed; function setUp() public { - ruleEngineMock = new RuleEngineOwnable2Step(OWNER_ADDRESS, ZERO_ADDRESS, ZERO_ADDRESS); - ruleEngineOwnable2StepExposed = new RuleEngineOwnable2StepExposed(OWNER_ADDRESS, ZERO_ADDRESS, ZERO_ADDRESS); + ruleEngineMock = new RuleEngineOwnable2Step(OWNER_ADDRESS, ZERO_ADDRESS); ruleConditionalTransferLight = new RuleConditionalTransferLightMock(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS, ruleEngineMock); } @@ -43,18 +40,25 @@ contract RuleEngineOwnable2StepTest is Test, HelperContractOwnable2Step { assertEq(ruleEngineMock.owner(), OWNER_ADDRESS); } - function testCannotDeployContractIfOwnerAddressIsZero() public { - vm.expectRevert(abi.encodeWithSignature("OwnableInvalidOwner(address)", ZERO_ADDRESS)); - new RuleEngineOwnable2Step(ZERO_ADDRESS, ZERO_ADDRESS, ZERO_ADDRESS); + function testHasRightVersion() public view { + assertEq(ruleEngineMock.version(), "3.0.0-rc7"); } - function testTrustedForwarderSetAtDeployment() public { - MinimalForwarderMock forwarder = new MinimalForwarderMock(); - forwarder.initialize(ERC2771_FORWARDER_DOMAIN); + function testSetTokenSelfBindingApprovalEmitsEvent() public { + vm.expectEmit(true, false, false, true, address(ruleEngineMock)); + emit ITokenBindingExtended.TokenSelfBindingApprovalSet(address(0x7070), true); + vm.prank(OWNER_ADDRESS); + ruleEngineMock.setTokenSelfBindingApproval(address(0x7070), true); - RuleEngineOwnable2Step ruleEngineWithForwarder = - new RuleEngineOwnable2Step(OWNER_ADDRESS, address(forwarder), ZERO_ADDRESS); - assertTrue(ruleEngineWithForwarder.isTrustedForwarder(address(forwarder))); + vm.expectEmit(true, false, false, true, address(ruleEngineMock)); + emit ITokenBindingExtended.TokenSelfBindingApprovalSet(address(0x7070), false); + vm.prank(OWNER_ADDRESS); + ruleEngineMock.setTokenSelfBindingApproval(address(0x7070), false); + } + + function testCannotDeployContractIfOwnerAddressIsZero() public { + vm.expectRevert(abi.encodeWithSignature("OwnableInvalidOwner(address)", ZERO_ADDRESS)); + new RuleEngineOwnable2Step(ZERO_ADDRESS, ZERO_ADDRESS); } function testSupportsOwnableAndComplianceInterfaces() public view { @@ -332,10 +336,12 @@ contract RuleEngineOwnable2StepTest is Test, HelperContractOwnable2Step { ruleEngineMock.bindTokens(tokens); } + /// @notice Batch binding is atomic on purpose (rc7 code-quality review `C-3`): one token already bound + /// reverts the whole batch, including the tokens bound before it in the same call. function testCannotBindTokensBatchWithAlreadyBoundToken() public { address[] memory tokens = new address[](2); - tokens[0] = TOKEN_1; - tokens[1] = TOKEN_2; + tokens[0] = TOKEN_2; + tokens[1] = TOKEN_1; vm.prank(OWNER_ADDRESS); ruleEngineMock.bindToken(TOKEN_1); @@ -343,6 +349,8 @@ contract RuleEngineOwnable2StepTest is Test, HelperContractOwnable2Step { vm.expectRevert(TokenBindingModuleInvariantStorage.TokenBinding_TokenAlreadyBound.selector); vm.prank(OWNER_ADDRESS); ruleEngineMock.bindTokens(tokens); + + assertFalse(ruleEngineMock.isTokenBound(TOKEN_2), "the token before the failing one is rolled back"); } function testCannotUnbindTokensBatchWithTokenNotBound() public { @@ -356,13 +364,23 @@ contract RuleEngineOwnable2StepTest is Test, HelperContractOwnable2Step { vm.expectRevert(TokenBindingModuleInvariantStorage.TokenBinding_TokenNotBound.selector); vm.prank(OWNER_ADDRESS); ruleEngineMock.unbindTokens(tokens); + + assertTrue(ruleEngineMock.isTokenBound(TOKEN_1), "the token before the failing one stays bound"); } - function testMsgDataReturnsCalldata() public view { - bytes memory data = ruleEngineOwnable2StepExposed.exposedMsgData(); - assertEq(data.length, 4); - // forge-lint: disable-next-line(unsafe-typecast) - assertEq(bytes4(data), ruleEngineOwnable2StepExposed.exposedMsgData.selector); + /// @notice An empty batch is a no-op: no revert, no event, no state change (rc7 code-quality review `C-3`). + function testEmptyBindAndUnbindBatchesAreNoOps() public { + address[] memory empty = new address[](0); + uint256 before = ruleEngineMock.getTokenBounds().length; + + vm.recordLogs(); + vm.startPrank(OWNER_ADDRESS); + ruleEngineMock.bindTokens(empty); + ruleEngineMock.unbindTokens(empty); + vm.stopPrank(); + + assertEq(vm.getRecordedLogs().length, 0); + assertEq(ruleEngineMock.getTokenBounds().length, before); } function testMessageForTransferRestrictionWithTransferOKCode() public { diff --git a/test/RuleEngineOwnable2Step/RuleGuard.t.sol b/test/RuleEngineOwnable2Step/RuleGuard.t.sol new file mode 100644 index 00000000..3739f6d7 --- /dev/null +++ b/test/RuleEngineOwnable2Step/RuleGuard.t.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: MPL-2.0 +pragma solidity ^0.8.20; + +import {RuleEngineOwnable2Step} from "src/deployment/ownable/RuleEngineOwnable2Step.sol"; +import {Ownable2StepRuleGuardTestBase} from "../utils/Ownable2StepRuleGuardTestBase.sol"; + +/** + * @title Ownable2StepRuleGuardTest + * @notice v3.0.0-rc7 security review, threat AC-3, for `RuleEngineOwnable2Step`. + */ +contract Ownable2StepRuleGuardTest is Ownable2StepRuleGuardTestBase { + function _deployEngine(address owner_) internal override returns (address) { + return address(new RuleEngineOwnable2Step(owner_, address(0))); + } +} diff --git a/test/RuleEngineOwnable2Step/SecurityReview.t.sol b/test/RuleEngineOwnable2Step/SecurityReview.t.sol new file mode 100644 index 00000000..cb3835ae --- /dev/null +++ b/test/RuleEngineOwnable2Step/SecurityReview.t.sol @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: MPL-2.0 +pragma solidity ^0.8.20; + +import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; +import {RuleEngineOwnable2Step} from "src/deployment/ownable/RuleEngineOwnable2Step.sol"; +import {SecurityReviewTestBase} from "../utils/SecurityReviewTestBase.sol"; + +/** + * @title SecurityReviewOwnable2StepTest + * @notice v3.0.0-rc7 security review tests for `RuleEngineOwnable2Step`. + */ +contract SecurityReviewOwnable2StepTest is SecurityReviewTestBase { + function _deployEngine(address admin, address token) internal override returns (address) { + return address(new RuleEngineOwnable2Step(admin, token)); + } + + function _unauthorizedRevertData(address caller, bytes32) internal pure override returns (bytes memory) { + return abi.encodeWithSelector(Ownable.OwnableUnauthorizedAccount.selector, caller); + } + + function _renounceAdministration() internal override { + vm.prank(ADMIN); + Ownable(address(engine)).renounceOwnership(); + } +} diff --git a/test/RuleEngineOwnable2Step2771/ERC2771TokenGate.t.sol b/test/RuleEngineOwnable2Step2771/ERC2771TokenGate.t.sol new file mode 100644 index 00000000..f8abcf3a --- /dev/null +++ b/test/RuleEngineOwnable2Step2771/ERC2771TokenGate.t.sol @@ -0,0 +1,20 @@ +// SPDX-License-Identifier: MPL-2.0 +pragma solidity ^0.8.20; + +import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; +import {RuleEngineOwnable2Step2771} from "src/deployment/ownable/RuleEngineOwnable2Step2771.sol"; +import {ERC2771TokenGateTestBase} from "../utils/ERC2771TokenGateTestBase.sol"; + +/** + * @title ERC2771TokenGateOwnable2StepTest + * @notice ERC-2771 token-identity gate tests for `RuleEngineOwnable2Step2771`. + */ +contract ERC2771TokenGateOwnable2StepTest is ERC2771TokenGateTestBase { + function _deployEngine(address admin, address forwarder, address token) internal override returns (address) { + return address(new RuleEngineOwnable2Step2771(admin, forwarder, token)); + } + + function _managerRevertData(address caller) internal pure override returns (bytes memory) { + return abi.encodeWithSelector(Ownable.OwnableUnauthorizedAccount.selector, caller); + } +} diff --git a/test/RuleEngineOwnable2Step2771/ERC2771Variant.t.sol b/test/RuleEngineOwnable2Step2771/ERC2771Variant.t.sol new file mode 100644 index 00000000..b8edb9b6 --- /dev/null +++ b/test/RuleEngineOwnable2Step2771/ERC2771Variant.t.sol @@ -0,0 +1,30 @@ +// SPDX-License-Identifier: MPL-2.0 +pragma solidity ^0.8.20; + +import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; +import {RuleEngineOwnable2Step} from "src/deployment/ownable/RuleEngineOwnable2Step.sol"; +import {RuleEngineOwnable2Step2771} from "src/deployment/ownable/RuleEngineOwnable2Step2771.sol"; +import {RuleEngineOwnable2Step2771Exposed} from "src/mocks/RuleEngineExposed.sol"; +import {ERC2771VariantTestBase} from "../utils/ERC2771VariantTestBase.sol"; + +/** + * @title ERC2771VariantOwnable2StepTest + * @notice ERC-2771 variant tests for `RuleEngineOwnable2Step2771`. + */ +contract ERC2771VariantOwnable2StepTest is ERC2771VariantTestBase { + function _deploy2771(address admin, address forwarder, address token) internal override returns (address) { + return address(new RuleEngineOwnable2Step2771(admin, forwarder, token)); + } + + function _deployWithoutForwarder(address admin, address token) internal override returns (address) { + return address(new RuleEngineOwnable2Step(admin, token)); + } + + function _deployExposed(address admin, address forwarder) internal override returns (address) { + return address(new RuleEngineOwnable2Step2771Exposed(admin, forwarder, address(0))); + } + + function _zeroAdminRevertData() internal pure override returns (bytes memory) { + return abi.encodeWithSelector(Ownable.OwnableInvalidOwner.selector, address(0)); + } +} diff --git a/test/RuleEngineOwnable2Step2771/RuleAggregation.t.sol b/test/RuleEngineOwnable2Step2771/RuleAggregation.t.sol new file mode 100644 index 00000000..069707ba --- /dev/null +++ b/test/RuleEngineOwnable2Step2771/RuleAggregation.t.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: MPL-2.0 +pragma solidity ^0.8.20; + +import {RuleEngineOwnable2Step2771} from "src/deployment/ownable/RuleEngineOwnable2Step2771.sol"; +import {RuleAggregationTestBase} from "../utils/RuleAggregationTestBase.sol"; + +/** + * @title RuleAggregationOwnable2Step2771Test + * @notice Rule aggregation tests for `RuleEngineOwnable2Step2771`. + */ +contract RuleAggregationOwnable2Step2771Test is RuleAggregationTestBase { + function _deployEngine(address admin, address token) internal override returns (address) { + return address(new RuleEngineOwnable2Step2771(admin, address(0), token)); + } +} diff --git a/test/RuleEngineOwnable2Step2771/RuleEngineInvariant.t.sol b/test/RuleEngineOwnable2Step2771/RuleEngineInvariant.t.sol new file mode 100644 index 00000000..40c02863 --- /dev/null +++ b/test/RuleEngineOwnable2Step2771/RuleEngineInvariant.t.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: MPL-2.0 +pragma solidity ^0.8.20; + +import {RuleEngineOwnable2Step2771} from "src/deployment/ownable/RuleEngineOwnable2Step2771.sol"; +import {RuleEngineInvariantTestBase} from "../utils/RuleEngineInvariantTestBase.sol"; + +/** + * @title RuleEngineOwnable2Step2771InvariantTest + * @notice Invariant tests over the rule set and the bound tokens for `RuleEngineOwnable2Step2771`. + */ +contract RuleEngineOwnable2Step2771InvariantTest is RuleEngineInvariantTestBase { + function _deployEngine(address admin) internal override returns (address) { + return address(new RuleEngineOwnable2Step2771(admin, address(0), address(0))); + } +} diff --git a/test/RuleEngineOwnable2Step2771/RuleGuard.t.sol b/test/RuleEngineOwnable2Step2771/RuleGuard.t.sol new file mode 100644 index 00000000..5694f045 --- /dev/null +++ b/test/RuleEngineOwnable2Step2771/RuleGuard.t.sol @@ -0,0 +1,15 @@ +// SPDX-License-Identifier: MPL-2.0 +pragma solidity ^0.8.20; + +import {RuleEngineOwnable2Step2771} from "src/deployment/ownable/RuleEngineOwnable2Step2771.sol"; +import {Ownable2StepRuleGuardTestBase} from "../utils/Ownable2StepRuleGuardTestBase.sol"; + +/** + * @title Ownable2Step2771RuleGuardTest + * @notice v3.0.0-rc7 security review, threat AC-3, for `RuleEngineOwnable2Step2771`. + */ +contract Ownable2Step2771RuleGuardTest is Ownable2StepRuleGuardTestBase { + function _deployEngine(address owner_) internal override returns (address) { + return address(new RuleEngineOwnable2Step2771(owner_, address(0xF0F0), address(0))); + } +} diff --git a/test/RuleEngineOwnable2Step2771/SecurityReview.t.sol b/test/RuleEngineOwnable2Step2771/SecurityReview.t.sol new file mode 100644 index 00000000..2bdc454c --- /dev/null +++ b/test/RuleEngineOwnable2Step2771/SecurityReview.t.sol @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: MPL-2.0 +pragma solidity ^0.8.20; + +import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol"; +import {RuleEngineOwnable2Step2771} from "src/deployment/ownable/RuleEngineOwnable2Step2771.sol"; +import {SecurityReviewTestBase} from "../utils/SecurityReviewTestBase.sol"; + +/** + * @title SecurityReviewOwnable2Step2771Test + * @notice v3.0.0-rc7 security review tests for `RuleEngineOwnable2Step2771`. + */ +contract SecurityReviewOwnable2Step2771Test is SecurityReviewTestBase { + function _deployEngine(address admin, address token) internal override returns (address) { + return address(new RuleEngineOwnable2Step2771(admin, FORWARDER, token)); + } + + function _unauthorizedRevertData(address caller, bytes32) internal pure override returns (bytes memory) { + return abi.encodeWithSelector(Ownable.OwnableUnauthorizedAccount.selector, caller); + } + + function _renounceAdministration() internal override { + vm.prank(ADMIN); + Ownable(address(engine)).renounceOwnership(); + } +} diff --git a/test/RuleStandalone/RuleStandaloneCMTAT.t.sol b/test/RuleStandalone/RuleStandaloneCMTAT.t.sol new file mode 100644 index 00000000..7228c0e2 --- /dev/null +++ b/test/RuleStandalone/RuleStandaloneCMTAT.t.sol @@ -0,0 +1,197 @@ +// SPDX-License-Identifier: MPL-2.0 +pragma solidity ^0.8.20; + +import {Test} from "forge-std/Test.sol"; +import {CMTATStandardStandalone} from "CMTAT/deployment/CMTATStandardStandalone.sol"; +import {IRuleEngine} from "CMTAT/interfaces/engine/IRuleEngine.sol"; +import {RuleEngineInterfaceId} from "CMTAT/library/RuleEngineInterfaceId.sol"; +import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; +import {CMTATDeployment} from "../utils/CMTATDeployment.sol"; +import {RuleWhitelistMock} from "src/mocks/rules/validation/RuleWhitelistMock.sol"; +import {RuleConditionalTransferLightMock} from "src/mocks/rules/operation/RuleConditionalTransferLightMock.sol"; +import {RuleMintAllowanceMock} from "src/mocks/rules/operation/RuleMintAllowanceMock.sol"; +import {RuleOperationRevertMock} from "src/mocks/rules/operation/RuleOperationRevertMock.sol"; +import { + RuleConditionalTransferLightInvariantStorage +} from "src/mocks/rules/operation/abstract/RuleConditionalTransferLightInvariantStorage.sol"; +import { + RuleMintAllowanceInvariantStorage +} from "src/mocks/rules/operation/abstract/RuleMintAllowanceInvariantStorage.sol"; + +/** + * @title RuleStandaloneCMTATTest + * @notice A reference rule attached directly to a CMTAT token as its rule engine, with no RuleEngine in + * between (rc7 code-quality review `I-2`). Every reference rule advertises `RULE_ENGINE_INTERFACE_ID` and + * implements the whole engine-facing surface; these tests check that the role works: the token calls the + * rule's `transferred`, `canTransfer` and ERC-1404 views directly, and the rule's codes and messages reach + * the token unchanged. CMTAT only: an ERC-3643 token calls `created` / `destroyed`, which a rule does not have. + */ +contract RuleStandaloneCMTATTest is Test { + address internal constant ADMIN = address(1); // CMTATDeployment admin + address internal constant ALICE = address(0xA11CE); + address internal constant BOB = address(0xB0B); + address internal constant CAROL = address(0xCA201); + + uint8 internal constant CODE_TO_NOT_WHITELISTED = 22; + string internal constant TEXT_TO_NOT_WHITELISTED = "The recipient is not in the whitelist"; + uint8 internal constant CODE_NOT_APPROVED = 71; + string internal constant TEXT_NOT_APPROVED = "ConditionalTransferLight: The request is not approved"; + + CMTATStandardStandalone internal token; + + function setUp() public { + token = new CMTATDeployment().cmtat(); + // Fund ALICE before any rule is attached. + vm.prank(ADMIN); + token.mint(ALICE, 100); + } + + function _attach(address rule) internal { + vm.prank(ADMIN); + token.setRuleEngine(IRuleEngine(rule)); + assertEq(address(token.ruleEngine()), rule); + } + + /* ============ ERC-165 ============ */ + + /// @notice Every reference rule advertises the engine role, using CMTAT's constant. + function testReferenceRulesAdvertiseTheRuleEngineInterface() public { + address[4] memory rules = [ + address(new RuleWhitelistMock(ADMIN, address(0))), + address(new RuleConditionalTransferLightMock(ADMIN, IRuleEngine(address(0)))), + address(new RuleMintAllowanceMock(ADMIN)), + address(new RuleOperationRevertMock()) + ]; + for (uint256 i = 0; i < rules.length; ++i) { + assertTrue(IERC165(rules[i]).supportsInterface(RuleEngineInterfaceId.RULE_ENGINE_INTERFACE_ID)); + } + } + + /* ============ Whitelist ============ */ + + function _whitelistAttached() internal returns (RuleWhitelistMock rule) { + rule = new RuleWhitelistMock(ADMIN, address(0)); + address[] memory listed = new address[](2); + listed[0] = ALICE; + listed[1] = BOB; + vm.prank(ADMIN); + rule.addAddressesToTheList(listed); + _attach(address(rule)); + } + + function testWhitelistStandaloneAllowsListedTransfer() public { + _whitelistAttached(); + assertTrue(token.canTransfer(ALICE, BOB, 10)); + assertEq(token.detectTransferRestriction(ALICE, BOB, 10), 0); + + vm.prank(ALICE); + token.transfer(BOB, 10); + assertEq(token.balanceOf(BOB), 10); + } + + function testWhitelistStandaloneRefusesUnlistedTransferWithItsCodeAndMessage() public { + _whitelistAttached(); + assertFalse(token.canTransfer(ALICE, CAROL, 10)); + assertEq(token.detectTransferRestriction(ALICE, CAROL, 10), CODE_TO_NOT_WHITELISTED); + assertEq(token.messageForTransferRestriction(CODE_TO_NOT_WHITELISTED), TEXT_TO_NOT_WHITELISTED); + + vm.prank(ALICE); + vm.expectRevert( + abi.encodeWithSelector( + RuleWhitelistMock.RuleWhitelist_InvalidTransfer.selector, ALICE, CAROL, 10, CODE_TO_NOT_WHITELISTED + ) + ); + token.transfer(CAROL, 10); + } + + /// @notice `transferFrom` reaches the rule through the 4-argument `transferred`, with the spender. + function testWhitelistStandaloneChecksTheSpender() public { + _whitelistAttached(); + vm.prank(ALICE); + token.approve(CAROL, 10); + assertEq(token.detectTransferRestrictionFrom(CAROL, ALICE, BOB, 10), 23); + + vm.prank(CAROL); + vm.expectRevert( + abi.encodeWithSelector(RuleWhitelistMock.RuleWhitelist_InvalidTransfer.selector, ALICE, BOB, 10, 23) + ); + token.transferFrom(ALICE, BOB, 10); + } + + /* ============ Conditional transfer ============ */ + + function _conditionalAttached() internal returns (RuleConditionalTransferLightMock rule) { + rule = new RuleConditionalTransferLightMock(ADMIN, IRuleEngine(address(0))); + _attach(address(rule)); + } + + function testConditionalTransferStandaloneRefusesUnapprovedTransfer() public { + _conditionalAttached(); + assertFalse(token.canTransfer(ALICE, BOB, 10)); + assertEq(token.detectTransferRestriction(ALICE, BOB, 10), CODE_NOT_APPROVED); + assertEq(token.messageForTransferRestriction(CODE_NOT_APPROVED), TEXT_NOT_APPROVED); + + vm.prank(ALICE); + vm.expectRevert(RuleConditionalTransferLightInvariantStorage.TransferNotApproved.selector); + token.transfer(BOB, 10); + } + + /// @notice The token's call to `transferred` consumes the approval, so it can be used once. + function testConditionalTransferStandaloneConsumesTheApproval() public { + RuleConditionalTransferLightMock rule = _conditionalAttached(); + vm.prank(ADMIN); + rule.approveTransfer(ALICE, BOB, 10); + assertTrue(token.canTransfer(ALICE, BOB, 10)); + + vm.prank(ALICE); + token.transfer(BOB, 10); + assertEq(token.balanceOf(BOB), 10); + // forge-lint: disable-next-line(asm-keccak256) + assertEq(rule.approvalCounts(keccak256(abi.encodePacked(ALICE, BOB, uint256(10)))), 0); + + vm.prank(ALICE); + vm.expectRevert(RuleConditionalTransferLightInvariantStorage.TransferNotApproved.selector); + token.transfer(BOB, 10); + } + + /* ============ Mint allowance ============ */ + + /// @notice CMTAT mints through the 4-argument `transferred` with the minter as spender. + function testMintAllowanceStandaloneConsumesTheMinterAllowance() public { + RuleMintAllowanceMock rule = new RuleMintAllowanceMock(ADMIN); + vm.prank(ADMIN); + rule.setMintAllowance(ADMIN, 50); + _attach(address(rule)); + + vm.prank(ADMIN); + token.mint(BOB, 30); + assertEq(token.balanceOf(BOB), 30); + assertEq(rule.mintAllowance(ADMIN), 20); + + vm.prank(ADMIN); + vm.expectRevert( + abi.encodeWithSelector( + RuleMintAllowanceInvariantStorage.RuleMintAllowance_InsufficientAllowance.selector, ADMIN, 20, 21 + ) + ); + token.mint(BOB, 21); + } + + /// @notice The rule restricts only mints: an ordinary transfer passes. + function testMintAllowanceStandaloneLetsTransfersThrough() public { + _attach(address(new RuleMintAllowanceMock(ADMIN))); + vm.prank(ALICE); + token.transfer(BOB, 10); + assertEq(token.balanceOf(BOB), 10); + } + + /* ============ Reverting rule ============ */ + + /// @notice A rule that reverts in `transferred` blocks the token operation with the rule's own error. + function testRevertingRuleStandaloneBlocksTheTransfer() public { + _attach(address(new RuleOperationRevertMock())); + vm.prank(ALICE); + vm.expectRevert(RuleOperationRevertMock.RuleConditionalTransferLight_InvalidTransfer.selector); + token.transfer(BOB, 10); + } +} diff --git a/test/RuleWhitelist/CMTATIntegrationBase.sol b/test/RuleWhitelist/CMTATIntegrationBase.sol index 2eaa8558..c4fd305c 100644 --- a/test/RuleWhitelist/CMTATIntegrationBase.sol +++ b/test/RuleWhitelist/CMTATIntegrationBase.sol @@ -27,7 +27,7 @@ abstract contract CMTATIntegrationBase is Test, HelperContract { // specific arrange vm.prank(DEFAULT_ADMIN_ADDRESS); - ruleEngineMock = new RuleEngine(DEFAULT_ADMIN_ADDRESS, ZERO_ADDRESS, address(cmtatContract)); + ruleEngineMock = new RuleEngine(DEFAULT_ADMIN_ADDRESS, address(cmtatContract)); vm.prank(DEFAULT_ADMIN_ADDRESS); ruleEngineMock.addRule(ruleWhitelist); diff --git a/test/hardhat/RuleEngine.smoke.js b/test/hardhat/RuleEngine.smoke.js index d0491f19..034c4398 100644 --- a/test/hardhat/RuleEngine.smoke.js +++ b/test/hardhat/RuleEngine.smoke.js @@ -8,16 +8,33 @@ describe("RuleEngine Hardhat smoke test", function () { const RuleEngine = await ethers.getContractFactory("RuleEngine"); const ruleEngine = await RuleEngine.deploy( admin.address, - ethers.ZeroAddress, ethers.ZeroAddress ); await ruleEngine.waitForDeployment(); - expect(await ruleEngine.version()).to.equal("3.0.0"); + expect(await ruleEngine.version()).to.equal("3.0.0-rc7"); expect(await ruleEngine.rulesCount()).to.equal(0n); expect(await ruleEngine.getTokenBound()).to.equal(ethers.ZeroAddress); const defaultAdminRole = await ruleEngine.DEFAULT_ADMIN_ROLE(); expect(await ruleEngine.hasRole(defaultAdminRole, admin.address)).to.equal(true); }); + + it("deploys the ERC-2771 variant with its trusted forwarder", async function () { + const [admin, forwarder] = await ethers.getSigners(); + + const RuleEngine2771 = await ethers.getContractFactory("RuleEngine2771"); + const ruleEngine = await RuleEngine2771.deploy( + admin.address, + forwarder.address, + ethers.ZeroAddress + ); + await ruleEngine.waitForDeployment(); + + expect(await ruleEngine.version()).to.equal("3.0.0-rc7"); + expect(await ruleEngine.isTrustedForwarder(forwarder.address)).to.equal(true); + + const defaultAdminRole = await ruleEngine.DEFAULT_ADMIN_ROLE(); + expect(await ruleEngine.hasRole(defaultAdminRole, admin.address)).to.equal(true); + }); }); diff --git a/test/script/RuleEngineScript.t.sol b/test/script/RuleEngineScript.t.sol index da449eba..3362f5c1 100644 --- a/test/script/RuleEngineScript.t.sol +++ b/test/script/RuleEngineScript.t.sol @@ -5,7 +5,7 @@ import {Test} from "forge-std/Test.sol"; import {CMTATDeployment} from "../utils/CMTATDeployment.sol"; import {CMTATStandardStandalone} from "CMTAT/deployment/CMTATStandardStandalone.sol"; import {RuleEngineScript} from "../../script/RuleEngineScript.s.sol"; -import {RuleEngine} from "src/deployment/RuleEngine.sol"; +import {RuleEngine} from "src/deployment/accessControl/RuleEngine.sol"; /** * @title Test for the RuleEngineScript deployment script diff --git a/test/utils/ERC2771TokenGateTestBase.sol b/test/utils/ERC2771TokenGateTestBase.sol new file mode 100644 index 00000000..1b0f0e6d --- /dev/null +++ b/test/utils/ERC2771TokenGateTestBase.sol @@ -0,0 +1,159 @@ +// SPDX-License-Identifier: MPL-2.0 +pragma solidity ^0.8.20; + +import {Test} from "forge-std/Test.sol"; +import {IRuleEngine} from "CMTAT/interfaces/engine/IRuleEngine.sol"; +import {IERC3643Compliance} from "src/interfaces/IERC3643Compliance.sol"; +import {ITokenBinding} from "src/interfaces/ITokenBinding.sol"; +import {ITokenBindingExtended} from "src/interfaces/ITokenBindingExtended.sol"; +import {IRulesManagementModule} from "src/interfaces/IRulesManagementModule.sol"; +import {IRule} from "src/interfaces/IRule.sol"; +import {RuleMintAllowanceMock} from "src/mocks/rules/operation/RuleMintAllowanceMock.sol"; +import {TokenBindingModuleInvariantStorage} from "src/modules/library/TokenBindingModuleInvariantStorage.sol"; +import {ERC2771ModuleStandalone} from "src/modules/ERC2771ModuleStandalone.sol"; + +/** + * @title ERC2771TokenGateTestBase + * @notice Shared tests pinning that the trusted ERC-2771 forwarder cannot act as a token. + * @dev The token-identity checks (`onlyBoundToken` and the token self-binding path) compare the raw + * `msg.sender`, while administrative checks keep the ERC-2771 `_msgSender()`. + * + * A relayed call is simulated exactly as `ERC2771Context` sees it: the call comes from the forwarder + * address, with the claimed sender appended to the calldata (`_relay`). No signature is involved: + * these tests model a forwarder that relays whatever it is given (buggy, malicious or permissive), + * which is the case the fix protects against. + * + * Each deployable variant inherits this contract and provides its constructor and the revert data of + * its binding-manager check. + */ +abstract contract ERC2771TokenGateTestBase is Test, TokenBindingModuleInvariantStorage { + address internal constant ADMIN = address(0xA11CE); + address internal constant FORWARDER = address(0xF0F0); + address internal constant TOKEN = address(0x7070); + address internal constant TOKEN_2 = address(0x7071); + address internal constant MINTER = address(0x3333); + address internal constant HOLDER = address(0x4444); + + address internal engine; + + /* ============ Variant hooks ============ */ + + /// @dev Deploys the variant with `admin` as admin/owner, `forwarder` as trusted forwarder and `token` bound. + function _deployEngine(address admin, address forwarder, address token) internal virtual returns (address); + + /// @dev Revert data of the variant's binding-manager check when `caller` is not authorized. + function _managerRevertData(address caller) internal view virtual returns (bytes memory); + + /* ============ Setup ============ */ + + function setUp() public virtual { + engine = _deployEngine(ADMIN, FORWARDER, TOKEN); + assertTrue(ERC2771ModuleStandalone(engine).isTrustedForwarder(FORWARDER), "forwarder should be trusted"); + assertTrue(IERC3643Compliance(engine).isTokenBound(TOKEN), "token should be bound"); + } + + /* ============ Helpers ============ */ + + /// @dev Calls the engine from the forwarder with `claimedSender` appended, as ERC-2771 does. + function _relay(address claimedSender, bytes memory data) internal returns (bool ok, bytes memory ret) { + vm.prank(FORWARDER); + (ok, ret) = engine.call(abi.encodePacked(data, claimedSender)); + } + + function _assertRelayRevertsUnauthorizedCaller(bytes memory data) internal { + (bool ok, bytes memory ret) = _relay(TOKEN, data); + assertFalse(ok, "relayed callback should revert"); + assertEq(ret, abi.encodeWithSelector(TokenBinding_UnauthorizedCaller.selector)); + } + + /* ============ Callbacks: the forwarder cannot act as a bound token ============ */ + + /// @notice All four callbacks reject a forwarder relaying a call with a bound token as the claimed sender. + function testForwarderCannotImpersonateBoundTokenOnCallbacks() public { + _assertRelayRevertsUnauthorizedCaller( + abi.encodeWithSignature("transferred(address,address,address,uint256)", MINTER, HOLDER, MINTER, 1) + ); + _assertRelayRevertsUnauthorizedCaller( + abi.encodeWithSignature("transferred(address,address,uint256)", HOLDER, MINTER, 1) + ); + _assertRelayRevertsUnauthorizedCaller(abi.encodeCall(IERC3643Compliance.created, (HOLDER, 1))); + _assertRelayRevertsUnauthorizedCaller(abi.encodeCall(IERC3643Compliance.destroyed, (HOLDER, 1))); + } + + /// @notice A bound token calling the engine directly is unaffected by the fix. + function testBoundTokenCanStillCallCallbacksDirectly() public { + vm.startPrank(TOKEN); + IRuleEngine(engine).transferred(MINTER, HOLDER, MINTER, 1); + IRuleEngine(engine).transferred(HOLDER, MINTER, 1); + IERC3643Compliance(engine).created(HOLDER, 1); + IERC3643Compliance(engine).destroyed(HOLDER, 1); + vm.stopPrank(); + } + + /// @notice A forged mint callback cannot consume a stateful rule's state: the mint quota is untouched, + /// while the same call made directly by the bound token debits it. + function testForgedMintCallbackDoesNotConsumeMintAllowance() public { + RuleMintAllowanceMock mintRule = new RuleMintAllowanceMock(ADMIN); + vm.startPrank(ADMIN); + mintRule.setMintAllowance(MINTER, 100); + IRulesManagementModule(engine).addRule(IRule(address(mintRule))); + vm.stopPrank(); + + _assertRelayRevertsUnauthorizedCaller( + abi.encodeWithSignature("transferred(address,address,address,uint256)", MINTER, address(0), HOLDER, 60) + ); + assertEq(mintRule.mintAllowance(MINTER), 100, "forged callback must not consume the quota"); + + vm.prank(TOKEN); + IRuleEngine(engine).transferred(MINTER, address(0), HOLDER, 60); + assertEq(mintRule.mintAllowance(MINTER), 40, "a real mint callback consumes the quota"); + } + + /* ============ Self-binding: the forwarder cannot act as an approved token ============ */ + + /// @notice The forwarder cannot unbind a token approved for self-binding by claiming to be that token. + function testForwarderCannotUnbindApprovedToken() public { + vm.prank(ADMIN); + ITokenBindingExtended(engine).setTokenSelfBindingApproval(TOKEN, true); + + (bool ok, bytes memory ret) = _relay(TOKEN, abi.encodeCall(ITokenBinding.unbindToken, (TOKEN))); + assertFalse(ok, "relayed self-unbind should revert"); + // The self-binding path no longer matches, so the call falls through to the manager check, + // which resolves the caller through _msgSender() (the claimed token) and rejects it. + assertEq(ret, _managerRevertData(TOKEN)); + assertTrue(IERC3643Compliance(engine).isTokenBound(TOKEN), "token must remain bound"); + } + + /// @notice An approved token can still unbind and re-bind itself directly (ERC-3643 `setCompliance`). + function testApprovedTokenCanStillSelfBindDirectly() public { + vm.prank(ADMIN); + ITokenBindingExtended(engine).setTokenSelfBindingApproval(TOKEN, true); + + vm.startPrank(TOKEN); + IERC3643Compliance(engine).unbindToken(TOKEN); + assertFalse(IERC3643Compliance(engine).isTokenBound(TOKEN)); + IERC3643Compliance(engine).bindToken(TOKEN); + vm.stopPrank(); + assertTrue(IERC3643Compliance(engine).isTokenBound(TOKEN)); + } + + /* ============ Administration remains gasless ============ */ + + /// @notice The binding manager can still bind and unbind a token through the forwarder. + function testManagerCanStillBindThroughForwarder() public { + (bool ok,) = _relay(ADMIN, abi.encodeCall(ITokenBinding.bindToken, (TOKEN_2))); + assertTrue(ok, "relayed bindToken by the manager should succeed"); + assertTrue(IERC3643Compliance(engine).isTokenBound(TOKEN_2)); + + (ok,) = _relay(ADMIN, abi.encodeCall(ITokenBinding.unbindToken, (TOKEN_2))); + assertTrue(ok, "relayed unbindToken by the manager should succeed"); + assertFalse(IERC3643Compliance(engine).isTokenBound(TOKEN_2)); + } + + /// @notice A relayed bind by a non-manager is still rejected by the manager check. + function testNonManagerCannotBindThroughForwarder() public { + (bool ok, bytes memory ret) = _relay(HOLDER, abi.encodeCall(ITokenBinding.bindToken, (TOKEN_2))); + assertFalse(ok); + assertEq(ret, _managerRevertData(HOLDER)); + } +} diff --git a/test/utils/ERC2771VariantTestBase.sol b/test/utils/ERC2771VariantTestBase.sol new file mode 100644 index 00000000..adfcccea --- /dev/null +++ b/test/utils/ERC2771VariantTestBase.sol @@ -0,0 +1,120 @@ +// SPDX-License-Identifier: MPL-2.0 +pragma solidity ^0.8.20; + +import {Test} from "forge-std/Test.sol"; +import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; +import {IAccessControl} from "@openzeppelin/contracts/access/IAccessControl.sol"; +import {IAccessControlEnumerable} from "@openzeppelin/contracts/access/extensions/IAccessControlEnumerable.sol"; +import {RuleEngineInterfaceId} from "CMTAT/library/RuleEngineInterfaceId.sol"; +import {ERC1404ExtendInterfaceId} from "CMTAT/library/ERC1404ExtendInterfaceId.sol"; +import {ERC2771ModuleStandalone} from "src/modules/ERC2771ModuleStandalone.sol"; +import {VersionModule} from "src/modules/VersionModule.sol"; +import {RuleEngineBase} from "src/RuleEngineBase.sol"; +import {ComplianceInterfaceId} from "src/modules/library/ComplianceInterfaceId.sol"; +import {ERC1404InterfaceId} from "src/modules/library/ERC1404InterfaceId.sol"; +import {OwnableInterfaceId} from "src/modules/library/OwnableInterfaceId.sol"; +import {Ownable2StepInterfaceId} from "src/modules/library/Ownable2StepInterfaceId.sol"; + +/// @dev Minimal view of the `*2771Exposed` coverage mocks. +interface IExposedMsgData { + function exposedMsgData() external view returns (bytes memory); +} + +/** + * @title ERC2771VariantTestBase + * @notice Shared tests for the deployables with ERC-2771 support (`RuleEngine2771`, `RuleEngineOwnable2771`, + * `RuleEngineOwnable2Step2771`): the forwarder is trusted, the ERC-2771 context unwraps relayed calls, and the + * variant behaves like its counterpart without a forwarder everywhere else. + */ +abstract contract ERC2771VariantTestBase is Test { + address internal constant ADMIN = address(0xA11CE); + address internal constant FORWARDER = address(0xF0F0); + address internal constant TOKEN = address(0x7070); + + /* ============ Variant hooks ============ */ + + /// @dev Deploys the ERC-2771 variant. + function _deploy2771(address admin, address forwarder, address token) internal virtual returns (address); + + /// @dev Deploys the same access-control variant without ERC-2771. + function _deployWithoutForwarder(address admin, address token) internal virtual returns (address); + + /// @dev Deploys the variant's `*2771Exposed` coverage mock. + function _deployExposed(address admin, address forwarder) internal virtual returns (address); + + /// @dev Revert data of the constructor when the admin/owner is the zero address. + function _zeroAdminRevertData() internal pure virtual returns (bytes memory); + + /* ============ Tests ============ */ + + function testForwarderIsTrusted() public { + ERC2771ModuleStandalone engine = ERC2771ModuleStandalone(_deploy2771(ADMIN, FORWARDER, TOKEN)); + assertTrue(engine.isTrustedForwarder(FORWARDER)); + assertFalse(engine.isTrustedForwarder(ADMIN)); + assertEq(engine.trustedForwarder(), FORWARDER); + } + + /// @notice Security review FW-1 (review item H-3): a `*2771` contract deployed with `address(0)` as forwarder + /// is accepted. No caller can be `address(0)`, so the contract behaves as the variant without forwarder, but + /// it still advertises a forwarder that cannot exist. This test pins the current behaviour. + function testZeroForwarderIsAccepted() public { + address engine = _deploy2771(ADMIN, address(0), TOKEN); + assertEq(ERC2771ModuleStandalone(engine).trustedForwarder(), address(0)); + assertTrue(ERC2771ModuleStandalone(engine).isTrustedForwarder(address(0))); + + vm.prank(ADMIN); + RuleEngineBase(engine).setMaxRules(5); + assertEq(RuleEngineBase(engine).maxRules(), 5); + } + + function testHasRightVersion() public { + assertEq(VersionModule(_deploy2771(ADMIN, FORWARDER, TOKEN)).version(), "3.0.0-rc7"); + } + + function testCannotDeployIfAdminIsZero() public { + vm.expectRevert(_zeroAdminRevertData()); + this.deploy2771External(address(0), FORWARDER, address(0)); + } + + /// @dev External wrapper so `vm.expectRevert` applies to the constructor call alone. + function deploy2771External(address admin, address forwarder, address token) external returns (address) { + return _deploy2771(admin, forwarder, token); + } + + /// @notice ERC-2771 has no ERC-165 id: the variant advertises exactly what its counterpart advertises. + function testAdvertisesTheSameInterfacesAsTheVariantWithoutForwarder() public { + IERC165 withForwarder = IERC165(_deploy2771(ADMIN, FORWARDER, TOKEN)); + IERC165 without = IERC165(_deployWithoutForwarder(ADMIN, TOKEN)); + bytes4[13] memory ids = [ + type(IERC165).interfaceId, + RuleEngineInterfaceId.RULE_ENGINE_INTERFACE_ID, + ERC1404InterfaceId.IERC1404_INTERFACE_ID, + ERC1404ExtendInterfaceId.ERC1404EXTEND_INTERFACE_ID, + ComplianceInterfaceId.ERC3643_COMPLIANCE_INTERFACE_ID, + ComplianceInterfaceId.ERC3643_COMPLIANCE_EXTENDED_INTERFACE_ID, + ComplianceInterfaceId.IERC7551_COMPLIANCE_INTERFACE_ID, + OwnableInterfaceId.IERC173_INTERFACE_ID, + Ownable2StepInterfaceId.IOWNABLE2STEP_INTERFACE_ID, + type(IAccessControl).interfaceId, + type(IAccessControlEnumerable).interfaceId, + bytes4(0x00000000), + bytes4(0xffffffff) + ]; + for (uint256 i = 0; i < ids.length; ++i) { + assertEq(withForwarder.supportsInterface(ids[i]), without.supportsInterface(ids[i])); + } + } + + /// @notice `_msgData` returns the plain calldata on a direct call, and strips the sender on a relayed one. + function testMsgDataStripsTheRelayedSender() public { + IExposedMsgData exposed = IExposedMsgData(_deployExposed(ADMIN, FORWARDER)); + bytes memory selector = abi.encodeCall(exposed.exposedMsgData, ()); + + assertEq(exposed.exposedMsgData(), selector); + + vm.prank(FORWARDER); + (bool ok, bytes memory ret) = address(exposed).call(abi.encodePacked(selector, ADMIN)); + assertTrue(ok); + assertEq(abi.decode(ret, (bytes)), selector); + } +} diff --git a/test/utils/LegacyIRuleIdProbe.sol b/test/utils/LegacyIRuleIdProbe.sol new file mode 100644 index 00000000..cfcf0d04 --- /dev/null +++ b/test/utils/LegacyIRuleIdProbe.sol @@ -0,0 +1,18 @@ +// SPDX-License-Identifier: MPL-2.0 +pragma solidity ^0.8.20; + +import {ERC165} from "@openzeppelin/contracts/utils/introspection/ERC165.sol"; + +/** + * @title LegacyIRuleIdProbe + * @notice Test-only contract that advertises the pre-narrowing `IRule` ID `0x2497d6cb` (with `canTransfer` and + * `canTransferFrom`) and not the current one, like a rule built against v3.0.0-rc6 or earlier. The engine + * still accepts that legacy ID (rc7 code-quality review `I-1`). + */ +contract LegacyIRuleIdProbe is ERC165 { + bytes4 public constant LEGACY_IRULE_INTERFACE_ID = 0x2497d6cb; + + function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { + return interfaceId == LEGACY_IRULE_INTERFACE_ID || ERC165.supportsInterface(interfaceId); + } +} diff --git a/test/utils/NoForwarderTestBase.sol b/test/utils/NoForwarderTestBase.sol new file mode 100644 index 00000000..68571591 --- /dev/null +++ b/test/utils/NoForwarderTestBase.sol @@ -0,0 +1,55 @@ +// SPDX-License-Identifier: MPL-2.0 +pragma solidity ^0.8.20; + +import {Test} from "forge-std/Test.sol"; +import {ITokenBinding} from "src/interfaces/ITokenBinding.sol"; + +/** + * @title NoForwarderTestBase + * @notice Shared tests for the deployables without ERC-2771 (`RuleEngine`, `RuleEngineOwnable`, + * `RuleEngineOwnable2Step`): they expose no forwarder and never read a sender appended to the calldata. + */ +abstract contract NoForwarderTestBase is Test { + address internal constant ADMIN = address(0xA11CE); + address internal constant RELAYER = address(0xF0F0); + address internal constant TOKEN = address(0x7070); + + address internal engine; + + /* ============ Variant hooks ============ */ + + /// @dev Deploys the variant with `admin` as admin/owner and `token` bound (or none). + function _deployEngine(address admin, address token) internal virtual returns (address); + + /// @dev Revert data of the variant's binding-manager check when `caller` is not authorized. + function _managerRevertData(address caller) internal view virtual returns (bytes memory); + + function setUp() public virtual { + engine = _deployEngine(ADMIN, address(0)); + } + + /* ============ Tests ============ */ + + /// @notice There is no ERC-2771 surface: `isTrustedForwarder` / `trustedForwarder` do not exist. + function testHasNoTrustedForwarder() public { + (bool ok,) = engine.call(abi.encodeWithSignature("isTrustedForwarder(address)", RELAYER)); + assertFalse(ok, "must not expose isTrustedForwarder"); + (ok,) = engine.call(abi.encodeWithSignature("trustedForwarder()")); + assertFalse(ok, "must not expose trustedForwarder"); + } + + /// @notice A sender appended to the calldata is ignored: the caller is always the raw `msg.sender`. + function testAppendedSenderIsIgnored() public { + vm.prank(RELAYER); + (bool ok, bytes memory ret) = + engine.call(abi.encodePacked(abi.encodeCall(ITokenBinding.bindToken, (TOKEN)), ADMIN)); + assertFalse(ok, "an appended admin address must not authorize the call"); + assertEq(ret, _managerRevertData(RELAYER)); + assertFalse(ITokenBinding(engine).isTokenBound(TOKEN)); + + // The same call made by the admin itself succeeds. + vm.prank(ADMIN); + ITokenBinding(engine).bindToken(TOKEN); + assertTrue(ITokenBinding(engine).isTokenBound(TOKEN)); + } +} diff --git a/test/utils/Ownable2StepRuleGuardTestBase.sol b/test/utils/Ownable2StepRuleGuardTestBase.sol new file mode 100644 index 00000000..bb111717 --- /dev/null +++ b/test/utils/Ownable2StepRuleGuardTestBase.sol @@ -0,0 +1,73 @@ +// SPDX-License-Identifier: MPL-2.0 +pragma solidity ^0.8.20; + +import {Test} from "forge-std/Test.sol"; +import {Ownable2Step} from "@openzeppelin/contracts/access/Ownable2Step.sol"; +import {RuleEngineBase} from "src/RuleEngineBase.sol"; +import {RulesManagementModuleInvariantStorage} from "src/modules/library/RulesManagementModuleInvariantStorage.sol"; +import {RuleCodeProbe} from "./RuleCodeProbe.sol"; + +/** + * @title Ownable2StepRuleGuardTestBase + * @notice Security review, threat AC-3 / finding F-1, for the two `Ownable2Step` deployables. The guard that + * keeps rule accounts away from ownership runs at nomination (`transferOwnership`) and again at acceptance + * (`acceptOwnership`), so an address that becomes a rule while it is the pending owner cannot accept. + */ +abstract contract Ownable2StepRuleGuardTestBase is Test { + address internal constant OWNER = address(0xA11CE); + + RuleEngineBase internal engine; + RuleCodeProbe internal nominee; + + /// @dev Deploys the variant with `owner_` as owner and no token bound. + function _deployEngine(address owner_) internal virtual returns (address); + + function setUp() public virtual { + engine = RuleEngineBase(_deployEngine(OWNER)); + nominee = new RuleCodeProbe(10, "nominee"); + } + + /// @notice AC-3. Nominating an address that is already a rule is rejected. + function testCannotNominateACurrentRule() public { + vm.startPrank(OWNER); + engine.addRule(nominee); + vm.expectRevert( + RulesManagementModuleInvariantStorage.RuleEngine_RulesManagementModule_RuleAccountCannotReceivePrivileges + .selector + ); + Ownable2Step(address(engine)).transferOwnership(address(nominee)); + vm.stopPrank(); + } + + /// @notice F-1 regression (was the AC-3 proof of concept). A nominee added as a rule before it accepts + /// cannot accept: the engine can no longer end up owned by one of its own rules. + function testNomineeAddedAsRuleBeforeAcceptingCannotAccept() public { + vm.startPrank(OWNER); + Ownable2Step(address(engine)).transferOwnership(address(nominee)); + engine.addRule(nominee); + vm.stopPrank(); + + vm.expectRevert( + RulesManagementModuleInvariantStorage.RuleEngine_RulesManagementModule_RuleAccountCannotReceivePrivileges + .selector + ); + vm.prank(address(nominee)); + Ownable2Step(address(engine)).acceptOwnership(); + + assertEq(Ownable2Step(address(engine)).owner(), OWNER); + assertEq(Ownable2Step(address(engine)).pendingOwner(), address(nominee)); + } + + /// @notice F-1. Once the owner removes the nominee from the rule set, the pending transfer completes. + function testNomineeCanAcceptOnceRemovedFromRules() public { + vm.startPrank(OWNER); + Ownable2Step(address(engine)).transferOwnership(address(nominee)); + engine.addRule(nominee); + engine.removeRule(nominee); + vm.stopPrank(); + + vm.prank(address(nominee)); + Ownable2Step(address(engine)).acceptOwnership(); + assertEq(Ownable2Step(address(engine)).owner(), address(nominee)); + } +} diff --git a/test/utils/ReentrantAdminRule.sol b/test/utils/ReentrantAdminRule.sol new file mode 100644 index 00000000..70dfd554 --- /dev/null +++ b/test/utils/ReentrantAdminRule.sol @@ -0,0 +1,51 @@ +// SPDX-License-Identifier: MPL-2.0 +pragma solidity ^0.8.20; + +import {ERC165, IERC165} from "@openzeppelin/contracts/utils/introspection/ERC165.sol"; +import {IRule} from "src/interfaces/IRule.sol"; +import {IRulesManagementModule} from "src/interfaces/IRulesManagementModule.sol"; +import {RuleInterfaceId} from "src/modules/library/RuleInterfaceId.sol"; + +/** + * @title ReentrantAdminRule + * @notice Test-only rule that, when the engine calls its `transferred` hook, calls back into the engine to add + * another rule. Used to show that a rule cannot reconfigure the engine from inside a callback, because rule + * accounts hold no role and no ownership (security review, threats RE-4 and AC-2). + */ +contract ReentrantAdminRule is IRule, ERC165 { + IRulesManagementModule public immutable ENGINE; + IRule public immutable RULE_TO_ADD; + + constructor(IRulesManagementModule engine, IRule ruleToAdd) { + ENGINE = engine; + RULE_TO_ADD = ruleToAdd; + } + + function transferred(address, address, uint256) external override { + ENGINE.addRule(RULE_TO_ADD); + } + + function transferred(address, address, address, uint256) external override { + ENGINE.addRule(RULE_TO_ADD); + } + + function detectTransferRestriction(address, address, uint256) external pure override returns (uint8) { + return 0; + } + + function detectTransferRestrictionFrom(address, address, address, uint256) external pure override returns (uint8) { + return 0; + } + + function canReturnTransferRestrictionCode(uint8) external pure override returns (bool) { + return false; + } + + function messageForTransferRestriction(uint8) external pure override returns (string memory) { + return ""; + } + + function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) { + return interfaceId == RuleInterfaceId.IRULE_INTERFACE_ID || ERC165.supportsInterface(interfaceId); + } +} diff --git a/test/utils/RevertingViewRule.sol b/test/utils/RevertingViewRule.sol new file mode 100644 index 00000000..24325aa8 --- /dev/null +++ b/test/utils/RevertingViewRule.sol @@ -0,0 +1,40 @@ +// SPDX-License-Identifier: MPL-2.0 +pragma solidity ^0.8.20; + +import {ERC165, IERC165} from "@openzeppelin/contracts/utils/introspection/ERC165.sol"; +import {IRule} from "src/interfaces/IRule.sol"; +import {RuleInterfaceId} from "src/modules/library/RuleInterfaceId.sol"; + +/** + * @title RevertingViewRule + * @notice Test-only rule whose enforcement hooks accept every operation while every view reverts. Used to show + * that the engine's ERC-1404 / ERC-3643 views propagate a rule's revert instead of returning a code, and that + * the views and the enforcement path can then disagree (security review, threat RE-2). + */ +contract RevertingViewRule is IRule, ERC165 { + error RevertingViewRule_ViewReverted(); + + function transferred(address, address, uint256) external pure override {} + + function transferred(address, address, address, uint256) external pure override {} + + function detectTransferRestriction(address, address, uint256) external pure override returns (uint8) { + revert RevertingViewRule_ViewReverted(); + } + + function detectTransferRestrictionFrom(address, address, address, uint256) external pure override returns (uint8) { + revert RevertingViewRule_ViewReverted(); + } + + function canReturnTransferRestrictionCode(uint8) external pure override returns (bool) { + revert RevertingViewRule_ViewReverted(); + } + + function messageForTransferRestriction(uint8) external pure override returns (string memory) { + revert RevertingViewRule_ViewReverted(); + } + + function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) { + return interfaceId == RuleInterfaceId.IRULE_INTERFACE_ID || ERC165.supportsInterface(interfaceId); + } +} diff --git a/test/utils/RuleAggregationTestBase.sol b/test/utils/RuleAggregationTestBase.sol new file mode 100644 index 00000000..91d152a9 --- /dev/null +++ b/test/utils/RuleAggregationTestBase.sol @@ -0,0 +1,193 @@ +// SPDX-License-Identifier: MPL-2.0 +pragma solidity ^0.8.20; + +import {Test} from "forge-std/Test.sol"; +import {IRuleEngine} from "CMTAT/interfaces/engine/IRuleEngine.sol"; +import {IERC3643Compliance} from "src/interfaces/IERC3643Compliance.sol"; +import {IRulesManagementModule} from "src/interfaces/IRulesManagementModule.sol"; +import {IRule} from "src/interfaces/IRule.sol"; +import {RuleEngineBase} from "src/RuleEngineBase.sol"; +import {RuleCodeProbe} from "./RuleCodeProbe.sol"; +import {LegacyIRuleIdProbe} from "./LegacyIRuleIdProbe.sol"; +import {RuleEngineInvariantStorage} from "src/modules/library/RuleEngineInvariantStorage.sol"; +import {RuleInterfaceId} from "src/modules/library/RuleInterfaceId.sol"; + +/** + * @title RuleAggregationTestBase + * @notice Shared tests pinning how the engine aggregates the answers of several rules, run for every + * deployable variant. + * @dev Two `RuleCodeProbe` rules are added in order (`first`, then `second`), with no removal, so the + * engine iterates them in insertion order. The probes' answers are set per test, which lets the + * assertions use independently known values rather than recomputing the engine's logic. + */ +abstract contract RuleAggregationTestBase is Test { + address internal constant ADMIN = address(0xA11CE); + address internal constant TOKEN = address(0x7070); + address internal constant SPENDER = address(0x5555); + address internal constant FROM = address(0x1111); + address internal constant TO = address(0x2222); + + uint8 internal constant FIRST_CLAIMED = 10; + uint8 internal constant SECOND_CLAIMED = 20; + + RuleEngineBase internal engine; + RuleCodeProbe internal first; + RuleCodeProbe internal second; + + /* ============ Variant hook ============ */ + + /// @dev Deploys the variant with `admin` as admin/owner, no forwarder and `token` bound. + function _deployEngine(address admin, address token) internal virtual returns (address); + + /* ============ Setup ============ */ + + function setUp() public virtual { + engine = RuleEngineBase(_deployEngine(ADMIN, TOKEN)); + first = new RuleCodeProbe(FIRST_CLAIMED, "first rule message"); + second = new RuleCodeProbe(SECOND_CLAIMED, "second rule message"); + vm.startPrank(ADMIN); + IRulesManagementModule(address(engine)).addRule(IRule(address(first))); + IRulesManagementModule(address(engine)).addRule(IRule(address(second))); + vm.stopPrank(); + assertEq(engine.rule(0), address(first)); + assertEq(engine.rule(1), address(second)); + } + + /* ============ IRule interface gate ============ */ + + /// @notice An engine-only rule is accepted: the probes implement `IRule` without `canTransfer` / + /// `canTransferFrom` (both added in `setUp`), and the engine never needs them. + function testEngineOnlyRuleWithoutComplianceReadsIsAccepted() public { + assertTrue(first.supportsInterface(RuleInterfaceId.IRULE_INTERFACE_ID)); + (bool ok,) = address(first).call(abi.encodeWithSignature("canTransfer(address,address,uint256)", FROM, TO, 1)); + assertFalse(ok, "the probe has no canTransfer"); + assertTrue(IRulesManagementModule(address(engine)).containsRule(IRule(address(first)))); + } + + /// @notice A rule advertising only the legacy ID `0x2497d6cb` (the interface before rc7, a superset of the + /// current one) is still accepted. + function testRuleAdvertisingOnlyTheLegacyIdIsAccepted() public { + LegacyIRuleIdProbe legacy = new LegacyIRuleIdProbe(); + assertFalse(legacy.supportsInterface(RuleInterfaceId.IRULE_INTERFACE_ID)); + vm.prank(ADMIN); + IRulesManagementModule(address(engine)).addRule(IRule(address(legacy))); + assertTrue(IRulesManagementModule(address(engine)).containsRule(IRule(address(legacy)))); + } + + /// @notice A contract that implements ERC-165 but advertises neither rule ID is rejected. + function testRuleAdvertisingNoRuleIdIsRejected() public { + RuleCodeProbe probe = new RuleCodeProbe(1, "m"); + vm.mockCall( + address(probe), + abi.encodeWithSignature("supportsInterface(bytes4)", RuleInterfaceId.IRULE_INTERFACE_ID), + abi.encode(false) + ); + vm.prank(ADMIN); + vm.expectRevert(RuleEngineInvariantStorage.RuleEngine_RuleInvalidInterface.selector); + IRulesManagementModule(address(engine)).addRule(IRule(address(probe))); + } + + /// @notice A contract that answers `true` to every interface ID, including the invalid `0xffffffff`, does not + /// implement ERC-165 correctly and is rejected, although it claims both rule IDs. + function testRuleClaimingEveryInterfaceIsRejected() public { + RuleCodeProbe probe = new RuleCodeProbe(1, "m"); + vm.mockCall(address(probe), abi.encodeWithSignature("supportsInterface(bytes4)"), abi.encode(true)); + vm.mockCall(address(probe), abi.encodeWithSelector(bytes4(0x01ffc9a7)), abi.encode(true)); + vm.prank(ADMIN); + vm.expectRevert(RuleEngineInvariantStorage.RuleEngine_RuleInvalidInterface.selector); + IRulesManagementModule(address(engine)).addRule(IRule(address(probe))); + } + + /// @notice An account with no ERC-165 support (here an EOA) is rejected before any rule ID is queried. + function testRuleWithoutErc165IsRejected() public { + vm.prank(ADMIN); + vm.expectRevert(RuleEngineInvariantStorage.RuleEngine_RuleInvalidInterface.selector); + IRulesManagementModule(address(engine)).addRule(IRule(address(0xBEEF))); + } + + /* ============ detectTransferRestriction / canTransfer ============ */ + + /// @notice The 3-argument view returns the first non-zero code in rule order, or 0 when every rule allows. + function testFuzz_DetectReturnsFirstNonZeroCode(uint8 codeFirst, uint8 codeSecond) public { + first.setCodes(codeFirst, 0); + second.setCodes(codeSecond, 0); + uint8 expected = codeFirst != 0 ? codeFirst : codeSecond; + + assertEq(engine.detectTransferRestriction(FROM, TO, 1), expected); + assertEq(engine.canTransfer(FROM, TO, 1), expected == 0); + } + + /// @notice The 4-argument view consults the rules' 4-argument answers, not their 3-argument ones. + function testFuzz_DetectFromReturnsFirstNonZeroCode(uint8 codeFirst, uint8 codeSecond) public { + // The 3-argument answers are the opposite, so using the wrong path changes the result. + first.setCodes(codeFirst == 0 ? 99 : 0, codeFirst); + second.setCodes(codeSecond == 0 ? 99 : 0, codeSecond); + uint8 expected = codeFirst != 0 ? codeFirst : codeSecond; + + assertEq(engine.detectTransferRestrictionFrom(SPENDER, FROM, TO, 1), expected); + assertEq(engine.canTransferFrom(SPENDER, FROM, TO, 1), expected == 0); + } + + /// @notice Boundary codes: the smallest non-zero code (1) and the largest (255) are both reported. + function testBoundaryCodesAreReported() public { + first.setCodes(1, 1); + assertEq(engine.detectTransferRestriction(FROM, TO, 1), 1); + assertEq(engine.detectTransferRestrictionFrom(SPENDER, FROM, TO, 1), 1); + assertFalse(engine.canTransfer(FROM, TO, 1)); + + first.setCodes(0, 0); + second.setCodes(255, 255); + assertEq(engine.detectTransferRestriction(FROM, TO, 1), 255); + assertEq(engine.detectTransferRestrictionFrom(SPENDER, FROM, TO, 1), 255); + assertFalse(engine.canTransferFrom(SPENDER, FROM, TO, 1)); + } + + /* ============ messageForTransferRestriction ============ */ + + /// @notice The message comes from the rule that claims the code, wherever it sits in the rule set. + function testMessageComesFromTheClaimingRule() public view { + assertEq(engine.messageForTransferRestriction(FIRST_CLAIMED), "first rule message"); + assertEq(engine.messageForTransferRestriction(SECOND_CLAIMED), "second rule message"); + assertEq(engine.messageForTransferRestriction(0), "NoRestriction"); + assertEq(engine.messageForTransferRestriction(77), "Unknown restriction code"); + } + + /* ============ transferred: every rule runs ============ */ + + /// @notice Each callback runs every rule: a rejection by the second rule reverts the 3-argument path. + function testTransferredRunsTheSecondRule() public { + second.setCodes(42, 0); + vm.startPrank(TOKEN); + vm.expectRevert(abi.encodeWithSelector(RuleCodeProbe.RuleCodeProbe_Rejected.selector, 42)); + IRuleEngine(address(engine)).transferred(FROM, TO, 1); + vm.expectRevert(abi.encodeWithSelector(RuleCodeProbe.RuleCodeProbe_Rejected.selector, 42)); + IERC3643Compliance(address(engine)).created(TO, 1); + vm.expectRevert(abi.encodeWithSelector(RuleCodeProbe.RuleCodeProbe_Rejected.selector, 42)); + IERC3643Compliance(address(engine)).destroyed(FROM, 1); + // The 4-argument path uses the rules' 4-argument hook, whose code is still 0. + IRuleEngine(address(engine)).transferred(SPENDER, FROM, TO, 1); + vm.stopPrank(); + } + + /// @notice A rejection by the second rule reverts the 4-argument path. + function testTransferredFromRunsTheSecondRule() public { + second.setCodes(0, 43); + vm.prank(TOKEN); + vm.expectRevert(abi.encodeWithSelector(RuleCodeProbe.RuleCodeProbe_Rejected.selector, 43)); + IRuleEngine(address(engine)).transferred(SPENDER, FROM, TO, 1); + } + + /// @notice `created` and `destroyed` forward the zero address on the correct side. + function testCreatedAndDestroyedForwardTheZeroAddressOnTheRightSide() public { + vm.startPrank(TOKEN); + vm.expectCall( + address(first), abi.encodeWithSignature("transferred(address,address,uint256)", address(0), TO, 5) + ); + IERC3643Compliance(address(engine)).created(TO, 5); + vm.expectCall( + address(first), abi.encodeWithSignature("transferred(address,address,uint256)", FROM, address(0), 7) + ); + IERC3643Compliance(address(engine)).destroyed(FROM, 7); + vm.stopPrank(); + } +} diff --git a/test/utils/RuleCodeProbe.sol b/test/utils/RuleCodeProbe.sol new file mode 100644 index 00000000..05b442b3 --- /dev/null +++ b/test/utils/RuleCodeProbe.sol @@ -0,0 +1,62 @@ +// SPDX-License-Identifier: MPL-2.0 +pragma solidity ^0.8.20; + +import {ERC165, IERC165} from "@openzeppelin/contracts/utils/introspection/ERC165.sol"; +import {IRule} from "src/interfaces/IRule.sol"; +import {RuleInterfaceId} from "src/modules/library/RuleInterfaceId.sol"; + +/** + * @title RuleCodeProbe + * @notice Test-only rule whose answers are set by the test: the restriction code of each view path, the code + * it claims and the message for it. Used to pin how the engine aggregates several rules. + * @dev The 3-argument and 4-argument paths have separate codes so a test can tell which path the engine used. + * Each `transferred` overload reverts with the code of its own path when that code is non-zero. + * Implements only `IRule`, with no `canTransfer` / `canTransferFrom`: an engine-only rule, which the narrowed + * interface accepts (rc7 code-quality review `I-1`). + */ +contract RuleCodeProbe is IRule, ERC165 { + error RuleCodeProbe_Rejected(uint8 code); + + uint8 public code; + uint8 public codeFrom; + uint8 public immutable CLAIMED_CODE; + string public message; + + constructor(uint8 claimedCode, string memory message_) { + CLAIMED_CODE = claimedCode; + message = message_; + } + + function setCodes(uint8 code_, uint8 codeFrom_) external { + code = code_; + codeFrom = codeFrom_; + } + + function transferred(address, address, uint256) external view override { + require(code == 0, RuleCodeProbe_Rejected(code)); + } + + function transferred(address, address, address, uint256) external view override { + require(codeFrom == 0, RuleCodeProbe_Rejected(codeFrom)); + } + + function detectTransferRestriction(address, address, uint256) external view override returns (uint8) { + return code; + } + + function detectTransferRestrictionFrom(address, address, address, uint256) external view override returns (uint8) { + return codeFrom; + } + + function canReturnTransferRestrictionCode(uint8 restrictionCode) external view override returns (bool) { + return restrictionCode == CLAIMED_CODE; + } + + function messageForTransferRestriction(uint8 restrictionCode) external view override returns (string memory) { + return restrictionCode == CLAIMED_CODE ? message : "RuleCodeProbe: unclaimed code"; + } + + function supportsInterface(bytes4 interfaceId) public view virtual override(ERC165, IERC165) returns (bool) { + return interfaceId == RuleInterfaceId.IRULE_INTERFACE_ID || ERC165.supportsInterface(interfaceId); + } +} diff --git a/test/utils/RuleEngineInvariantTestBase.sol b/test/utils/RuleEngineInvariantTestBase.sol new file mode 100644 index 00000000..7f9c82b4 --- /dev/null +++ b/test/utils/RuleEngineInvariantTestBase.sol @@ -0,0 +1,291 @@ +// SPDX-License-Identifier: MPL-2.0 +pragma solidity ^0.8.20; + +import {Test} from "forge-std/Test.sol"; +import {IRule} from "src/interfaces/IRule.sol"; +import {RuleEngineBase} from "src/RuleEngineBase.sol"; +import {RuleInterfaceId} from "src/modules/library/RuleInterfaceId.sol"; +import {RuleInvalidMock} from "src/mocks/RuleInvalidMock.sol"; +import {RuleCodeProbe} from "./RuleCodeProbe.sol"; +import {LegacyIRuleIdProbe} from "./LegacyIRuleIdProbe.sol"; + +/** + * @title RuleEngineHandler + * @notice Drives random sequences of administrative calls on one engine, as its admin/owner, and keeps a + * model of the rule set and of the bound tokens. The model is updated from the semantics of each call that + * succeeded, never by reading the engine, so the invariants compare two independent sources. + * @dev Inputs are indices into fixed pools, so the fuzzer hits duplicates, already-bound tokens, invalid + * rules and `address(0)` often. Every call is wrapped in try/catch: a revert must leave the state unchanged, + * and the model is only touched on success. + */ +contract RuleEngineHandler is Test { + RuleEngineBase internal immutable ENGINE; + address internal immutable ADMIN; + + /// @dev Candidate rules: valid probes, one legacy-ID probe, one contract without the rule ID, address(0). + address[] public rulePool; + /// @dev Candidate tokens, including address(0). + address[] public tokenPool; + + mapping(address => bool) public modelHasRule; + mapping(address => bool) public modelIsBound; + uint256 public modelRuleCount; + uint256 public modelBoundCount; + uint256 public modelMaxRules; + + /// @dev Number of calls that succeeded, per kind; lets a test check the fuzzer exercised the paths. + mapping(bytes32 => uint256) public successes; + + constructor(RuleEngineBase engine_, address admin_) { + ENGINE = engine_; + ADMIN = admin_; + for (uint8 i = 0; i < 4; ++i) { + rulePool.push(address(new RuleCodeProbe(10 + i, "probe"))); + } + rulePool.push(address(new LegacyIRuleIdProbe())); + rulePool.push(address(new RuleInvalidMock())); + rulePool.push(address(0)); + tokenPool.push(address(0x7071)); + tokenPool.push(address(0x7072)); + tokenPool.push(address(0x7073)); + tokenPool.push(address(0x7074)); + tokenPool.push(address(0)); + modelMaxRules = engine_.maxRules(); + } + + /* ============ Pool helpers ============ */ + + function rulePoolLength() external view returns (uint256) { + return rulePool.length; + } + + function tokenPoolLength() external view returns (uint256) { + return tokenPool.length; + } + + function _rule(uint256 seed) internal view returns (address) { + return rulePool[seed % rulePool.length]; + } + + /// @dev One draw in three is a rule-pool address, so the fuzzer also tries to bind rules (F-3). + function _token(uint256 seed) internal view returns (address) { + if (seed % 3 == 0) { + return rulePool[(seed / 3) % rulePool.length]; + } + return tokenPool[seed % tokenPool.length]; + } + + function _isAcceptedRule(address r) internal view returns (bool) { + return r != address(0) && r != rulePool[rulePool.length - 2]; + } + + /* ============ Rule set ============ */ + + function addRule(uint256 seed) external { + address r = _rule(seed); + vm.prank(ADMIN); + try ENGINE.addRule(IRule(r)) { + modelHasRule[r] = true; + ++modelRuleCount; + ++successes["addRule"]; + } catch {} + } + + function removeRule(uint256 seed) external { + address r = _rule(seed); + vm.prank(ADMIN); + try ENGINE.removeRule(IRule(r)) { + modelHasRule[r] = false; + --modelRuleCount; + ++successes["removeRule"]; + } catch {} + } + + function setRules(uint256 seedA, uint256 seedB, uint256 length) external { + length = bound(length, 0, 2); + IRule[] memory rs = new IRule[](length); + if (length > 0) rs[0] = IRule(_rule(seedA)); + if (length > 1) rs[1] = IRule(_rule(seedB)); + vm.prank(ADMIN); + try ENGINE.setRules(rs) { + _clearModelRules(); + for (uint256 i = 0; i < length; ++i) { + modelHasRule[address(rs[i])] = true; + ++modelRuleCount; + } + ++successes["setRules"]; + } catch {} + } + + function clearRules() external { + vm.prank(ADMIN); + try ENGINE.clearRules() { + _clearModelRules(); + ++successes["clearRules"]; + } catch {} + } + + function setMaxRules(uint256 maxRules_) external { + maxRules_ = bound(maxRules_, 0, 6); + vm.prank(ADMIN); + try ENGINE.setMaxRules(maxRules_) { + modelMaxRules = maxRules_; + ++successes["setMaxRules"]; + } catch {} + } + + function _clearModelRules() internal { + for (uint256 i = 0; i < rulePool.length; ++i) { + modelHasRule[rulePool[i]] = false; + } + modelRuleCount = 0; + } + + /* ============ Token binding ============ */ + + function bindToken(uint256 seed) external { + address t = _token(seed); + vm.prank(ADMIN); + try ENGINE.bindToken(t) { + modelIsBound[t] = true; + ++modelBoundCount; + ++successes["bindToken"]; + } catch {} + } + + function unbindToken(uint256 seed) external { + address t = _token(seed); + vm.prank(ADMIN); + try ENGINE.unbindToken(t) { + modelIsBound[t] = false; + --modelBoundCount; + ++successes["unbindToken"]; + } catch {} + } + + function bindTokens(uint256 seedA, uint256 seedB) external { + address[] memory ts = new address[](2); + ts[0] = _token(seedA); + ts[1] = _token(seedB); + vm.prank(ADMIN); + try ENGINE.bindTokens(ts) { + for (uint256 i = 0; i < 2; ++i) { + modelIsBound[ts[i]] = true; + ++modelBoundCount; + } + ++successes["bindTokens"]; + } catch {} + } + + function unbindTokens(uint256 seedA, uint256 seedB) external { + address[] memory ts = new address[](2); + ts[0] = _token(seedA); + ts[1] = _token(seedB); + vm.prank(ADMIN); + try ENGINE.unbindTokens(ts) { + for (uint256 i = 0; i < 2; ++i) { + modelIsBound[ts[i]] = false; + --modelBoundCount; + } + ++successes["unbindTokens"]; + } catch {} + } + + /// @dev Exposes the private pool rule for the gate invariant. + function isAcceptedRule(address r) external view returns (bool) { + return _isAcceptedRule(r); + } +} + +/** + * @title RuleEngineInvariantTestBase + * @notice Handler-based invariant tests over the rule set and the bound-token set, run for every deployable + * variant (rc7 code-quality review `K-5`). + * @dev The handler is the only target. After every call of every random sequence, the engine's state must + * match the handler's model, and the structural properties must hold. `rulesCount() <= maxRules()` is + * deliberately not an invariant: lowering the cap below the current count is allowed. + */ +abstract contract RuleEngineInvariantTestBase is Test { + address internal constant ADMIN = address(0xA11CE); + + RuleEngineBase internal engine; + RuleEngineHandler internal handler; + + /* ============ Variant hook ============ */ + + /// @dev Deploys the variant with `admin` as admin/owner, no forwarder and no token bound. + function _deployEngine(address admin) internal virtual returns (address); + + function setUp() public virtual { + engine = RuleEngineBase(_deployEngine(ADMIN)); + handler = new RuleEngineHandler(engine, ADMIN); + targetContract(address(handler)); + } + + /* ============ Rule set ============ */ + + /// @notice The engine holds exactly the rules the successful calls imply, with the right count. + function invariant_RuleSetMatchesModel() public view { + assertEq(engine.rulesCount(), handler.modelRuleCount(), "rulesCount"); + for (uint256 i = 0; i < handler.rulePoolLength(); ++i) { + address r = handler.rulePool(i); + assertEq(engine.containsRule(IRule(r)), handler.modelHasRule(r), "containsRule"); + } + } + + /// @notice No duplicate, no `address(0)`, only rules the ERC-165 gate accepts; `rules()` and `rule(i)` agree. + function invariant_RuleSetIsWellFormed() public view { + address[] memory rs = engine.rules(); + assertEq(rs.length, engine.rulesCount(), "rules().length"); + for (uint256 i = 0; i < rs.length; ++i) { + assertTrue(rs[i] != address(0), "zero rule"); + assertTrue(handler.isAcceptedRule(rs[i]), "rule rejected by the gate is in the set"); + assertTrue( + IRule(rs[i]).supportsInterface(RuleInterfaceId.IRULE_INTERFACE_ID) + || IRule(rs[i]).supportsInterface(RuleInterfaceId.IRULE_LEGACY_INTERFACE_ID), + "rule without a rule ID" + ); + assertEq(engine.rule(i), rs[i], "rule(i)"); + for (uint256 j = i + 1; j < rs.length; ++j) { + assertTrue(rs[i] != rs[j], "duplicate rule"); + } + } + } + + /// @notice The cap is the last value set, and never zero. + function invariant_MaxRulesMatchesModelAndIsNotZero() public view { + assertEq(engine.maxRules(), handler.modelMaxRules(), "maxRules"); + assertGt(engine.maxRules(), 0, "maxRules is zero"); + } + + /* ============ Token binding ============ */ + + /// @notice F-3. No address is both a rule and a bound token. + function invariant_RulesAndBoundTokensAreDisjoint() public view { + address[] memory rs = engine.rules(); + for (uint256 i = 0; i < rs.length; ++i) { + assertFalse(engine.isTokenBound(rs[i]), "a rule is also a bound token"); + } + } + + /// @notice A token is bound exactly when the successful calls imply it; `getTokenBounds()` agrees. + function invariant_BoundTokensMatchModel() public view { + address[] memory ts = engine.getTokenBounds(); + assertEq(ts.length, handler.modelBoundCount(), "getTokenBounds().length"); + for (uint256 i = 0; i < handler.tokenPoolLength(); ++i) { + address t = handler.tokenPool(i); + assertEq(engine.isTokenBound(t), handler.modelIsBound(t), "isTokenBound"); + } + for (uint256 i = 0; i < handler.rulePoolLength(); ++i) { + address t = handler.rulePool(i); + assertEq(engine.isTokenBound(t), handler.modelIsBound(t), "isTokenBound (rule pool)"); + } + for (uint256 i = 0; i < ts.length; ++i) { + assertTrue(ts[i] != address(0), "zero token bound"); + assertTrue(engine.isTokenBound(ts[i]), "listed but not bound"); + for (uint256 j = i + 1; j < ts.length; ++j) { + assertTrue(ts[i] != ts[j], "duplicate token"); + } + } + } +} diff --git a/test/utils/SecurityReviewTestBase.sol b/test/utils/SecurityReviewTestBase.sol new file mode 100644 index 00000000..e18f7318 --- /dev/null +++ b/test/utils/SecurityReviewTestBase.sol @@ -0,0 +1,343 @@ +// SPDX-License-Identifier: MPL-2.0 +pragma solidity ^0.8.20; + +import {Test, Vm} from "forge-std/Test.sol"; +import {ITokenBindingExtended} from "src/interfaces/ITokenBindingExtended.sol"; +import {IRule} from "src/interfaces/IRule.sol"; +import {IRulesManagementModule} from "src/interfaces/IRulesManagementModule.sol"; +import {RuleEngineBase} from "src/RuleEngineBase.sol"; +import {RuleMintAllowanceMock} from "src/mocks/rules/operation/RuleMintAllowanceMock.sol"; +import {TokenBindingModuleInvariantStorage} from "src/modules/library/TokenBindingModuleInvariantStorage.sol"; +import {RulesManagementModuleInvariantStorage} from "src/modules/library/RulesManagementModuleInvariantStorage.sol"; +import {RuleCodeProbe} from "./RuleCodeProbe.sol"; +import {RevertingViewRule} from "./RevertingViewRule.sol"; +import {ReentrantAdminRule} from "./ReentrantAdminRule.sol"; + +/** + * @title SecurityReviewTestBase + * @notice Tests written for the v3.0.0-rc7 security review, run for every deployable variant. Each test names + * the threat it covers (see the review report). Several are proofs of concept that pin the current behaviour + * of a finding: they document what the engine does today, and must change if the finding is fixed. + * @dev `_deployEngine` deploys the variant with `ADMIN` as admin/owner and `TOKEN` bound; a `*2771` variant uses + * `FORWARDER`, which the fuzzed callers exclude. + */ +abstract contract SecurityReviewTestBase is Test { + address internal constant ADMIN = address(0xA11CE); + address internal constant FORWARDER = address(0xF0F0); + address internal constant TOKEN = address(0x7070); + address internal constant TOKEN_2 = address(0x7071); + address internal constant MINTER = address(0x3333); + address internal constant HOLDER = address(0x4444); + + bytes32 internal constant DEFAULT_ADMIN_ROLE = bytes32(0); + bytes32 internal constant RULES_MANAGEMENT_ROLE = keccak256("RULES_MANAGEMENT_ROLE"); + bytes32 internal constant COMPLIANCE_MANAGER_ROLE = keccak256("COMPLIANCE_MANAGER_ROLE"); + + RuleEngineBase internal engine; + RuleCodeProbe internal probe; + + /* ============ Variant hooks ============ */ + + /// @dev Deploys the variant with `admin` as admin/owner and `token` bound. + function _deployEngine(address admin, address token) internal virtual returns (address); + + /// @dev Revert data of the variant when `caller` lacks `role` (RBAC) or is not the owner (ownable variants). + function _unauthorizedRevertData(address caller, bytes32 role) internal view virtual returns (bytes memory); + + /// @dev Makes `ADMIN` give up control: renounce `DEFAULT_ADMIN_ROLE` (RBAC) or ownership (ownable variants). + function _renounceAdministration() internal virtual; + + function setUp() public virtual { + engine = RuleEngineBase(_deployEngine(ADMIN, TOKEN)); + probe = new RuleCodeProbe(10, "probe"); + } + + /* ============ AC-6: every admin entry point rejects every other caller ============ */ + + /// @notice AC-6. A random caller is rejected by the eleven administrative entry points, with the exact error + /// of the variant's guard: rule management needs RULES_MANAGEMENT_ROLE, the cap needs DEFAULT_ADMIN_ROLE, + /// binding needs COMPLIANCE_MANAGER_ROLE; the ownable variants need the owner for all of them. + function testFuzz_NonAuthorizedCallerCannotAdminister(address caller) public { + vm.assume(caller != ADMIN && caller != FORWARDER); + IRule[] memory rs = new IRule[](1); + rs[0] = probe; + address[] memory ts = new address[](1); + ts[0] = TOKEN_2; + + _expectUnauthorized(caller, RULES_MANAGEMENT_ROLE); + engine.addRule(probe); + _expectUnauthorized(caller, RULES_MANAGEMENT_ROLE); + engine.removeRule(probe); + _expectUnauthorized(caller, RULES_MANAGEMENT_ROLE); + engine.setRules(rs); + _expectUnauthorized(caller, RULES_MANAGEMENT_ROLE); + engine.clearRules(); + _expectUnauthorized(caller, DEFAULT_ADMIN_ROLE); + engine.setMaxRules(5); + _expectUnauthorized(caller, COMPLIANCE_MANAGER_ROLE); + engine.bindToken(TOKEN_2); + _expectUnauthorized(caller, COMPLIANCE_MANAGER_ROLE); + engine.unbindToken(TOKEN); + _expectUnauthorized(caller, COMPLIANCE_MANAGER_ROLE); + engine.bindTokens(ts); + _expectUnauthorized(caller, COMPLIANCE_MANAGER_ROLE); + engine.unbindTokens(ts); + _expectUnauthorized(caller, COMPLIANCE_MANAGER_ROLE); + engine.setTokenSelfBindingApproval(TOKEN_2, true); + _expectUnauthorized(caller, COMPLIANCE_MANAGER_ROLE); + engine.setTokenSelfBindingApprovalBatch(ts, true); + } + + /// @notice Invariant 4. A random caller that is not a bound token is rejected by the four token callbacks. + function testFuzz_UnboundCallerCannotDriveRules(address caller) public { + vm.assume(caller != TOKEN && caller != FORWARDER); + bytes4 unauthorized = TokenBindingModuleInvariantStorage.TokenBinding_UnauthorizedCaller.selector; + + vm.prank(caller); + vm.expectRevert(unauthorized); + engine.transferred(HOLDER, MINTER, 1); + vm.prank(caller); + vm.expectRevert(unauthorized); + engine.transferred(MINTER, HOLDER, MINTER, 1); + vm.prank(caller); + vm.expectRevert(unauthorized); + engine.created(HOLDER, 1); + vm.prank(caller); + vm.expectRevert(unauthorized); + engine.destroyed(HOLDER, 1); + } + + /* ============ TB-2 / F-2: an administrative unbind revokes the self-binding approval ============ */ + + /// @notice F-2 regression (was the TB-2 proof of concept). When the manager unbinds a token approved for + /// self-binding, the approval is revoked with a `TokenSelfBindingApprovalSet(token, false)` event, so the + /// token cannot bind itself again. + function testManagerUnbindRevokesSelfBindingApproval() public { + vm.startPrank(ADMIN); + engine.setTokenSelfBindingApproval(TOKEN_2, true); + engine.bindToken(TOKEN_2); + vm.expectEmit(address(engine)); + emit ITokenBindingExtended.TokenSelfBindingApprovalSet(TOKEN_2, false); + engine.unbindToken(TOKEN_2); + vm.stopPrank(); + assertFalse(engine.isTokenSelfBindingApproved(TOKEN_2)); + + _expectUnauthorized(TOKEN_2, COMPLIANCE_MANAGER_ROLE); + engine.bindToken(TOKEN_2); + assertFalse(engine.isTokenBound(TOKEN_2)); + } + + /// @notice F-2. The batch `unbindTokens` revokes the approvals the same way. + function testManagerBatchUnbindRevokesSelfBindingApproval() public { + address[] memory ts = new address[](1); + ts[0] = TOKEN_2; + vm.startPrank(ADMIN); + engine.setTokenSelfBindingApproval(TOKEN_2, true); + engine.bindToken(TOKEN_2); + engine.unbindTokens(ts); + vm.stopPrank(); + + assertFalse(engine.isTokenSelfBindingApproved(TOKEN_2)); + _expectUnauthorized(TOKEN_2, COMPLIANCE_MANAGER_ROLE); + engine.bindToken(TOKEN_2); + } + + /// @notice F-2. A token that unbinds itself (ERC-3643 `setCompliance` moving away) keeps its approval and can + /// bind itself again later. + function testTokenUnbindingItselfKeepsApproval() public { + vm.prank(ADMIN); + engine.setTokenSelfBindingApproval(TOKEN_2, true); + + vm.startPrank(TOKEN_2); + engine.bindToken(TOKEN_2); + engine.unbindToken(TOKEN_2); + assertTrue(engine.isTokenSelfBindingApproved(TOKEN_2)); + engine.bindToken(TOKEN_2); + vm.stopPrank(); + assertTrue(engine.isTokenBound(TOKEN_2)); + } + + /// @notice F-2. Unbinding a token that was never approved emits no approval event. + function testManagerUnbindOfUnapprovedTokenEmitsNoApprovalEvent() public { + vm.recordLogs(); + vm.prank(ADMIN); + engine.unbindToken(TOKEN); + Vm.Log[] memory logs = vm.getRecordedLogs(); + assertEq(logs.length, 1, "TokenUnbound only"); + assertFalse(engine.isTokenSelfBindingApproved(TOKEN)); + } + + /// @notice TB-2. Revoking the approval explicitly before unbinding also keeps the token out. + function testRevokingApprovalPreventsRebind() public { + vm.startPrank(ADMIN); + engine.setTokenSelfBindingApproval(TOKEN_2, true); + engine.bindToken(TOKEN_2); + engine.setTokenSelfBindingApproval(TOKEN_2, false); + engine.unbindToken(TOKEN_2); + vm.stopPrank(); + + _expectUnauthorized(TOKEN_2, COMPLIANCE_MANAGER_ROLE); + engine.bindToken(TOKEN_2); + assertFalse(engine.isTokenBound(TOKEN_2)); + } + + /* ============ TB-3: any address can be bound ============ */ + + /// @notice F-3 regression (was the TB-3 proof of concept). A current rule cannot be bound, through any binding + /// path: `bindToken`, `bindTokens`, or the rule binding itself with a self-binding approval. + function testCannotBindACurrentRule() public { + address[] memory ts = new address[](1); + ts[0] = address(probe); + bytes4 err = + RulesManagementModuleInvariantStorage.RuleEngine_RulesManagementModule_RuleAccountCannotReceivePrivileges + .selector; + vm.startPrank(ADMIN); + engine.addRule(probe); + engine.setTokenSelfBindingApproval(address(probe), true); + vm.expectRevert(err); + engine.bindToken(address(probe)); + vm.expectRevert(err); + engine.bindTokens(ts); + vm.stopPrank(); + + vm.prank(address(probe)); + vm.expectRevert(err); + engine.bindToken(address(probe)); + assertFalse(engine.isTokenBound(address(probe))); + } + + /// @notice F-3 regression. A bound token cannot be added as a rule, through `addRule` or `setRules`. + function testCannotAddABoundTokenAsRule() public { + IRule[] memory rs = new IRule[](1); + rs[0] = probe; + bytes4 err = + RulesManagementModuleInvariantStorage.RuleEngine_RulesManagementModule_RuleAccountCannotReceivePrivileges + .selector; + vm.startPrank(ADMIN); + engine.bindToken(address(probe)); + vm.expectRevert(err); + engine.addRule(probe); + vm.expectRevert(err); + engine.setRules(rs); + vm.stopPrank(); + assertFalse(engine.containsRule(probe)); + } + + /// @notice F-3. Once removed from the rule set, the address can be bound, and the other way round. + function testRuleAndTokenRolesCanBeSwappedSequentially() public { + vm.startPrank(ADMIN); + engine.addRule(probe); + engine.removeRule(probe); + engine.bindToken(address(probe)); + assertTrue(engine.isTokenBound(address(probe))); + engine.unbindToken(address(probe)); + engine.addRule(probe); + vm.stopPrank(); + assertTrue(engine.containsRule(probe)); + } + + /// @notice TB-3 / F-3 (documented behaviour). A bound externally owned account drives a stateful rule with no + /// token movement: here it consumes a minter's allowance. Binding is a trust decision of the manager; the + /// registry cannot tell a token contract from an EOA, so this stays a documentation item. + function testBoundEoaConsumesStatefulRuleState() public { + address eoa = address(0xE0A); + RuleMintAllowanceMock allowance = new RuleMintAllowanceMock(ADMIN); + vm.startPrank(ADMIN); + allowance.setMintAllowance(MINTER, 100); + engine.addRule(IRule(address(allowance))); + engine.bindToken(eoa); + vm.stopPrank(); + + vm.prank(eoa); + engine.transferred(MINTER, address(0), HOLDER, 60); + assertEq(allowance.mintAllowance(MINTER), 40, "allowance consumed without any mint"); + } + + /* ============ RE-2: views propagate a rule's revert ============ */ + + /// @notice RE-2 (proof of concept). When a rule's view reverts, the engine's ERC-1404 and ERC-3643 views + /// revert instead of returning a restriction code, while the enforcement path, which does not call those + /// views, still accepts the operation. + function testViewsRevertWhenARuleViewReverts() public { + RevertingViewRule rule = new RevertingViewRule(); + vm.prank(ADMIN); + engine.addRule(rule); + bytes4 err = RevertingViewRule.RevertingViewRule_ViewReverted.selector; + + vm.expectRevert(err); + engine.detectTransferRestriction(HOLDER, MINTER, 1); + vm.expectRevert(err); + engine.detectTransferRestrictionFrom(MINTER, HOLDER, MINTER, 1); + vm.expectRevert(err); + engine.canTransfer(HOLDER, MINTER, 1); + vm.expectRevert(err); + engine.canTransferFrom(MINTER, HOLDER, MINTER, 1); + vm.expectRevert(err); + engine.messageForTransferRestriction(1); + + vm.prank(TOKEN); + engine.transferred(HOLDER, MINTER, 1); + } + + /* ============ RE-4 / AC-2: a rule cannot reconfigure the engine from a callback ============ */ + + /// @notice RE-4 / AC-2. A rule that calls `addRule` from its `transferred` hook is rejected by the guard, + /// because a rule account holds no role and no ownership; the token operation reverts with that error. + function testRuleCannotReconfigureEngineFromCallback() public { + ReentrantAdminRule rule = new ReentrantAdminRule(IRulesManagementModule(address(engine)), probe); + vm.prank(ADMIN); + engine.addRule(rule); + + vm.expectRevert(_unauthorizedRevertData(address(rule), RULES_MANAGEMENT_ROLE)); + vm.prank(TOKEN); + engine.transferred(HOLDER, MINTER, 1); + assertFalse(engine.containsRule(probe)); + } + + /* ============ AC-4: giving up administration freezes the configuration ============ */ + + /// @notice AC-4. Once the administrator renounces, nobody can change the rule set or the bindings; the bound + /// token keeps operating under the rules in place. + function testRenouncingAdministrationFreezesConfiguration() public { + vm.prank(ADMIN); + engine.addRule(probe); + _renounceAdministration(); + + _expectUnauthorized(ADMIN, RULES_MANAGEMENT_ROLE); + engine.removeRule(probe); + _expectUnauthorized(ADMIN, COMPLIANCE_MANAGER_ROLE); + engine.unbindToken(TOKEN); + + probe.setCodes(42, 0); + vm.prank(TOKEN); + vm.expectRevert(abi.encodeWithSelector(RuleCodeProbe.RuleCodeProbe_Rejected.selector, uint8(42))); + engine.transferred(HOLDER, MINTER, 1); + } + + /* ============ CM-2: ERC-3643 mint carries no operator ============ */ + + /// @notice CM-2. The ERC-3643 `created` callback carries no operator, so a spender-keyed rule (mint + /// allowance) is not applied to it; the CMTAT 4-argument path, which carries the minter, is. + function testErc3643CreatedDoesNotReachSpenderKeyedRule() public { + RuleMintAllowanceMock allowance = new RuleMintAllowanceMock(ADMIN); + vm.startPrank(ADMIN); + allowance.setMintAllowance(MINTER, 100); + engine.addRule(IRule(address(allowance))); + vm.stopPrank(); + + vm.prank(TOKEN); + engine.created(HOLDER, 60); + assertEq(allowance.mintAllowance(MINTER), 100, "created: no operator, nothing consumed"); + + vm.prank(TOKEN); + engine.transferred(MINTER, address(0), HOLDER, 60); + assertEq(allowance.mintAllowance(MINTER), 40, "4-argument mint: minter's allowance consumed"); + } + + /* ============ Helpers ============ */ + + function _expectUnauthorized(address caller, bytes32 role) internal { + vm.prank(caller); + vm.expectRevert(_unauthorizedRevertData(caller, role)); + } +} diff --git a/test/utils/onchainid/interface/IClaimIssuer.sol b/test/utils/onchainid/interface/IClaimIssuer.sol new file mode 100644 index 00000000..38854be1 --- /dev/null +++ b/test/utils/onchainid/interface/IClaimIssuer.sol @@ -0,0 +1,31 @@ +// SPDX-License-Identifier: MPL-2.0 +pragma solidity ^0.8.20; + +import {IIdentity} from "./IIdentity.sol"; + +/** + * @title IClaimIssuer — minimal stand-in for ONCHAINID's `IClaimIssuer`. + * @notice Imported by ERC-3643's trusted-issuers registry interface. Within the compile set it is + * used as a type in most places, and *called* in one: `IdentityRegistry.isVerified` invokes + * `isClaimValid` on the trusted issuer of each required claim topic. + * + * @dev See {IIdentity} for why these stubs exist and the remapping that wires them in. + * + * WARNING: not the real ONCHAINID interface. The genuine `IClaimIssuer` adds claim revocation and + * signature validation. Do not import this outside the ERC-3643 build context. + */ +interface IClaimIssuer is IIdentity { + /** + * @notice Returns whether a claim issued by this issuer is currently valid. + * @dev Called by `IdentityRegistry.isVerified` for every required claim topic. + * @param _identity The identity the claim is about. + * @param _claimTopic The claim topic. + * @param _sig The claim signature. + * @param _data The claim data. + * @return True when the claim is valid. + */ + function isClaimValid(IIdentity _identity, uint256 _claimTopic, bytes calldata _sig, bytes calldata _data) + external + view + returns (bool); +} diff --git a/test/utils/onchainid/interface/IIdentity.sol b/test/utils/onchainid/interface/IIdentity.sol new file mode 100644 index 00000000..6deceff0 --- /dev/null +++ b/test/utils/onchainid/interface/IIdentity.sol @@ -0,0 +1,52 @@ +// SPDX-License-Identifier: MPL-2.0 +pragma solidity ^0.8.20; + +/** + * @title IIdentity — minimal stand-in for ONCHAINID's `IIdentity`. + * @notice ERC-3643 imports `@onchain-id/solidity/contracts/interface/IIdentity.sol`. That package + * is an npm dependency, not a git submodule, so it is not vendored here. This file supplies the + * members ERC-3643 actually *calls* — `keyHasPurpose` in `Token.recoveryAddress`, and `getClaim` in + * `IdentityRegistry.isVerified` — and is wired in through a context-scoped remapping that applies to + * `lib/ERC-3643/` only. + * + * @dev Same approach as `src/rules/interfaces/AggregatorV3Interface.sol`: redeclare the slice of a + * third-party interface that is genuinely used rather than vendor the whole package. Everywhere + * else in ERC-3643, `IIdentity` appears only as a parameter or event type, and a contract type + * canonicalises to `address` in the ABI, so the declared members do not affect any selector. + * + * WARNING: this is NOT the real ONCHAINID interface. The genuine `IIdentity` extends ERC-734 + * (key management) and ERC-735 (claims) with a much larger surface. Do not treat this file as a + * specification of ONCHAINID, and do not import it outside the ERC-3643 build context. + */ +interface IIdentity { + /** + * @notice Returns whether a key holds a given purpose. + * @param _key The key, `keccak256(abi.encode(walletAddress))` in ERC-3643's usage. + * @param _purpose The ERC-734 purpose (1 = MANAGEMENT). + * @return True if the key holds the purpose. + */ + function keyHasPurpose(bytes32 _key, uint256 _purpose) external view returns (bool); + + /** + * @notice Returns a claim held by this identity (ERC-735). + * @dev Called by `IdentityRegistry.isVerified` once the token requires at least one claim topic. + * @param _claimId `keccak256(abi.encode(issuer, topic))`. + * @return topic The claim topic. + * @return scheme The signature scheme. + * @return issuer The claim issuer. + * @return signature The claim signature. + * @return data The claim data. + * @return uri A URI pointing at the claim. + */ + function getClaim(bytes32 _claimId) + external + view + returns ( + uint256 topic, + uint256 scheme, + address issuer, + bytes memory signature, + bytes memory data, + string memory uri + ); +}