| Public ❗️ | 🛑 | MetaTxModuleStandalone |
| └ | createTransferRequest | Public ❗️ | 🛑 |NO❗️ |
+| └ | createTransferRequestBatch | Public ❗️ | 🛑 |NO❗️ |
| └ | cancelTransferRequest | Public ❗️ | 🛑 |NO❗️ |
+| └ | cancelTransferRequestBatch | Public ❗️ | 🛑 |NO❗️ |
+| └ | _cancelTransferRequest | Internal 🔒 | 🛑 | |
| └ | getRequestTrade | Public ❗️ | |NO❗️ |
| └ | getRequestByStatus | Public ❗️ | |NO❗️ |
| └ | operateOnTransfer | Public ❗️ | 🛑 | onlyRole |
diff --git a/doc/surya/surya_report/surya_report_RuleConditionalTransferInvariantStorage.sol.md b/doc/surya/surya_report/surya_report_RuleConditionalTransferInvariantStorage.sol.md
index f3ae1f7..3e68d6f 100644
--- a/doc/surya/surya_report/surya_report_RuleConditionalTransferInvariantStorage.sol.md
+++ b/doc/surya/surya_report/surya_report_RuleConditionalTransferInvariantStorage.sol.md
@@ -5,7 +5,7 @@
| File Name | SHA-1 Hash |
|-------------|--------------|
-| ./rules/operation/abstract/RuleConditionalTransferInvariantStorage.sol | 4f6a42a549cb435d490721e8091f34f9ac55fd1c |
+| ./rules/operation/abstract/RuleConditionalTransferInvariantStorage.sol | fca0008dbf1e9645944506d01fea4281a5e5208b |
### Contracts Description Table
diff --git a/doc/surya/surya_report/surya_report_RuleConditionalTransferOperator.sol.md b/doc/surya/surya_report/surya_report_RuleConditionalTransferOperator.sol.md
index 4660310..11d4af0 100644
--- a/doc/surya/surya_report/surya_report_RuleConditionalTransferOperator.sol.md
+++ b/doc/surya/surya_report/surya_report_RuleConditionalTransferOperator.sol.md
@@ -5,7 +5,7 @@
| File Name | SHA-1 Hash |
|-------------|--------------|
-| ./rules/operation/abstract/RuleConditionalTransferOperator.sol | 76e5a428623395575861a4d45bdc3f5b6f797f7e |
+| ./rules/operation/abstract/RuleConditionalTransferOperator.sol | 5e35d28ab99475759783fca1614544e132797487 |
### Contracts Description Table
@@ -16,6 +16,7 @@
| └ | **Function Name** | **Visibility** | **Mutability** | **Modifiers** |
||||||
| **RuleConditionalTransferOperator** | Implementation | AccessControl, RuleConditionalTransferInvariantStorage |||
+| └ | setConditionalWhitelist | Public ❗️ | 🛑 | onlyRole |
| └ | setIssuanceOptions | Public ❗️ | 🛑 | onlyRole |
| └ | setAutomaticTransfer | Public ❗️ | 🛑 | onlyRole |
| └ | setTimeLimit | Public ❗️ | 🛑 | onlyRole |
@@ -24,6 +25,12 @@
| └ | approveTransferRequest | Public ❗️ | 🛑 | onlyRole |
| └ | approveTransferRequestWithId | Public ❗️ | 🛑 | onlyRole |
| └ | resetRequestStatus | Public ❗️ | 🛑 | onlyRole |
+| └ | approveTransferRequestBatchWithId | Public ❗️ | 🛑 | onlyRole |
+| └ | approveTransferRequestBatch | Public ❗️ | 🛑 | onlyRole |
+| └ | createTransferRequestWithApprovalBatch | Public ❗️ | 🛑 | onlyRole |
+| └ | resetRequestStatusBatch | Public ❗️ | 🛑 | onlyRole |
+| └ | _approveTransferRequestKeyElement | Internal 🔒 | 🛑 | |
+| └ | _createTransferRequestWithApproval | Public ❗️ | 🛑 | onlyRole |
| └ | _resetRequestStatus | Internal 🔒 | 🛑 | |
| └ | _checkRequestStatus | Internal 🔒 | | |
| └ | _approveRequest | Internal 🔒 | 🛑 | |
diff --git a/doc/surya/surya_report/surya_report_RuleEngine.sol.md b/doc/surya/surya_report/surya_report_RuleEngine.sol.md
index b596fbb..d0812d9 100644
--- a/doc/surya/surya_report/surya_report_RuleEngine.sol.md
+++ b/doc/surya/surya_report/surya_report_RuleEngine.sol.md
@@ -5,7 +5,7 @@
| File Name | SHA-1 Hash |
|-------------|--------------|
-| ./RuleEngine.sol | b1c26380badaa4dd34dd75647bb62db7e30e5e40 |
+| ./RuleEngine.sol | 0fc418971885c84c32fab8ba76462a7ae5c77b77 |
### Contracts Description Table
diff --git a/doc/surya/surya_report/surya_report_RuleEngineOperation.sol.md b/doc/surya/surya_report/surya_report_RuleEngineOperation.sol.md
index 5600732..9823a14 100644
--- a/doc/surya/surya_report/surya_report_RuleEngineOperation.sol.md
+++ b/doc/surya/surya_report/surya_report_RuleEngineOperation.sol.md
@@ -5,7 +5,7 @@
| File Name | SHA-1 Hash |
|-------------|--------------|
-| ./modules/RuleEngineOperation.sol | d3de41695a73eb2f2cb02dbea88b72174a2a9830 |
+| ./modules/RuleEngineOperation.sol | a511cf11774bebce822a8b277f0d33a71d6df492 |
### Contracts Description Table
diff --git a/doc/surya/surya_report/surya_report_RuleEngineValidation.sol.md b/doc/surya/surya_report/surya_report_RuleEngineValidation.sol.md
index 8c67257..fe3ac20 100644
--- a/doc/surya/surya_report/surya_report_RuleEngineValidation.sol.md
+++ b/doc/surya/surya_report/surya_report_RuleEngineValidation.sol.md
@@ -5,7 +5,7 @@
| File Name | SHA-1 Hash |
|-------------|--------------|
-| ./modules/RuleEngineValidation.sol | 818bc0f7e4fc858d3aa6efc76811268aa81bd3ee |
+| ./modules/RuleEngineValidation.sol | 389f8e6a721d981e7704f67c608138af0b3bed97 |
### Contracts Description Table
diff --git a/doc/surya/surya_report/surya_report_RuleWhitelist.sol.md b/doc/surya/surya_report/surya_report_RuleWhitelist.sol.md
index 308d7d8..dcae5ae 100644
--- a/doc/surya/surya_report/surya_report_RuleWhitelist.sol.md
+++ b/doc/surya/surya_report/surya_report_RuleWhitelist.sol.md
@@ -5,7 +5,7 @@
| File Name | SHA-1 Hash |
|-------------|--------------|
-| ./rules/validation/RuleWhitelist.sol | a5c81461282137d1360d7934607e6e40c0727aa4 |
+| ./rules/validation/RuleWhitelist.sol | 721bc822979b9948547c0d499ccb831ee6083775 |
### Contracts Description Table
diff --git a/doc/technical/RuleConditionalTransfer.md b/doc/technical/RuleConditionalTransfer.md
index 438a89b..5695a09 100644
--- a/doc/technical/RuleConditionalTransfer.md
+++ b/doc/technical/RuleConditionalTransfer.md
@@ -77,7 +77,7 @@ Each request has a status, which changes regarding the decision of the operator
The default status is `NONE`.
-
+![conditionalTransfer-state machine.drawio](../schema/rule/conditionalTransfer-state machine.drawio.png)
#### With the CMTAT
diff --git a/doc/test/coverage/index-sort-b.html b/doc/test/coverage/index-sort-b.html
index 557016c..a8ed6d6 100644
--- a/doc/test/coverage/index-sort-b.html
+++ b/doc/test/coverage/index-sort-b.html
@@ -31,17 +31,17 @@
|
-
-
-
+
+
+
-
+
|
-
-
+
+
@@ -49,9 +49,9 @@
|
|
-
-
-
+
+
+
|
@@ -120,14 +120,14 @@
src/rules/operation |
-
+
|
- 98.7 % |
- 78 / 79 |
+ 98.8 % |
+ 84 / 85 |
93.8 % |
15 / 16 |
- 94.1 % |
- 32 / 34 |
+ 90.5 % |
+ 38 / 42 |
src/modules |
@@ -147,9 +147,9 @@
100.0 % |
- 94 / 94 |
- 94.4 % |
- 17 / 18 |
+ 96 / 96 |
+ 94.7 % |
+ 18 / 19 |
98.1 % |
53 / 54 |
diff --git a/doc/test/coverage/index-sort-f.html b/doc/test/coverage/index-sort-f.html
index 7f71a63..6d4fae1 100644
--- a/doc/test/coverage/index-sort-f.html
+++ b/doc/test/coverage/index-sort-f.html
@@ -31,17 +31,17 @@
|
-
-
-
+
+
+
-
+
|
-
-
+
+
@@ -49,9 +49,9 @@
|
|
-
-
-
+
+
+
|
@@ -144,14 +144,14 @@
src/rules/operation |
-
+
|
- 98.7 % |
- 78 / 79 |
+ 98.8 % |
+ 84 / 85 |
93.8 % |
15 / 16 |
- 94.1 % |
- 32 / 34 |
+ 90.5 % |
+ 38 / 42 |
src/rules/operation/abstract |
@@ -159,9 +159,9 @@
100.0 % |
- 94 / 94 |
- 94.4 % |
- 17 / 18 |
+ 96 / 96 |
+ 94.7 % |
+ 18 / 19 |
98.1 % |
53 / 54 |
diff --git a/doc/test/coverage/index-sort-l.html b/doc/test/coverage/index-sort-l.html
index 2131c05..c955df1 100644
--- a/doc/test/coverage/index-sort-l.html
+++ b/doc/test/coverage/index-sort-l.html
@@ -31,17 +31,17 @@
|
-
-
-
+
+
+
-
+
|
-
-
+
+
@@ -49,9 +49,9 @@
|
|
-
-
-
+
+
+
|
@@ -144,14 +144,14 @@
src/rules/operation |
-
+
|
- 98.7 % |
- 78 / 79 |
+ 98.8 % |
+ 84 / 85 |
93.8 % |
15 / 16 |
- 94.1 % |
- 32 / 34 |
+ 90.5 % |
+ 38 / 42 |
src/rules/validation/abstract |
@@ -183,9 +183,9 @@
100.0 % |
- 94 / 94 |
- 94.4 % |
- 17 / 18 |
+ 96 / 96 |
+ 94.7 % |
+ 18 / 19 |
98.1 % |
53 / 54 |
diff --git a/doc/test/coverage/index.html b/doc/test/coverage/index.html
index dc0a8e6..960324e 100644
--- a/doc/test/coverage/index.html
+++ b/doc/test/coverage/index.html
@@ -31,17 +31,17 @@
|
-
-
-
+
+
+
-
+
|
-
-
+
+
@@ -49,9 +49,9 @@
|
|
-
-
-
+
+
+
|
@@ -120,14 +120,14 @@
src/rules/operation |
-
+
|
- 98.7 % |
- 78 / 79 |
+ 98.8 % |
+ 84 / 85 |
93.8 % |
15 / 16 |
- 94.1 % |
- 32 / 34 |
+ 90.5 % |
+ 38 / 42 |
src/rules/operation/abstract |
@@ -135,9 +135,9 @@
100.0 % |
- 94 / 94 |
- 94.4 % |
- 17 / 18 |
+ 96 / 96 |
+ 94.7 % |
+ 18 / 19 |
98.1 % |
53 / 54 |
diff --git a/doc/test/coverage/script/CMTATWithRuleEngineScript.s.sol.func-sort-c.html b/doc/test/coverage/script/CMTATWithRuleEngineScript.s.sol.func-sort-c.html
index 3a16415..104e111 100644
--- a/doc/test/coverage/script/CMTATWithRuleEngineScript.s.sol.func-sort-c.html
+++ b/doc/test/coverage/script/CMTATWithRuleEngineScript.s.sol.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/doc/test/coverage/script/CMTATWithRuleEngineScript.s.sol.func.html b/doc/test/coverage/script/CMTATWithRuleEngineScript.s.sol.func.html
index a3a6835..6955f40 100644
--- a/doc/test/coverage/script/CMTATWithRuleEngineScript.s.sol.func.html
+++ b/doc/test/coverage/script/CMTATWithRuleEngineScript.s.sol.func.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/doc/test/coverage/script/CMTATWithRuleEngineScript.s.sol.gcov.html b/doc/test/coverage/script/CMTATWithRuleEngineScript.s.sol.gcov.html
index a631bb2..fd8f994 100644
--- a/doc/test/coverage/script/CMTATWithRuleEngineScript.s.sol.gcov.html
+++ b/doc/test/coverage/script/CMTATWithRuleEngineScript.s.sol.gcov.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/doc/test/coverage/script/RuleEngineScript.s.sol.func-sort-c.html b/doc/test/coverage/script/RuleEngineScript.s.sol.func-sort-c.html
index 4c08eb1..0be87b7 100644
--- a/doc/test/coverage/script/RuleEngineScript.s.sol.func-sort-c.html
+++ b/doc/test/coverage/script/RuleEngineScript.s.sol.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/doc/test/coverage/script/RuleEngineScript.s.sol.func.html b/doc/test/coverage/script/RuleEngineScript.s.sol.func.html
index 4707d3f..f91ca3b 100644
--- a/doc/test/coverage/script/RuleEngineScript.s.sol.func.html
+++ b/doc/test/coverage/script/RuleEngineScript.s.sol.func.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/doc/test/coverage/script/RuleEngineScript.s.sol.gcov.html b/doc/test/coverage/script/RuleEngineScript.s.sol.gcov.html
index 173ba22..4eb457e 100644
--- a/doc/test/coverage/script/RuleEngineScript.s.sol.gcov.html
+++ b/doc/test/coverage/script/RuleEngineScript.s.sol.gcov.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/doc/test/coverage/script/index-sort-b.html b/doc/test/coverage/script/index-sort-b.html
index fdf335a..7e3a773 100644
--- a/doc/test/coverage/script/index-sort-b.html
+++ b/doc/test/coverage/script/index-sort-b.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/doc/test/coverage/script/index-sort-f.html b/doc/test/coverage/script/index-sort-f.html
index 34b8963..afd417e 100644
--- a/doc/test/coverage/script/index-sort-f.html
+++ b/doc/test/coverage/script/index-sort-f.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/doc/test/coverage/script/index-sort-l.html b/doc/test/coverage/script/index-sort-l.html
index f87bbf7..0366127 100644
--- a/doc/test/coverage/script/index-sort-l.html
+++ b/doc/test/coverage/script/index-sort-l.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/doc/test/coverage/script/index.html b/doc/test/coverage/script/index.html
index e4c6479..38a89dc 100644
--- a/doc/test/coverage/script/index.html
+++ b/doc/test/coverage/script/index.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/doc/test/coverage/src/RuleEngine.sol.func-sort-c.html b/doc/test/coverage/src/RuleEngine.sol.func-sort-c.html
index 6d7459d..a8539b5 100644
--- a/doc/test/coverage/src/RuleEngine.sol.func-sort-c.html
+++ b/doc/test/coverage/src/RuleEngine.sol.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
@@ -86,15 +86,15 @@
RuleEngine.operateOnTransfer |
- 26 |
+ 45 |
RuleEngine._contextSuffixLength |
- 203 |
+ 244 |
RuleEngine._msgSender |
- 203 |
+ 244 |
diff --git a/doc/test/coverage/src/RuleEngine.sol.func.html b/doc/test/coverage/src/RuleEngine.sol.func.html
index 770c4e9..2250ee1 100644
--- a/doc/test/coverage/src/RuleEngine.sol.func.html
+++ b/doc/test/coverage/src/RuleEngine.sol.func.html
@@ -37,7 +37,7 @@
-
+
|
@@ -70,7 +70,7 @@
RuleEngine._contextSuffixLength |
- 203 |
+ 244 |
RuleEngine._msgData |
@@ -78,7 +78,7 @@
RuleEngine._msgSender |
- 203 |
+ 244 |
RuleEngine.detectTransferRestriction |
@@ -90,7 +90,7 @@
RuleEngine.operateOnTransfer |
- 26 |
+ 45 |
RuleEngine.validateTransfer |
diff --git a/doc/test/coverage/src/RuleEngine.sol.gcov.html b/doc/test/coverage/src/RuleEngine.sol.gcov.html
index 40c448b..a5ae197 100644
--- a/doc/test/coverage/src/RuleEngine.sol.gcov.html
+++ b/doc/test/coverage/src/RuleEngine.sol.gcov.html
@@ -37,7 +37,7 @@
-
+
|
@@ -186,11 +186,11 @@
115 : : */
116 : : function operateOnTransfer(address from, address to, uint256 amount) external override onlyRole(TOKEN_CONTRACT_ROLE) returns (bool isValid) {
117 : : // Validate the transfer
- 118 [ + + ]: 50 : if(!RuleEngineValidation.validateTransferValidation(from, to, amount)){
+ 118 [ + + ]: 88 : if(!RuleEngineValidation.validateTransferValidation(from, to, amount)){
119 : 14 : return false;
120 : : }
121 : : // Apply operation on RuleEngine
- 122 : 54 : return RuleEngineOperation._operateOnTransfer(from, to, amount);
+ 122 : 111 : return RuleEngineOperation._operateOnTransfer(from, to, amount);
123 : : }
124 : :
125 : : /**
@@ -202,7 +202,7 @@
131 : : override(ERC2771Context, Context)
132 : : returns (address sender)
133 : : {
- 134 : 609 : return ERC2771Context._msgSender();
+ 134 : 732 : return ERC2771Context._msgSender();
135 : : }
136 : :
137 : : /**
@@ -221,7 +221,7 @@
150 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule
151 : : */
152 : : function _contextSuffixLength() internal view override(ERC2771Context, Context) returns (uint256) {
- 153 : 609 : return ERC2771Context._contextSuffixLength();
+ 153 : 732 : return ERC2771Context._contextSuffixLength();
154 : : }
155 : : }
diff --git a/doc/test/coverage/src/index-sort-b.html b/doc/test/coverage/src/index-sort-b.html
index 329777c..7c7d1c2 100644
--- a/doc/test/coverage/src/index-sort-b.html
+++ b/doc/test/coverage/src/index-sort-b.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/doc/test/coverage/src/index-sort-f.html b/doc/test/coverage/src/index-sort-f.html
index f831a28..6a6bcc1 100644
--- a/doc/test/coverage/src/index-sort-f.html
+++ b/doc/test/coverage/src/index-sort-f.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/doc/test/coverage/src/index-sort-l.html b/doc/test/coverage/src/index-sort-l.html
index 177354e..876daf1 100644
--- a/doc/test/coverage/src/index-sort-l.html
+++ b/doc/test/coverage/src/index-sort-l.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/doc/test/coverage/src/index.html b/doc/test/coverage/src/index.html
index c29cf55..3326585 100644
--- a/doc/test/coverage/src/index.html
+++ b/doc/test/coverage/src/index.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/doc/test/coverage/src/modules/RuleEngineOperation.sol.func-sort-c.html b/doc/test/coverage/src/modules/RuleEngineOperation.sol.func-sort-c.html
index 52d0974..60b6676 100644
--- a/doc/test/coverage/src/modules/RuleEngineOperation.sol.func-sort-c.html
+++ b/doc/test/coverage/src/modules/RuleEngineOperation.sol.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
@@ -96,21 +96,21 @@
RuleEngineOperation._clearRulesOperation |
14 |
-
- RuleEngineOperation._operateOnTransfer |
- 18 |
-
RuleEngineOperation._removeRuleOperation |
22 |
+
+ RuleEngineOperation._operateOnTransfer |
+ 37 |
+
RuleEngineOperation.rulesCountOperation |
41 |
RuleEngineOperation.addRuleOperation |
- 46 |
+ 68 |
diff --git a/doc/test/coverage/src/modules/RuleEngineOperation.sol.func.html b/doc/test/coverage/src/modules/RuleEngineOperation.sol.func.html
index 7911e43..d1a961d 100644
--- a/doc/test/coverage/src/modules/RuleEngineOperation.sol.func.html
+++ b/doc/test/coverage/src/modules/RuleEngineOperation.sol.func.html
@@ -37,7 +37,7 @@
-
+
|
@@ -74,7 +74,7 @@
RuleEngineOperation._operateOnTransfer |
- 18 |
+ 37 |
RuleEngineOperation._removeRuleOperation |
@@ -82,7 +82,7 @@
RuleEngineOperation.addRuleOperation |
- 46 |
+ 68 |
RuleEngineOperation.clearRulesOperation |
diff --git a/doc/test/coverage/src/modules/RuleEngineOperation.sol.gcov.html b/doc/test/coverage/src/modules/RuleEngineOperation.sol.gcov.html
index c43cf6a..157fff9 100644
--- a/doc/test/coverage/src/modules/RuleEngineOperation.sol.gcov.html
+++ b/doc/test/coverage/src/modules/RuleEngineOperation.sol.gcov.html
@@ -37,7 +37,7 @@
-
+
|
@@ -130,8 +130,8 @@
59 : : *
60 : : */
61 : : function addRuleOperation(IRuleOperation rule_) public onlyRole(RULE_ENGINE_ROLE) {
- 62 : 92 : RuleInternal._addRule( _rulesOperation, address(rule_));
- 63 : 88 : emit AddRule(address(rule_));
+ 62 : 136 : RuleInternal._addRule( _rulesOperation, address(rule_));
+ 63 : 132 : emit AddRule(address(rule_));
64 : : }
65 : :
66 : : /**
@@ -213,18 +213,18 @@
142 : : address _to,
143 : : uint256 _amount
144 : : ) internal returns (bool isValid){
- 145 : 36 : uint256 rulesLength = _rulesOperation.length;
- 146 : 68 : for (uint256 i = 0; i < rulesLength; ++i ) {
- 147 : 42 : bool result = IRuleOperation(_rulesOperation[i]).operateOnTransfer(
+ 145 : 74 : uint256 rulesLength = _rulesOperation.length;
+ 146 : 143 : for (uint256 i = 0; i < rulesLength; ++i ) {
+ 147 : 99 : bool result = IRuleOperation(_rulesOperation[i]).operateOnTransfer(
148 : : _from,
149 : : _to,
150 : : _amount
151 : : );
- 152 [ + + ]: 28 : if(!result){
- 153 : 14 : return false;
+ 152 [ + + ]: 66 : if(!result){
+ 153 : 34 : return false;
154 : : }
155 : : }
- 156 : 22 : return true;
+ 156 : 40 : return true;
157 : : }
158 : : }
diff --git a/doc/test/coverage/src/modules/RuleEngineValidation.sol.func-sort-c.html b/doc/test/coverage/src/modules/RuleEngineValidation.sol.func-sort-c.html
index d91e642..25488e0 100644
--- a/doc/test/coverage/src/modules/RuleEngineValidation.sol.func-sort-c.html
+++ b/doc/test/coverage/src/modules/RuleEngineValidation.sol.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/doc/test/coverage/src/modules/RuleEngineValidation.sol.func.html b/doc/test/coverage/src/modules/RuleEngineValidation.sol.func.html
index 06fb650..0e25146 100644
--- a/doc/test/coverage/src/modules/RuleEngineValidation.sol.func.html
+++ b/doc/test/coverage/src/modules/RuleEngineValidation.sol.func.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/doc/test/coverage/src/modules/RuleEngineValidation.sol.gcov.html b/doc/test/coverage/src/modules/RuleEngineValidation.sol.gcov.html
index 6182787..d78351a 100644
--- a/doc/test/coverage/src/modules/RuleEngineValidation.sol.gcov.html
+++ b/doc/test/coverage/src/modules/RuleEngineValidation.sol.gcov.html
@@ -37,7 +37,7 @@
-
+
|
@@ -216,8 +216,8 @@
145 : : address _to,
146 : : uint256 _amount
147 : : ) public view override returns (uint8) {
- 148 : 104 : uint256 rulesLength = _rulesValidation.length;
- 149 : 176 : for (uint256 i = 0; i < rulesLength; ++i ) {
+ 148 : 142 : uint256 rulesLength = _rulesValidation.length;
+ 149 : 233 : for (uint256 i = 0; i < rulesLength; ++i ) {
150 : 96 : uint8 restriction = IRuleValidation(_rulesValidation[i]).detectTransferRestriction(
151 : : _from,
152 : : _to,
@@ -228,7 +228,7 @@
157 : : }
158 : : }
159 : :
- 160 : 90 : return uint8(REJECTED_CODE_BASE.TRANSFER_OK);
+ 160 : 147 : return uint8(REJECTED_CODE_BASE.TRANSFER_OK);
161 : : }
162 : :
163 : : /**
@@ -243,7 +243,7 @@
172 : : address _to,
173 : : uint256 _amount
174 : : ) public view override returns (bool) {
- 175 : 135 : return detectTransferRestrictionValidation(_from, _to, _amount) == uint8(REJECTED_CODE_BASE.TRANSFER_OK);
+ 175 : 230 : return detectTransferRestrictionValidation(_from, _to, _amount) == uint8(REJECTED_CODE_BASE.TRANSFER_OK);
176 : : }
177 : : }
diff --git a/doc/test/coverage/src/modules/RuleInternal.sol.func-sort-c.html b/doc/test/coverage/src/modules/RuleInternal.sol.func-sort-c.html
index 90d60ca..7f87299 100644
--- a/doc/test/coverage/src/modules/RuleInternal.sol.func-sort-c.html
+++ b/doc/test/coverage/src/modules/RuleInternal.sol.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
@@ -82,7 +82,7 @@
RuleInternal._addRule |
- 112 |
+ 134 |
diff --git a/doc/test/coverage/src/modules/RuleInternal.sol.func.html b/doc/test/coverage/src/modules/RuleInternal.sol.func.html
index e2594ba..3682d83 100644
--- a/doc/test/coverage/src/modules/RuleInternal.sol.func.html
+++ b/doc/test/coverage/src/modules/RuleInternal.sol.func.html
@@ -37,7 +37,7 @@
-
+
|
@@ -70,7 +70,7 @@
RuleInternal._addRule |
- 112 |
+ 134 |
RuleInternal._removeRule |
diff --git a/doc/test/coverage/src/modules/RuleInternal.sol.gcov.html b/doc/test/coverage/src/modules/RuleInternal.sol.gcov.html
index a3b8f90..56428d7 100644
--- a/doc/test/coverage/src/modules/RuleInternal.sol.gcov.html
+++ b/doc/test/coverage/src/modules/RuleInternal.sol.gcov.html
@@ -37,7 +37,7 @@
-
+
|
@@ -115,16 +115,16 @@
44 : : *
45 : : */
46 : : function _addRule(address[] storage _rules, address rule_) internal {
- 47 [ + + ]: 448 : if( address(rule_) == address(0x0))
+ 47 [ + + ]: 536 : if( address(rule_) == address(0x0))
48 : : {
49 : 4 : revert RuleEngine_RuleAddressZeroNotAllowed();
50 : : }
- 51 [ + + ]: 110 : if( _ruleIsPresent[rule_])
+ 51 [ + + ]: 132 : if( _ruleIsPresent[rule_])
52 : : {
53 : 4 : revert RuleEngine_RuleAlreadyExists();
54 : : }
- 55 : 216 : _rules.push(rule_);
- 56 : 216 : _ruleIsPresent[rule_] = true;
+ 55 : 260 : _rules.push(rule_);
+ 56 : 260 : _ruleIsPresent[rule_] = true;
57 : : }
58 : :
59 : : /**
diff --git a/doc/test/coverage/src/modules/index-sort-b.html b/doc/test/coverage/src/modules/index-sort-b.html
index b1b0d46..85bb87e 100644
--- a/doc/test/coverage/src/modules/index-sort-b.html
+++ b/doc/test/coverage/src/modules/index-sort-b.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/doc/test/coverage/src/modules/index-sort-f.html b/doc/test/coverage/src/modules/index-sort-f.html
index 3897b8f..a84ef03 100644
--- a/doc/test/coverage/src/modules/index-sort-f.html
+++ b/doc/test/coverage/src/modules/index-sort-f.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/doc/test/coverage/src/modules/index-sort-l.html b/doc/test/coverage/src/modules/index-sort-l.html
index cb2ba07..49f111f 100644
--- a/doc/test/coverage/src/modules/index-sort-l.html
+++ b/doc/test/coverage/src/modules/index-sort-l.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/doc/test/coverage/src/modules/index.html b/doc/test/coverage/src/modules/index.html
index b8940ef..373a764 100644
--- a/doc/test/coverage/src/modules/index.html
+++ b/doc/test/coverage/src/modules/index.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/doc/test/coverage/src/rules/operation/RuleConditionalTransfer.sol.func-sort-c.html b/doc/test/coverage/src/rules/operation/RuleConditionalTransfer.sol.func-sort-c.html
index 5e3af45..6760052 100644
--- a/doc/test/coverage/src/rules/operation/RuleConditionalTransfer.sol.func-sort-c.html
+++ b/doc/test/coverage/src/rules/operation/RuleConditionalTransfer.sol.func-sort-c.html
@@ -31,13 +31,13 @@
|
-
-
-
+
+
+
-
+
|
@@ -49,9 +49,9 @@
|
|
-
-
-
+
+
+
|
@@ -69,68 +69,68 @@
Hit count |
- RuleConditionalTransfer._msgData |
+ RuleConditionalTransfer._msgData |
0 |
- RuleConditionalTransfer.canReturnTransferRestrictionCode |
+ RuleConditionalTransfer.canReturnTransferRestrictionCode |
2 |
- RuleConditionalTransfer.cancelTransferRequestBatch |
+ RuleConditionalTransfer.cancelTransferRequestBatch |
3 |
- RuleConditionalTransfer.createTransferRequestBatch |
+ RuleConditionalTransfer.createTransferRequestBatch |
3 |
- RuleConditionalTransfer.messageForTransferRestriction |
+ RuleConditionalTransfer.messageForTransferRestriction |
3 |
- RuleConditionalTransfer.cancelTransferRequest |
- 5 |
+ RuleConditionalTransfer.cancelTransferRequest |
+ 6 |
- RuleConditionalTransfer._cancelTransferRequest |
- 8 |
+ RuleConditionalTransfer._cancelTransferRequest |
+ 9 |
- RuleConditionalTransfer.detectTransferRestriction |
- 8 |
+ RuleConditionalTransfer.detectTransferRestriction |
+ 11 |
- RuleConditionalTransfer.operateOnTransfer |
- 14 |
+ RuleConditionalTransfer.operateOnTransfer |
+ 33 |
- RuleConditionalTransfer._validateApproval |
- 20 |
+ RuleConditionalTransfer.getRequestByStatus |
+ 35 |
- RuleConditionalTransfer._validateBurnMint |
- 22 |
+ RuleConditionalTransfer._validateApproval |
+ 37 |
- RuleConditionalTransfer.getRequestByStatus |
- 35 |
+ RuleConditionalTransfer._validateBurnMint |
+ 41 |
- RuleConditionalTransfer.getRequestTrade |
+ RuleConditionalTransfer.getRequestTrade |
57 |
- RuleConditionalTransfer.createTransferRequest |
- 91 |
+ RuleConditionalTransfer.createTransferRequest |
+ 102 |
- RuleConditionalTransfer._contextSuffixLength |
- 328 |
+ RuleConditionalTransfer._contextSuffixLength |
+ 452 |
- RuleConditionalTransfer._msgSender |
- 328 |
+ RuleConditionalTransfer._msgSender |
+ 452 |
diff --git a/doc/test/coverage/src/rules/operation/RuleConditionalTransfer.sol.func.html b/doc/test/coverage/src/rules/operation/RuleConditionalTransfer.sol.func.html
index d783f66..4bb3fe2 100644
--- a/doc/test/coverage/src/rules/operation/RuleConditionalTransfer.sol.func.html
+++ b/doc/test/coverage/src/rules/operation/RuleConditionalTransfer.sol.func.html
@@ -31,13 +31,13 @@
|
-
-
-
+
+
+
-
+
|
@@ -49,9 +49,9 @@
|
|
-
-
-
+
+
+
|
@@ -69,68 +69,68 @@
Hit count |
- RuleConditionalTransfer._cancelTransferRequest |
- 8 |
+ RuleConditionalTransfer._cancelTransferRequest |
+ 9 |
- RuleConditionalTransfer._contextSuffixLength |
- 328 |
+ RuleConditionalTransfer._contextSuffixLength |
+ 452 |
- RuleConditionalTransfer._msgData |
+ RuleConditionalTransfer._msgData |
0 |
- RuleConditionalTransfer._msgSender |
- 328 |
+ RuleConditionalTransfer._msgSender |
+ 452 |
- RuleConditionalTransfer._validateApproval |
- 20 |
+ RuleConditionalTransfer._validateApproval |
+ 37 |
- RuleConditionalTransfer._validateBurnMint |
- 22 |
+ RuleConditionalTransfer._validateBurnMint |
+ 41 |
- RuleConditionalTransfer.canReturnTransferRestrictionCode |
+ RuleConditionalTransfer.canReturnTransferRestrictionCode |
2 |
- RuleConditionalTransfer.cancelTransferRequest |
- 5 |
+ RuleConditionalTransfer.cancelTransferRequest |
+ 6 |
- RuleConditionalTransfer.cancelTransferRequestBatch |
+ RuleConditionalTransfer.cancelTransferRequestBatch |
3 |
- RuleConditionalTransfer.createTransferRequest |
- 91 |
+ RuleConditionalTransfer.createTransferRequest |
+ 102 |
- RuleConditionalTransfer.createTransferRequestBatch |
+ RuleConditionalTransfer.createTransferRequestBatch |
3 |
- RuleConditionalTransfer.detectTransferRestriction |
- 8 |
+ RuleConditionalTransfer.detectTransferRestriction |
+ 11 |
- RuleConditionalTransfer.getRequestByStatus |
+ RuleConditionalTransfer.getRequestByStatus |
35 |
- RuleConditionalTransfer.getRequestTrade |
+ RuleConditionalTransfer.getRequestTrade |
57 |
- RuleConditionalTransfer.messageForTransferRestriction |
+ RuleConditionalTransfer.messageForTransferRestriction |
3 |
- RuleConditionalTransfer.operateOnTransfer |
- 14 |
+ RuleConditionalTransfer.operateOnTransfer |
+ 33 |
diff --git a/doc/test/coverage/src/rules/operation/RuleConditionalTransfer.sol.gcov.html b/doc/test/coverage/src/rules/operation/RuleConditionalTransfer.sol.gcov.html
index 946bf16..d822f2b 100644
--- a/doc/test/coverage/src/rules/operation/RuleConditionalTransfer.sol.gcov.html
+++ b/doc/test/coverage/src/rules/operation/RuleConditionalTransfer.sol.gcov.html
@@ -31,13 +31,13 @@
|
-
-
-
+
+
+
-
+
|
@@ -49,9 +49,9 @@
|
|
-
-
-
+
+
+
|
@@ -113,284 +113,304 @@
42 : : options = options_;
43 : : }
44 : :
- 45 : : function createTransferRequest(
- 46 : : address to, uint256 value
- 47 : : ) public {
- 48 : : // WAIT => Will set a new delay to approve
- 49 : : // APPROVED => will overwrite previous status
- 50 : : // DENIED => KO
- 51 : 282 : address from = _msgSender();
- 52 : 282 : bytes32 key = keccak256(abi.encode(from, to, value));
- 53 [ + + ]: 188 : if(transferRequests[key].status == STATUS.DENIED){
- 54 : 2 : revert RuleConditionalTransfer_TransferDenied();
- 55 : : }
- 56 : : // Status NONE not enough because reset is possible
- 57 [ # + ]: 186 : if(_checkRequestStatus(key)){
- 58 : 180 : uint256 requestIdLocal = requestId;
- 59 : 270 : TransferRequest memory newTransferApproval = TransferRequest({
- 60 : : key:key,
- 61 : : id: requestIdLocal,
- 62 : : from: from,
- 63 : : to:to,
- 64 : : value:value,
- 65 : : askTime: block.timestamp,
- 66 : : maxTime:0,
- 67 : : status: STATUS.WAIT
- 68 : : }
- 69 : : );
- 70 : 180 : transferRequests[key] = newTransferApproval;
- 71 : 180 : IdToKey[requestIdLocal] = key;
- 72 : 180 : emit transferWaiting(key, from, to, value, requestId);
- 73 : 180 : ++requestId;
- 74 : : } else {
- 75 : : // Overwrite previous approval
- 76 : 6 : transferRequests[key].askTime = block.timestamp;
- 77 : 6 : transferRequests[key].status = STATUS.WAIT;
- 78 : 6 : emit transferWaiting(key, from, to, value, transferRequests[key].id);
- 79 : : }
- 80 : : }
- 81 : :
- 82 : : function createTransferRequestBatch(address[] memory tos, uint256[] memory values) public{
- 83 [ + + ]: 6 : if(tos.length == 0){
- 84 : 2 : revert RuleConditionalTransfer_EmptyArray();
- 85 : : }
- 86 [ + + ]: 4 : if(tos.length != values.length){
- 87 : 2 : revert RuleConditionalTransfer_InvalidLengthArray();
- 88 : : }
- 89 : 9 : for(uint256 i = 0; i < tos.length; ++i){
- 90 : 6 : createTransferRequest(tos[i], values[i]);
- 91 : : }
- 92 : : }
- 93 : :
- 94 : : /**
- 95 : : * @notice allow a token holder to cancel/reset his own request
- 96 : : */
- 97 : : function cancelTransferRequest(
- 98 : : uint256 requestId_
- 99 : : ) public {
- 100 : 10 : _cancelTransferRequest(requestId_);
- 101 : : }
- 102 : :
- 103 : : /**
- 104 : : * @notice allow a token holder to cancel/reset his own request
- 105 : : */
- 106 : : function cancelTransferRequestBatch(
- 107 : : uint256[] memory requestIds
- 108 : : ) public {
- 109 [ + + ]: 6 : if(requestIds.length == 0){
- 110 : 2 : revert RuleConditionalTransfer_EmptyArray();
- 111 : : }
- 112 : : // Check id validity before performing actions
- 113 : 14 : for(uint256 i = 0; i < requestIds.length; ++i){
- 114 [ + + ]: 15 : if(requestIds[i] + 1 > requestId) {
- 115 : 2 : revert RuleConditionalTransfer_InvalidId();
- 116 : : }
- 117 : : }
- 118 : 9 : for(uint256 i = 0; i < requestIds.length; ++i){
- 119 : 6 : _cancelTransferRequest(requestIds[i]);
- 120 : : }
- 121 : :
- 122 : : }
- 123 : :
- 124 : : function _cancelTransferRequest(
- 125 : : uint256 requestId_
- 126 : : ) internal {
- 127 [ + + ]: 24 : if(requestId_ + 1 > requestId) {
- 128 : 2 : revert RuleConditionalTransfer_InvalidId();
- 129 : : }
- 130 : 14 : bytes32 key = IdToKey[requestId_];
- 131 : : // Check Sender
- 132 [ + + ]: 21 : if(transferRequests[key].from != _msgSender()){
- 133 : 2 : revert RuleConditionalTransfer_InvalidSender();
- 134 : : }
- 135 : : // Check status
- 136 [ + + ]: 18 : if(transferRequests[key].status != STATUS.WAIT
- 137 : 4 : && transferRequests[key].status != STATUS.APPROVED
- 138 : : ){
- 139 : 2 : revert RuleConditionalTransfer_Wrong_Status();
- 140 : : }
- 141 : 10 : _resetRequestStatus(key);
- 142 : : }
- 143 : :
- 144 : :
- 145 : : function getRequestTrade(address from, address to, uint256 value) public view returns (TransferRequest memory) {
- 146 : 171 : bytes32 key = keccak256(abi.encode(from, to, value));
- 147 : 114 : return transferRequests[key];
- 148 : : }
- 149 : :
- 150 : : /**
- 151 : : * @notice get Trade by status
- 152 : : * @param _targetStatus The status of the transactions you want to retrieve
- 153 : : * @return array with corresponding transactions
- 154 : : */
- 155 : : function getRequestByStatus(STATUS _targetStatus) public view returns (TransferRequest[] memory) {
- 156 : 70 : uint totalRequestCount = requestId;
- 157 : 70 : uint requestCount = 0;
- 158 : 70 : uint currentIndex = 0;
- 159 : :
- 160 : : // We count the number of requests matching the criteria
- 161 : 181 : for (uint i = 0; i < totalRequestCount; ++i) {
- 162 [ + + ]: 76 : if (transferRequests[IdToKey[i]].status == _targetStatus) {
- 163 : 72 : requestCount += 1;
- 164 : : }
- 165 : : }
+ 45 : : /**
+ 46 : : * @notice Create a request of transfer for yourselves
+ 47 : : * @param to recipient of tokens
+ 48 : : * @param value amount of tokens to transfer
+ 49 : : */
+ 50 : : function createTransferRequest(
+ 51 : : address to, uint256 value
+ 52 : : ) public {
+ 53 : : // WAIT => Will set a new delay to approve
+ 54 : : // APPROVED => will overwrite previous status
+ 55 : : // DENIED => reject
+ 56 : 315 : address from = _msgSender();
+ 57 : 315 : bytes32 key = keccak256(abi.encode(from, to, value));
+ 58 [ + + ]: 210 : if(transferRequests[key].status == STATUS.DENIED){
+ 59 : 2 : revert RuleConditionalTransfer_TransferDenied();
+ 60 : : }
+ 61 [ # + ]: 208 : if(_checkRequestStatus(key)){
+ 62 : 202 : uint256 requestIdLocal = requestId;
+ 63 : 303 : TransferRequest memory newTransferApproval = TransferRequest({
+ 64 : : key:key,
+ 65 : : id: requestIdLocal,
+ 66 : : from: from,
+ 67 : : to:to,
+ 68 : : value:value,
+ 69 : : askTime: block.timestamp,
+ 70 : : maxTime:0,
+ 71 : : status: STATUS.WAIT
+ 72 : : }
+ 73 : : );
+ 74 : 202 : transferRequests[key] = newTransferApproval;
+ 75 : 202 : IdToKey[requestIdLocal] = key;
+ 76 : 202 : emit transferWaiting(key, from, to, value, requestId);
+ 77 : 202 : ++requestId;
+ 78 : : } else {
+ 79 : : // Overwrite previous approval
+ 80 : 6 : transferRequests[key].askTime = block.timestamp;
+ 81 : 6 : transferRequests[key].status = STATUS.WAIT;
+ 82 : 6 : emit transferWaiting(key, from, to, value, transferRequests[key].id);
+ 83 : : }
+ 84 : : }
+ 85 : :
+ 86 : : /**
+ 87 : : * @notice Batch version of {createTransferRequest}
+ 88 : : */
+ 89 : : function createTransferRequestBatch(address[] memory tos, uint256[] memory values) public{
+ 90 [ + + ]: 6 : if(tos.length == 0){
+ 91 : 2 : revert RuleConditionalTransfer_EmptyArray();
+ 92 : : }
+ 93 [ + + ]: 4 : if(tos.length != values.length){
+ 94 : 2 : revert RuleConditionalTransfer_InvalidLengthArray();
+ 95 : : }
+ 96 : 9 : for(uint256 i = 0; i < tos.length; ++i){
+ 97 : 6 : createTransferRequest(tos[i], values[i]);
+ 98 : : }
+ 99 : : }
+ 100 : :
+ 101 : : /**
+ 102 : : * @notice allow a token holder to cancel/reset his own request
+ 103 : : */
+ 104 : : function cancelTransferRequest(
+ 105 : : uint256 requestId_
+ 106 : : ) public {
+ 107 : 12 : _cancelTransferRequest(requestId_);
+ 108 : : }
+ 109 : :
+ 110 : : /**
+ 111 : : * @notice allow a token holder to cancel/reset his own request
+ 112 : : */
+ 113 : : function cancelTransferRequestBatch(
+ 114 : : uint256[] memory requestIds
+ 115 : : ) public {
+ 116 [ + + ]: 6 : if(requestIds.length == 0){
+ 117 : 2 : revert RuleConditionalTransfer_EmptyArray();
+ 118 : : }
+ 119 : : // Check id validity before performing actions
+ 120 : 14 : for(uint256 i = 0; i < requestIds.length; ++i){
+ 121 [ + + ]: 15 : if(requestIds[i] + 1 > requestId) {
+ 122 : 2 : revert RuleConditionalTransfer_InvalidId();
+ 123 : : }
+ 124 : : }
+ 125 : 9 : for(uint256 i = 0; i < requestIds.length; ++i){
+ 126 : 6 : _cancelTransferRequest(requestIds[i]);
+ 127 : : }
+ 128 : :
+ 129 : : }
+ 130 : :
+ 131 : : function _cancelTransferRequest(
+ 132 : : uint256 requestId_
+ 133 : : ) internal {
+ 134 [ + + ]: 27 : if(requestId_ + 1 > requestId) {
+ 135 : 2 : revert RuleConditionalTransfer_InvalidId();
+ 136 : : }
+ 137 : 16 : bytes32 key = IdToKey[requestId_];
+ 138 : : // Check Sender
+ 139 [ + + ]: 24 : if(transferRequests[key].from != _msgSender()){
+ 140 : 2 : revert RuleConditionalTransfer_InvalidSender();
+ 141 : : }
+ 142 : : // Check status
+ 143 [ + + ]: 21 : if(transferRequests[key].status != STATUS.WAIT
+ 144 : 4 : && transferRequests[key].status != STATUS.APPROVED
+ 145 : : ){
+ 146 : 2 : revert RuleConditionalTransfer_Wrong_Status();
+ 147 : : }
+ 148 : 12 : _resetRequestStatus(key);
+ 149 : : }
+ 150 : :
+ 151 : :
+ 152 : : function getRequestTrade(address from, address to, uint256 value) public view returns (TransferRequest memory) {
+ 153 : 171 : bytes32 key = keccak256(abi.encode(from, to, value));
+ 154 : 114 : return transferRequests[key];
+ 155 : : }
+ 156 : :
+ 157 : : /**
+ 158 : : * @notice get Trade by status
+ 159 : : * @param _targetStatus The status of the transactions you want to retrieve
+ 160 : : * @return array with corresponding transactions
+ 161 : : */
+ 162 : : function getRequestByStatus(STATUS _targetStatus) public view returns (TransferRequest[] memory) {
+ 163 : 70 : uint totalRequestCount = requestId;
+ 164 : 70 : uint requestCount = 0;
+ 165 : 70 : uint currentIndex = 0;
166 : :
- 167 : : // We reserve the memory to store the trade
- 168 : 105 : TransferRequest[] memory requests = new TransferRequest[](requestCount);
- 169 : :
- 170 : : // We create an array with the list of trade
- 171 : 181 : for (uint i = 0; i < totalRequestCount; ++i) {
- 172 [ # + ]: 76 : if (transferRequests[IdToKey[i]].status == _targetStatus) {
- 173 : : //uint currentId = i + 1;
- 174 : 72 : TransferRequest memory currentRequest = transferRequests[IdToKey[i]];
- 175 : 72 : requests[currentIndex] = currentRequest;
- 176 : 72 : currentIndex += 1;
- 177 : : }
- 178 : : }
- 179 : 70 : return requests;
- 180 : : }
- 181 : :
- 182 : : /**
- 183 : : * @dev Returns true if the transfer is valid, and false otherwise.
- 184 : : * Add access control with the RuleEngine
- 185 : : */
- 186 : : function operateOnTransfer(
- 187 : : address _from,
- 188 : : address _to,
- 189 : : uint256 _amount
- 190 : : ) public override onlyRole(RULE_ENGINE_CONTRACT_ROLE) returns(bool isValid){
- 191 : : // Mint & Burn
- 192 [ + + ]: 28 : if(_validateBurnMint(_from, _to)) {
- 193 : 4 : return true;
- 194 : : }
- 195 : 36 : bytes32 key = keccak256(abi.encode(_from, _to, _amount));
- 196 [ + + ]: 24 : if(_validateApproval(key)) {
- 197 : 10 : _updateProcessedTransfer(key);
- 198 : 10 : return true;
- 199 : : } else {
- 200 : 14 : return false;
- 201 : : }
- 202 : : }
- 203 : :
- 204 : : /**
- 205 : : * @notice Check if the transfer is valid
- 206 : : * @param _from the origin address
- 207 : : * @param _to the destination address
- 208 : : * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK
- 209 : : **/
- 210 : : function detectTransferRestriction(
- 211 : : address _from,
- 212 : : address _to,
- 213 : : uint256 _amount
- 214 : : ) public view override returns (uint8) {
- 215 : 24 : bytes32 key = keccak256(abi.encode(_from, _to, _amount));
- 216 [ + + ]: 32 : if (!_validateBurnMint(_from,_to) && !_validateApproval(key)) {
- 217 : 12 : return CODE_TRANSFER_REQUEST_NOT_APPROVED;
- 218 : : }
- 219 : : else {
- 220 : 6 : return uint8(REJECTED_CODE_BASE.TRANSFER_OK);
- 221 : : }
- 222 : : }
- 223 : :
- 224 : : /**
- 225 : : * @notice To know if the restriction code is valid for this rule or not.
- 226 : : * @param _restrictionCode The target restriction code
- 227 : : * @return true if the restriction code is known, false otherwise
- 228 : : **/
- 229 : : function canReturnTransferRestrictionCode(
- 230 : : uint8 _restrictionCode
- 231 : : ) external pure override returns (bool) {
- 232 : 4 : return
- 233 : 4 : _restrictionCode == CODE_TRANSFER_REQUEST_NOT_APPROVED;
- 234 : : }
- 235 : :
- 236 : : /**
- 237 : : * @notice Return the corresponding message
- 238 : : * @param _restrictionCode The target restriction code
- 239 : : * @return true if the transfer is valid, false otherwise
- 240 : : **/
- 241 : : function messageForTransferRestriction(
- 242 : : uint8 _restrictionCode
- 243 : : ) external pure override returns (string memory) {
- 244 [ + + ]: 6 : if (_restrictionCode == CODE_TRANSFER_REQUEST_NOT_APPROVED) {
- 245 : 4 : return TEXT_TRANSFER_REQUEST_NOT_APPROVED;
- 246 : : } else {
- 247 : 2 : return TEXT_CODE_NOT_FOUND;
- 248 : : }
- 249 : : }
- 250 : :
- 251 : : /**
- 252 : : *
- 253 : : * @dev
- 254 : : * Test burn and mint condition
- 255 : : * Returns true if the transfer is valid, and false otherwise.
- 256 : : *
- 257 : : */
- 258 : : function _validateBurnMint(
- 259 : : address _from,
- 260 : : address _to
- 261 : : ) internal view returns(bool isValid){
- 262 : : // Mint & Burn
- 263 [ + + ]: : if(
- 264 : 44 : (_from == address(0) && options.issuance.authorizedMintWithoutApproval)
- 265 : : || (_to == address(0) && options.issuance.authorizedBurnWithoutApproval)
- 266 : : ){
- 267 : 4 : return true;
+ 167 : : // We count the number of requests matching the criteria
+ 168 : 181 : for (uint i = 0; i < totalRequestCount; ++i) {
+ 169 [ + + ]: 76 : if (transferRequests[IdToKey[i]].status == _targetStatus) {
+ 170 : 72 : requestCount += 1;
+ 171 : : }
+ 172 : : }
+ 173 : :
+ 174 : : // We reserve the memory to store the trade
+ 175 : 105 : TransferRequest[] memory requests = new TransferRequest[](requestCount);
+ 176 : :
+ 177 : : // We create an array with the list of trade
+ 178 : 181 : for (uint i = 0; i < totalRequestCount; ++i) {
+ 179 [ # + ]: 76 : if (transferRequests[IdToKey[i]].status == _targetStatus) {
+ 180 : : //uint currentId = i + 1;
+ 181 : 72 : TransferRequest memory currentRequest = transferRequests[IdToKey[i]];
+ 182 : 72 : requests[currentIndex] = currentRequest;
+ 183 : 72 : currentIndex += 1;
+ 184 : : }
+ 185 : : }
+ 186 : 70 : return requests;
+ 187 : : }
+ 188 : :
+ 189 : : /**
+ 190 : : * @dev Returns true if the transfer is valid, and false otherwise.
+ 191 : : * Add access control with the RuleEngine
+ 192 : : */
+ 193 : : function operateOnTransfer(
+ 194 : : address _from,
+ 195 : : address _to,
+ 196 : : uint256 _amount
+ 197 : : ) public override onlyRole(RULE_ENGINE_CONTRACT_ROLE) returns(bool isValid){
+ 198 : : // No need of approval if from and to are in the whitelist
+ 199 [ + + ]: 132 : if(address(whitelistConditionalTransfer) != address(0)){
+ 200 [ + + ]: 57 : if(whitelistConditionalTransfer.addressIsListed(_from) && whitelistConditionalTransfer.addressIsListed(_to)){
+ 201 : 4 : return true;
+ 202 : : }
+ 203 : : }
+ 204 : :
+ 205 : : // Mint & Burn
+ 206 [ + + ]: 62 : if(_validateBurnMint(_from, _to)) {
+ 207 : 8 : return true;
+ 208 : : }
+ 209 : 81 : bytes32 key = keccak256(abi.encode(_from, _to, _amount));
+ 210 [ + + ]: 54 : if(_validateApproval(key)) {
+ 211 : 20 : _updateProcessedTransfer(key);
+ 212 : 20 : return true;
+ 213 : : } else {
+ 214 : 34 : return false;
+ 215 : : }
+ 216 : : }
+ 217 : :
+ 218 : : /**
+ 219 : : * @notice Check if the transfer is valid
+ 220 : : * @param _from the origin address
+ 221 : : * @param _to the destination address
+ 222 : : * @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK
+ 223 : : **/
+ 224 : : function detectTransferRestriction(
+ 225 : : address _from,
+ 226 : : address _to,
+ 227 : : uint256 _amount
+ 228 : : ) public view override returns (uint8) {
+ 229 : : // No need of approval if from and to are in the whitelist
+ 230 [ # + ]: 44 : if(address(whitelistConditionalTransfer) != address(0)){
+ 231 [ # + ]: 11 : if(whitelistConditionalTransfer.addressIsListed(_from) && whitelistConditionalTransfer.addressIsListed(_to)){
+ 232 : 3 : return uint8(REJECTED_CODE_BASE.TRANSFER_OK);
+ 233 : : }
+ 234 : : }
+ 235 : 30 : bytes32 key = keccak256(abi.encode(_from, _to, _amount));
+ 236 [ + + ]: 40 : if (!_validateBurnMint(_from,_to) && !_validateApproval(key)) {
+ 237 : 16 : return CODE_TRANSFER_REQUEST_NOT_APPROVED;
+ 238 : : }
+ 239 : : else {
+ 240 : 6 : return uint8(REJECTED_CODE_BASE.TRANSFER_OK);
+ 241 : : }
+ 242 : : }
+ 243 : :
+ 244 : : /**
+ 245 : : * @notice To know if the restriction code is valid for this rule or not.
+ 246 : : * @param _restrictionCode The target restriction code
+ 247 : : * @return true if the restriction code is known, false otherwise
+ 248 : : **/
+ 249 : : function canReturnTransferRestrictionCode(
+ 250 : : uint8 _restrictionCode
+ 251 : : ) external pure override returns (bool) {
+ 252 : 4 : return
+ 253 : 4 : _restrictionCode == CODE_TRANSFER_REQUEST_NOT_APPROVED;
+ 254 : : }
+ 255 : :
+ 256 : : /**
+ 257 : : * @notice Return the corresponding message
+ 258 : : * @param _restrictionCode The target restriction code
+ 259 : : * @return true if the transfer is valid, false otherwise
+ 260 : : **/
+ 261 : : function messageForTransferRestriction(
+ 262 : : uint8 _restrictionCode
+ 263 : : ) external pure override returns (string memory) {
+ 264 [ + + ]: 6 : if (_restrictionCode == CODE_TRANSFER_REQUEST_NOT_APPROVED) {
+ 265 : 4 : return TEXT_TRANSFER_REQUEST_NOT_APPROVED;
+ 266 : : } else {
+ 267 : 2 : return TEXT_CODE_NOT_FOUND;
268 : : }
- 269 : 40 : return false;
- 270 : : }
- 271 : :
- 272 : : /**
- 273 : : *
- 274 : : * @dev
- 275 : : * Test transfer approval condition
- 276 : : * Returns true if the transfer is valid, and false otherwise.
+ 269 : : }
+ 270 : :
+ 271 : : /**
+ 272 : : *
+ 273 : : * @dev
+ 274 : : * Test burn and mint condition
+ 275 : : * Returns true if the transfer is valid, and false otherwise.
+ 276 : : *
277 : : */
- 278 : : function _validateApproval(
- 279 : : bytes32 key
- 280 : : ) internal view returns(bool isValid){
- 281 : 60 : bool automaticApprovalCondition = options.automaticApproval.isActivate && ((transferRequests[key].askTime + options.automaticApproval.timeLimitBeforeAutomaticApproval ) >= block.timestamp);
- 282 : 60 : bool isTransferApproved = (transferRequests[key].status == STATUS.APPROVED)
- 283 : : && (transferRequests[key].maxTime >= block.timestamp);
- 284 [ + + ]: 40 : if(automaticApprovalCondition || isTransferApproved)
- 285 : : {
- 286 : 14 : return true;
- 287 : : } else {
- 288 : 26 : return false;
- 289 : : }
+ 278 : : function _validateBurnMint(
+ 279 : : address _from,
+ 280 : : address _to
+ 281 : : ) internal view returns(bool isValid){
+ 282 : : // Mint & Burn
+ 283 [ + + ]: : if(
+ 284 : 82 : (_from == address(0) && options.issuance.authorizedMintWithoutApproval)
+ 285 : : || (_to == address(0) && options.issuance.authorizedBurnWithoutApproval)
+ 286 : : ){
+ 287 : 8 : return true;
+ 288 : : }
+ 289 : 74 : return false;
290 : : }
291 : :
- 292 : : /**
- 293 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule
- 294 : : */
- 295 : : function _msgSender()
- 296 : : internal
- 297 : : view
- 298 : : override(ERC2771Context, Context)
- 299 : : returns (address sender)
- 300 : : {
- 301 : 984 : return ERC2771Context._msgSender();
- 302 : : }
- 303 : :
- 304 : : /**
- 305 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule
- 306 : : */
- 307 : : function _msgData()
- 308 : : internal
- 309 : : view
- 310 : : override(ERC2771Context, Context)
- 311 : : returns (bytes calldata)
- 312 : : {
- 313 : 0 : return ERC2771Context._msgData();
- 314 : : }
- 315 : :
- 316 : : /**
- 317 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule
- 318 : : */
- 319 : : function _contextSuffixLength() internal view override(ERC2771Context, Context) returns (uint256) {
- 320 : 984 : return ERC2771Context._contextSuffixLength();
- 321 : : }
- 322 : : }
+ 292 : : /**
+ 293 : : *
+ 294 : : * @dev
+ 295 : : * Test transfer approval condition
+ 296 : : * Returns true if the transfer is valid, and false otherwise.
+ 297 : : */
+ 298 : : function _validateApproval(
+ 299 : : bytes32 key
+ 300 : : ) internal view returns(bool isValid){
+ 301 : 111 : bool automaticApprovalCondition = options.automaticApproval.isActivate && ((transferRequests[key].askTime + options.automaticApproval.timeLimitBeforeAutomaticApproval ) >= block.timestamp);
+ 302 : 111 : bool isTransferApproved = (transferRequests[key].status == STATUS.APPROVED)
+ 303 : : && (transferRequests[key].maxTime >= block.timestamp);
+ 304 [ + + ]: 74 : if(automaticApprovalCondition || isTransferApproved)
+ 305 : : {
+ 306 : 24 : return true;
+ 307 : : } else {
+ 308 : 50 : return false;
+ 309 : : }
+ 310 : : }
+ 311 : :
+ 312 : : /**
+ 313 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule
+ 314 : : */
+ 315 : : function _msgSender()
+ 316 : : internal
+ 317 : : view
+ 318 : : override(ERC2771Context, Context)
+ 319 : : returns (address sender)
+ 320 : : {
+ 321 : 1356 : return ERC2771Context._msgSender();
+ 322 : : }
+ 323 : :
+ 324 : : /**
+ 325 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule
+ 326 : : */
+ 327 : : function _msgData()
+ 328 : : internal
+ 329 : : view
+ 330 : : override(ERC2771Context, Context)
+ 331 : : returns (bytes calldata)
+ 332 : : {
+ 333 : 0 : return ERC2771Context._msgData();
+ 334 : : }
+ 335 : :
+ 336 : : /**
+ 337 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule
+ 338 : : */
+ 339 : : function _contextSuffixLength() internal view override(ERC2771Context, Context) returns (uint256) {
+ 340 : 1356 : return ERC2771Context._contextSuffixLength();
+ 341 : : }
+ 342 : : }
diff --git a/doc/test/coverage/src/rules/operation/abstract/RuleConditionalTransferOperator.sol.func-sort-c.html b/doc/test/coverage/src/rules/operation/abstract/RuleConditionalTransferOperator.sol.func-sort-c.html
index 48bbaa7..b1117d6 100644
--- a/doc/test/coverage/src/rules/operation/abstract/RuleConditionalTransferOperator.sol.func-sort-c.html
+++ b/doc/test/coverage/src/rules/operation/abstract/RuleConditionalTransferOperator.sol.func-sort-c.html
@@ -31,18 +31,18 @@
|
-
-
+
+
-
+
|
-
-
+
+
|
@@ -69,76 +69,80 @@
Hit count |
- RuleConditionalTransferOperator._createTransferRequestWithApproval |
+ RuleConditionalTransferOperator._createTransferRequestWithApproval |
0 |
- RuleConditionalTransferOperator.createTransferRequestWithApprovalBatch |
- 2 |
-
-
- RuleConditionalTransferOperator.setAutomaticTransfer |
- 2 |
+ RuleConditionalTransferOperator.createTransferRequestWithApprovalBatch |
+ 3 |
- RuleConditionalTransferOperator.resetRequestStatus |
+ RuleConditionalTransferOperator.resetRequestStatus |
3 |
- RuleConditionalTransferOperator.resetRequestStatusBatch |
+ RuleConditionalTransferOperator.resetRequestStatusBatch |
3 |
- RuleConditionalTransferOperator.setAutomaticApproval |
+ RuleConditionalTransferOperator.setAutomaticTransfer |
3 |
- RuleConditionalTransferOperator.setIssuanceOptions |
- 3 |
+ RuleConditionalTransferOperator.setTimeLimit |
+ 4 |
- RuleConditionalTransferOperator.setTimeLimit |
- 3 |
+ RuleConditionalTransferOperator.approveTransferRequestWithId |
+ 5 |
- RuleConditionalTransferOperator._updateProcessedTransfer |
+ RuleConditionalTransferOperator.setAutomaticApproval |
5 |
- RuleConditionalTransferOperator.approveTransferRequestWithId |
+ RuleConditionalTransferOperator.setIssuanceOptions |
5 |
- RuleConditionalTransferOperator.approveTransferRequestBatch |
+ RuleConditionalTransferOperator.createTransferRequestWithApproval |
6 |
- RuleConditionalTransferOperator.approveTransferRequestBatchWithId |
- 6 |
+ RuleConditionalTransferOperator.approveTransferRequestBatch |
+ 7 |
- RuleConditionalTransferOperator.createTransferRequestWithApproval |
- 6 |
+ RuleConditionalTransferOperator.approveTransferRequestBatchWithId |
+ 7 |
+
+
+ RuleConditionalTransferOperator._resetRequestStatus |
+ 10 |
+
+
+ RuleConditionalTransferOperator._updateProcessedTransfer |
+ 10 |
- RuleConditionalTransferOperator._resetRequestStatus |
- 9 |
+ RuleConditionalTransferOperator.setConditionalWhitelist |
+ 25 |
- RuleConditionalTransferOperator.approveTransferRequest |
- 26 |
+ RuleConditionalTransferOperator.approveTransferRequest |
+ 33 |
- RuleConditionalTransferOperator._approveTransferRequestKeyElement |
- 34 |
+ RuleConditionalTransferOperator._approveTransferRequestKeyElement |
+ 41 |
- RuleConditionalTransferOperator._approveRequest |
- 39 |
+ RuleConditionalTransferOperator._approveRequest |
+ 46 |
- RuleConditionalTransferOperator._checkRequestStatus |
- 106 |
+ RuleConditionalTransferOperator._checkRequestStatus |
+ 119 |
diff --git a/doc/test/coverage/src/rules/operation/abstract/RuleConditionalTransferOperator.sol.func.html b/doc/test/coverage/src/rules/operation/abstract/RuleConditionalTransferOperator.sol.func.html
index 2636fb2..7f4ac9d 100644
--- a/doc/test/coverage/src/rules/operation/abstract/RuleConditionalTransferOperator.sol.func.html
+++ b/doc/test/coverage/src/rules/operation/abstract/RuleConditionalTransferOperator.sol.func.html
@@ -31,18 +31,18 @@
|
-
-
+
+
-
+
|
-
-
+
+
|
@@ -69,76 +69,80 @@
Hit count |
- RuleConditionalTransferOperator._approveRequest |
- 39 |
+ RuleConditionalTransferOperator._approveRequest |
+ 46 |
- RuleConditionalTransferOperator._approveTransferRequestKeyElement |
- 34 |
+ RuleConditionalTransferOperator._approveTransferRequestKeyElement |
+ 41 |
- RuleConditionalTransferOperator._checkRequestStatus |
- 106 |
+ RuleConditionalTransferOperator._checkRequestStatus |
+ 119 |
- RuleConditionalTransferOperator._createTransferRequestWithApproval |
+ RuleConditionalTransferOperator._createTransferRequestWithApproval |
0 |
- RuleConditionalTransferOperator._resetRequestStatus |
- 9 |
+ RuleConditionalTransferOperator._resetRequestStatus |
+ 10 |
- RuleConditionalTransferOperator._updateProcessedTransfer |
- 5 |
+ RuleConditionalTransferOperator._updateProcessedTransfer |
+ 10 |
- RuleConditionalTransferOperator.approveTransferRequest |
- 26 |
+ RuleConditionalTransferOperator.approveTransferRequest |
+ 33 |
- RuleConditionalTransferOperator.approveTransferRequestBatch |
- 6 |
+ RuleConditionalTransferOperator.approveTransferRequestBatch |
+ 7 |
- RuleConditionalTransferOperator.approveTransferRequestBatchWithId |
- 6 |
+ RuleConditionalTransferOperator.approveTransferRequestBatchWithId |
+ 7 |
- RuleConditionalTransferOperator.approveTransferRequestWithId |
+ RuleConditionalTransferOperator.approveTransferRequestWithId |
5 |
- RuleConditionalTransferOperator.createTransferRequestWithApproval |
+ RuleConditionalTransferOperator.createTransferRequestWithApproval |
6 |
- RuleConditionalTransferOperator.createTransferRequestWithApprovalBatch |
- 2 |
+ RuleConditionalTransferOperator.createTransferRequestWithApprovalBatch |
+ 3 |
- RuleConditionalTransferOperator.resetRequestStatus |
+ RuleConditionalTransferOperator.resetRequestStatus |
3 |
- RuleConditionalTransferOperator.resetRequestStatusBatch |
+ RuleConditionalTransferOperator.resetRequestStatusBatch |
3 |
- RuleConditionalTransferOperator.setAutomaticApproval |
+ RuleConditionalTransferOperator.setAutomaticApproval |
+ 5 |
+
+
+ RuleConditionalTransferOperator.setAutomaticTransfer |
3 |
- RuleConditionalTransferOperator.setAutomaticTransfer |
- 2 |
+ RuleConditionalTransferOperator.setConditionalWhitelist |
+ 25 |
- RuleConditionalTransferOperator.setIssuanceOptions |
- 3 |
+ RuleConditionalTransferOperator.setIssuanceOptions |
+ 5 |
- RuleConditionalTransferOperator.setTimeLimit |
- 3 |
+ RuleConditionalTransferOperator.setTimeLimit |
+ 4 |
diff --git a/doc/test/coverage/src/rules/operation/abstract/RuleConditionalTransferOperator.sol.gcov.html b/doc/test/coverage/src/rules/operation/abstract/RuleConditionalTransferOperator.sol.gcov.html
index 7f605fd..0c436a8 100644
--- a/doc/test/coverage/src/rules/operation/abstract/RuleConditionalTransferOperator.sol.gcov.html
+++ b/doc/test/coverage/src/rules/operation/abstract/RuleConditionalTransferOperator.sol.gcov.html
@@ -31,18 +31,18 @@
|
-
-
+
+
-
+
|
-
-
+
+
|
@@ -76,279 +76,313 @@
5 : : import "OZ/access/AccessControl.sol";
6 : : import "./RuleConditionalTransferInvariantStorage.sol";
7 : : import "OZ/token/ERC20/utils/SafeERC20.sol";
- 8 : :
- 9 : : /**
- 10 : : * @title a RuleConditionalTransfer manager
- 11 : : */
- 12 : :
- 13 : : abstract contract RuleConditionalTransferOperator is AccessControl, RuleConditionalTransferInvariantStorage {
- 14 : : // Security
- 15 : : using SafeERC20 for IERC20;
- 16 : :
- 17 : : OPTION internal options;
- 18 : :
- 19 : :
- 20 : : // Getter
- 21 : : uint256 public requestId;
- 22 : : mapping(uint256 => bytes32) public IdToKey;
- 23 : : mapping(bytes32 => TransferRequest) public transferRequests;
- 24 : :
- 25 : :
- 26 : : function setIssuanceOptions(ISSUANCE calldata issuance_) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE){
- 27 [ + + ]: 4 : if(options.issuance.authorizedMintWithoutApproval != issuance_.authorizedMintWithoutApproval ){
- 28 : 2 : options.issuance.authorizedMintWithoutApproval = issuance_.authorizedMintWithoutApproval;
- 29 : : }
- 30 [ + + ]: 4 : if(options.issuance.authorizedBurnWithoutApproval != issuance_.authorizedBurnWithoutApproval ){
- 31 : 2 : options.issuance.authorizedBurnWithoutApproval = issuance_.authorizedBurnWithoutApproval;
- 32 : : }
- 33 : : }
- 34 : :
- 35 : : function setAutomaticTransfer(AUTOMATIC_TRANSFER calldata automaticTransfer_) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE){
- 36 [ + + ]: 2 : if(automaticTransfer_.isActivate != options.automaticTransfer.isActivate){
- 37 : 2 : options.automaticTransfer.isActivate = automaticTransfer_.isActivate;
- 38 : : }
- 39 : : // No need to put the cmtat to zero to deactivate automaticTransfer
- 40 [ + + ]: 4 : if(address(automaticTransfer_.cmtat) != address(options.automaticTransfer.cmtat)){
- 41 : 2 : options.automaticTransfer.cmtat = automaticTransfer_.cmtat;
- 42 : : }
- 43 : : }
- 44 : :
- 45 : : /**
- 46 : : * @notice set time limit for new requests (Approval and transfer)
- 47 : : * Don't affect already created requests
- 48 : : */
- 49 : : function setTimeLimit(TIME_LIMIT memory timeLimit_) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE){
- 50 [ + + ]: 4 : if(options.timeLimit.timeLimitToApprove != timeLimit_.timeLimitToApprove){
- 51 : 4 : options.timeLimit.timeLimitToApprove = timeLimit_.timeLimitToApprove;
- 52 : : }
- 53 [ + + ]: 4 : if(options.timeLimit.timeLimitToTransfer != timeLimit_.timeLimitToTransfer){
- 54 : 4 : options.timeLimit.timeLimitToTransfer = timeLimit_.timeLimitToTransfer;
- 55 : : }
- 56 : : }
- 57 : :
- 58 : : function setAutomaticApproval(AUTOMATIC_APPROVAL memory automaticApproval_) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE){
- 59 [ + + ]: 4 : if(options.automaticApproval.isActivate != automaticApproval_.isActivate ){
- 60 : 4 : options.automaticApproval.isActivate = automaticApproval_.isActivate;
- 61 : : }
- 62 [ + + ]: 4 : if(options.automaticApproval.timeLimitBeforeAutomaticApproval != automaticApproval_.timeLimitBeforeAutomaticApproval){
- 63 : 4 : options.automaticApproval.timeLimitBeforeAutomaticApproval = automaticApproval_.timeLimitBeforeAutomaticApproval;
- 64 : : }
- 65 : : }
- 66 : :
- 67 : :
- 68 : : function createTransferRequestWithApproval(
- 69 : : TransferRequestKeyElement calldata keyElement
- 70 : : ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE){
- 71 : 10 : _createTransferRequestWithApproval(keyElement);
- 72 : : }
- 73 : :
- 74 : : /**
- 75 : : @param keyElement contains from, to, value
- 76 : : @param partialValue amount approved. Put 0 if all the amount specified by value is approved.
- 77 : : @param isApproved_ approved (true) or refused (false). Put true if you use partialApproval
- 78 : : */
- 79 : : function approveTransferRequest(
- 80 : : TransferRequestKeyElement calldata keyElement, uint256 partialValue, bool isApproved_
- 81 : : ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE) {
- 82 : 50 : _approveTransferRequestKeyElement(keyElement, partialValue, isApproved_);
- 83 : : }
- 84 : :
- 85 : : function approveTransferRequestWithId(
- 86 : : uint256 requestId_, bool isApproved_
- 87 : : ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE){
- 88 [ + + ]: 12 : if(requestId_ + 1 > requestId) {
- 89 : 4 : revert RuleConditionalTransfer_InvalidId();
- 90 : : }
- 91 : 4 : TransferRequest memory transferRequest = transferRequests[IdToKey[requestId_]];
- 92 : 4 : _approveRequest(transferRequest, isApproved_);
- 93 : : }
- 94 : :
- 95 : :
- 96 : : function resetRequestStatus(
- 97 : : uint256 requestId_
- 98 : : ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE){
- 99 [ + + ]: 6 : if(requestId_ + 1 > requestId) {
- 100 : 2 : revert RuleConditionalTransfer_InvalidId();
- 101 : : }
- 102 : 2 : bytes32 key = IdToKey[requestId_];
- 103 : 2 : _resetRequestStatus(key);
- 104 : : }
- 105 : :
- 106 : : /***** Batch function */
- 107 : :
- 108 : : function approveTransferRequestBatchWithId(
- 109 : : uint256[] calldata requestId_, bool[] calldata isApproved_
+ 8 : : /**
+ 9 : : * @title Restricted functions
+ 10 : : */
+ 11 : : abstract contract RuleConditionalTransferOperator is AccessControl, RuleConditionalTransferInvariantStorage {
+ 12 : : // Security
+ 13 : : using SafeERC20 for IERC20;
+ 14 : :
+ 15 : : // public variable with automatic Getter
+ 16 : : OPTION public options;
+ 17 : : uint256 public requestId;
+ 18 : : mapping(uint256 => bytes32) public IdToKey;
+ 19 : : mapping(bytes32 => TransferRequest) public transferRequests;
+ 20 : : RuleWhitelist public whitelistConditionalTransfer;
+ 21 : :
+ 22 : : /**
+ 23 : : * @notice set a whitelist. A transfer does not need of an approved request if from and to are in the whitelist
+ 24 : : */
+ 25 : : function setConditionalWhitelist(RuleWhitelist newWhitelistConditionalTransfer) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE){
+ 26 : 50 : whitelistConditionalTransfer = newWhitelistConditionalTransfer;
+ 27 : 50 : emit WhitelistConditionalTransfer(newWhitelistConditionalTransfer);
+ 28 : : }
+ 29 : :
+ 30 : : /**
+ 31 : : set/unset the issuance options (mint & burn)
+ 32 : : */
+ 33 : : function setIssuanceOptions(ISSUANCE calldata issuance_) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE){
+ 34 [ + + ]: 8 : if(options.issuance.authorizedMintWithoutApproval != issuance_.authorizedMintWithoutApproval ){
+ 35 : 4 : options.issuance.authorizedMintWithoutApproval = issuance_.authorizedMintWithoutApproval;
+ 36 : : }
+ 37 [ + + ]: 8 : if(options.issuance.authorizedBurnWithoutApproval != issuance_.authorizedBurnWithoutApproval ){
+ 38 : 4 : options.issuance.authorizedBurnWithoutApproval = issuance_.authorizedBurnWithoutApproval;
+ 39 : : }
+ 40 : : }
+ 41 : :
+ 42 : : /**
+ 43 : : * @notice set/unset the option to perform the transfer if the request is approved by the rule operator.
+ 44 : : * To perform the transfer, the token holder has to approve the rule to spend tokens on his behalf (standard ERC-20 approval).
+ 45 : : * If the allowance is not sufficient, the request will be approved, but without performing the transfer.
+ 46 : : */
+ 47 : : function setAutomaticTransfer(AUTOMATIC_TRANSFER calldata automaticTransfer_) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE){
+ 48 [ + + ]: 4 : if(automaticTransfer_.isActivate != options.automaticTransfer.isActivate){
+ 49 : 4 : options.automaticTransfer.isActivate = automaticTransfer_.isActivate;
+ 50 : : }
+ 51 : : // No need to put the cmtat to zero to deactivate automaticTransfer
+ 52 [ + + ]: 8 : if(address(automaticTransfer_.cmtat) != address(options.automaticTransfer.cmtat)){
+ 53 : 4 : options.automaticTransfer.cmtat = automaticTransfer_.cmtat;
+ 54 : : }
+ 55 : : }
+ 56 : :
+ 57 : : /**
+ 58 : : * @notice set time limit for new requests (Approval and transfer)
+ 59 : : * timeLimitToApprove: time limit for an operator to approve a request
+ 60 : : * timeLimitToTransfer: once a request is approved, time limit for the token holder to perform the transfer
+ 61 : : */
+ 62 : : function setTimeLimit(TIME_LIMIT memory timeLimit_) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE){
+ 63 [ + + ]: 6 : if(options.timeLimit.timeLimitToApprove != timeLimit_.timeLimitToApprove){
+ 64 : 6 : options.timeLimit.timeLimitToApprove = timeLimit_.timeLimitToApprove;
+ 65 : : }
+ 66 [ + + ]: 6 : if(options.timeLimit.timeLimitToTransfer != timeLimit_.timeLimitToTransfer){
+ 67 : 6 : options.timeLimit.timeLimitToTransfer = timeLimit_.timeLimitToTransfer;
+ 68 : : }
+ 69 : : }
+ 70 : : /**
+ 71 : : * @notice If the transfer is not approved or denied within {timeLimitBeforeAutomaticApproval},
+ 72 : : * the request is considered as approved during a transfer.
+ 73 : : *
+ 74 : : */
+ 75 : : function setAutomaticApproval(AUTOMATIC_APPROVAL memory automaticApproval_) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE){
+ 76 [ + + ]: 8 : if(options.automaticApproval.isActivate != automaticApproval_.isActivate ){
+ 77 : 8 : options.automaticApproval.isActivate = automaticApproval_.isActivate;
+ 78 : : }
+ 79 [ + + ]: 8 : if(options.automaticApproval.timeLimitBeforeAutomaticApproval != automaticApproval_.timeLimitBeforeAutomaticApproval){
+ 80 : 8 : options.automaticApproval.timeLimitBeforeAutomaticApproval = automaticApproval_.timeLimitBeforeAutomaticApproval;
+ 81 : : }
+ 82 : : }
+ 83 : :
+ 84 : : /**
+ 85 : : * @notice create a transfer request directly approved
+ 86 : : */
+ 87 : : function createTransferRequestWithApproval(
+ 88 : : TransferRequestKeyElement calldata keyElement
+ 89 : : ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE){
+ 90 : 10 : _createTransferRequestWithApproval(keyElement);
+ 91 : : }
+ 92 : :
+ 93 : : /**
+ 94 : : @notice approve a transferRequest
+ 95 : : @param keyElement contains from, to, value
+ 96 : : @param partialValue amount approved. Put 0 if all the amount specified by value is approved.
+ 97 : : @param isApproved approved (true) or refused (false). Put true if you use partialApproval
+ 98 : : */
+ 99 : : function approveTransferRequest(
+ 100 : : TransferRequestKeyElement calldata keyElement, uint256 partialValue, bool isApproved
+ 101 : : ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE) {
+ 102 : 64 : _approveTransferRequestKeyElement(keyElement, partialValue, isApproved);
+ 103 : : }
+ 104 : :
+ 105 : : /**
+ 106 : : * @notice approve a transferRequestby using its id
+ 107 : : */
+ 108 : : function approveTransferRequestWithId(
+ 109 : : uint256 requestId_, bool isApproved
110 : : ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE){
- 111 [ + + ]: 10 : if(requestId_.length == 0){
- 112 : 2 : revert RuleConditionalTransfer_EmptyArray();
+ 111 [ + + ]: 12 : if(requestId_ + 1 > requestId) {
+ 112 : 4 : revert RuleConditionalTransfer_InvalidId();
113 : : }
- 114 [ + + ]: 8 : if(requestId_.length != isApproved_.length){
- 115 : 2 : revert RuleConditionalTransfer_InvalidLengthArray();
- 116 : : }
- 117 : : // Check id validity before performing actions
- 118 : 29 : for(uint256 i = 0; i < requestId_.length; ++i){
- 119 [ + + ]: 33 : if(requestId_[i] + 1 > requestId) {
- 120 : 2 : revert RuleConditionalTransfer_InvalidId();
- 121 : : }
- 122 : : }
- 123 : 14 : for(uint256 i = 0; i < requestId_.length; ++i){
- 124 : 10 : TransferRequest memory transferRequest = transferRequests[IdToKey[requestId_[i]]];
- 125 : 10 : _approveRequest(transferRequest, isApproved_[i]);
+ 114 : 4 : TransferRequest memory transferRequest = transferRequests[IdToKey[requestId_]];
+ 115 : 4 : _approveRequest(transferRequest, isApproved);
+ 116 : : }
+ 117 : :
+ 118 : : /**
+ 119 : : * @notice reset to None the status of a request
+ 120 : : */
+ 121 : : function resetRequestStatus(
+ 122 : : uint256 requestId_
+ 123 : : ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE){
+ 124 [ + + ]: 6 : if(requestId_ + 1 > requestId) {
+ 125 : 2 : revert RuleConditionalTransfer_InvalidId();
126 : : }
- 127 : : }
- 128 : :
- 129 : :
- 130 : : function approveTransferRequestBatch(
- 131 : : TransferRequestKeyElement[] calldata keyElements, uint256[] calldata partialValues, bool[] calldata isApproved_
- 132 : : ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE) {
- 133 [ + + ]: 12 : if(keyElements.length == 0){
- 134 : 2 : revert RuleConditionalTransfer_EmptyArray();
- 135 : : }
- 136 [ + + ]: 10 : if((keyElements.length != partialValues.length) || (partialValues.length != isApproved_.length)){
- 137 : 6 : revert RuleConditionalTransfer_InvalidLengthArray();
- 138 : : }
- 139 : 24 : for(uint256 i = 0; i < keyElements.length; ++i){
- 140 : 18 : _approveTransferRequestKeyElement(keyElements[i], partialValues[i], isApproved_[i]);
- 141 : : }
- 142 : : }
- 143 : :
- 144 : :
- 145 : : function createTransferRequestWithApprovalBatch(
- 146 : : TransferRequestKeyElement[] calldata keyElements
- 147 : : ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE){
- 148 [ + + ]: 4 : if(keyElements.length == 0){
- 149 : 2 : revert RuleConditionalTransfer_EmptyArray();
- 150 : : }
- 151 : 11 : for(uint256 i = 0; i < keyElements.length; ++i){
- 152 : 8 : _createTransferRequestWithApproval(keyElements[i]);
+ 127 : 2 : bytes32 key = IdToKey[requestId_];
+ 128 : 2 : _resetRequestStatus(key);
+ 129 : : }
+ 130 : :
+ 131 : : /***** Batch function */
+ 132 : : /**
+ 133 : : * @notice Batch version of {approveTransferRequestWithId}
+ 134 : : */
+ 135 : : function approveTransferRequestBatchWithId(
+ 136 : : uint256[] calldata requestId_, bool[] calldata isApproved
+ 137 : : ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE){
+ 138 [ + + ]: 10 : if(requestId_.length == 0){
+ 139 : 2 : revert RuleConditionalTransfer_EmptyArray();
+ 140 : : }
+ 141 [ + + ]: 8 : if(requestId_.length != isApproved.length){
+ 142 : 2 : revert RuleConditionalTransfer_InvalidLengthArray();
+ 143 : : }
+ 144 : : // Check id validity before performing actions
+ 145 : 29 : for(uint256 i = 0; i < requestId_.length; ++i){
+ 146 [ + + ]: 33 : if(requestId_[i] + 1 > requestId) {
+ 147 : 2 : revert RuleConditionalTransfer_InvalidId();
+ 148 : : }
+ 149 : : }
+ 150 : 14 : for(uint256 i = 0; i < requestId_.length; ++i){
+ 151 : 10 : TransferRequest memory transferRequest = transferRequests[IdToKey[requestId_[i]]];
+ 152 : 10 : _approveRequest(transferRequest, isApproved[i]);
153 : : }
154 : : }
155 : :
- 156 : :
- 157 : : function resetRequestStatusBatch(
- 158 : : uint256[] memory requestIds
- 159 : : ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE){
- 160 [ + + ]: 6 : if(requestIds.length == 0){
- 161 : 2 : revert RuleConditionalTransfer_EmptyArray();
- 162 : : }
- 163 : : // Check id validity before performing actions
- 164 : 12 : for(uint256 i = 0; i < requestIds.length; ++i){
- 165 [ + + ]: 12 : if(requestIds[i] + 1 > requestId) {
- 166 : 2 : revert RuleConditionalTransfer_InvalidId();
- 167 : : }
- 168 : : }
- 169 : 9 : for(uint256 i = 0; i < requestIds.length; ++i){
- 170 : 6 : bytes32 key = IdToKey[requestIds[i]];
- 171 : 6 : _resetRequestStatus(key);
- 172 : : }
- 173 : : }
- 174 : :
- 175 : :
- 176 : : /*** Internal functions ****/
- 177 : :
- 178 : : function _approveTransferRequestKeyElement(
- 179 : : TransferRequestKeyElement calldata keyElement, uint256 partialValue, bool isApproved_
- 180 : : ) internal {
- 181 [ + + ]: 68 : if(partialValue > keyElement.value){
- 182 : 2 : revert RuleConditionalTransfer_InvalidValueApproved();
- 183 : : }
- 184 : 99 : bytes32 key = keccak256(abi.encode(keyElement.from, keyElement.to, keyElement.value));
- 185 : 66 : TransferRequest memory transferRequest = transferRequests[key];
- 186 [ + + ]: 66 : if(partialValue > 0 ){
- 187 [ + + ]: 10 : if(! isApproved_){
- 188 : 2 : revert RuleConditionalTransfer_CannotDeniedPartially();
- 189 : : }
- 190 : : // Denied the first request
- 191 : 8 : _approveRequest(transferRequest, false);
- 192 : : // Create new request
- 193 : 8 : _createTransferRequestWithApproval(TransferRequestKeyElement({from: keyElement.from, to: keyElement.to, value: partialValue}));
- 194 : : }else{
- 195 : 56 : _approveRequest(transferRequest, isApproved_);
- 196 : : }
- 197 : : }
- 198 : :
- 199 : : function _createTransferRequestWithApproval(
- 200 : : TransferRequestKeyElement memory keyElement
- 201 : : ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE){
- 202 : : // WAIT => Will overwrite
- 203 : : // APPROVED => will overwrite previous status with a new delay
- 204 : : // DENIED => will overwrite
- 205 : 39 : bytes32 key = keccak256(abi.encode(keyElement.from, keyElement.to, keyElement.value));
- 206 : : // Status NONE not enough because reset is possible
- 207 [ # + ]: 26 : if(_checkRequestStatus(key)){
- 208 : 36 : TransferRequest memory newTransferApproval = TransferRequest({
- 209 : : key: key,
- 210 : : id: requestId,
- 211 : : from: keyElement.from,
- 212 : : to: keyElement.to,
- 213 : : value: keyElement.value,
- 214 : : askTime:0,
- 215 : : maxTime : block.timestamp + options.timeLimit.timeLimitToTransfer,
- 216 : : status:STATUS.APPROVED
- 217 : : });
- 218 : 24 : transferRequests[key] = newTransferApproval;
- 219 : 24 : IdToKey[requestId] = key;
- 220 : 24 : emit transferApproved(key, keyElement.from, keyElement.to, keyElement.value, requestId);
- 221 : 24 : ++requestId;
- 222 : : } else {
- 223 : : // Overwrite previous approval
- 224 : 2 : transferRequests[key].maxTime = block.timestamp + options.timeLimit.timeLimitToTransfer;
- 225 : 2 : transferRequests[key].status = STATUS.APPROVED;
- 226 : 2 : emit transferApproved(key, keyElement.from, keyElement.to, keyElement.value, transferRequests[key].id);
- 227 : : }
- 228 : : }
- 229 : :
- 230 : : function _resetRequestStatus(
- 231 : : bytes32 key
- 232 : : ) internal {
- 233 : 18 : transferRequests[key].status = STATUS.NONE;
- 234 : 18 : emit transferReset(key, transferRequests[key].from, transferRequests[key].to, transferRequests[key].value, transferRequests[key].id );
- 235 : : }
- 236 : :
- 237 : : function _checkRequestStatus(bytes32 key) internal view returns(bool) {
- 238 : 318 : return (transferRequests[key].status == STATUS.NONE) && (transferRequests[key].key == 0x0);
- 239 : : }
- 240 : :
- 241 : : function _approveRequest(TransferRequest memory transferRequest , bool isApproved_) internal{
- 242 : : // status
- 243 [ + + ]: 78 : if(transferRequest.status != STATUS.WAIT){
- 244 : 2 : revert RuleConditionalTransfer_Wrong_Status();
- 245 : : }
- 246 [ + + ]: 38 : if(isApproved_){
- 247 : : // Time
- 248 [ + + ]: 44 : if(block.timestamp > (transferRequest.askTime + options.timeLimit.timeLimitToApprove)){
- 249 : 6 : revert RuleConditionalTransfer_timeExceeded();
- 250 : : }
- 251 : : // Set status
- 252 : 38 : transferRequests[transferRequest.key].status = STATUS.APPROVED;
- 253 : : // Set max time
- 254 : 38 : transferRequests[transferRequest.key].maxTime = block.timestamp + options.timeLimit.timeLimitToTransfer;
- 255 : 38 : emit transferApproved(transferRequest.key, transferRequest.from, transferRequest.to, transferRequest.value, transferRequests[transferRequest.key].id );
- 256 [ + + ]: 41 : if(options.automaticTransfer.isActivate && address(options.automaticTransfer.cmtat) != address(0)){
- 257 : : // Transfer with approval
- 258 : : // External call
- 259 [ + + ]: 3 : if(options.automaticTransfer.cmtat.allowance(transferRequest.from, address(this)) >= transferRequest.value){
- 260 : : //_updateProcessedTransfer(transferRequest.key);
- 261 : : // Will call the ruleEngine and the rule again...
- 262 : 2 : options.automaticTransfer.cmtat.safeTransferFrom(transferRequest.from, transferRequest.to, transferRequest.value);
- 263 : : }
- 264 : : }
- 265 : : } else {
- 266 : 32 : transferRequests[transferRequest.key].status = STATUS.DENIED;
- 267 : 32 : emit transferDenied(transferRequest.key, transferRequest.from, transferRequest.to, transferRequest.value, transferRequests[transferRequest.key].id );
- 268 : : }
- 269 : : }
- 270 : :
- 271 : : function _updateProcessedTransfer(bytes32 key) internal {
- 272 : : // Reset to zero
- 273 : 10 : transferRequests[key].maxTime = 0;
- 274 : 10 : transferRequests[key].askTime = 0;
- 275 : : // Change status
- 276 : 10 : transferRequests[key].status = STATUS.EXECUTED;
- 277 : : // Emit event
- 278 : 10 : emit transferProcessed(key, transferRequests[key].from, transferRequests[key].to, transferRequests[key].value, transferRequests[key].id);
- 279 : : }
- 280 : : }
+ 156 : : /**
+ 157 : : * @notice Batch version of {approveTransferRequest}
+ 158 : : */
+ 159 : : function approveTransferRequestBatch(
+ 160 : : TransferRequestKeyElement[] calldata keyElements, uint256[] calldata partialValues, bool[] calldata isApproved
+ 161 : : ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE) {
+ 162 [ + + ]: 12 : if(keyElements.length == 0){
+ 163 : 2 : revert RuleConditionalTransfer_EmptyArray();
+ 164 : : }
+ 165 [ + + ]: 10 : if((keyElements.length != partialValues.length) || (partialValues.length != isApproved.length)){
+ 166 : 6 : revert RuleConditionalTransfer_InvalidLengthArray();
+ 167 : : }
+ 168 : 24 : for(uint256 i = 0; i < keyElements.length; ++i){
+ 169 : 18 : _approveTransferRequestKeyElement(keyElements[i], partialValues[i], isApproved[i]);
+ 170 : : }
+ 171 : : }
+ 172 : :
+ 173 : : /**
+ 174 : : * @notice Batch version of {createTransferRequestWithApproval}
+ 175 : : */
+ 176 : : function createTransferRequestWithApprovalBatch(
+ 177 : : TransferRequestKeyElement[] calldata keyElements
+ 178 : : ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE){
+ 179 [ + + ]: 4 : if(keyElements.length == 0){
+ 180 : 2 : revert RuleConditionalTransfer_EmptyArray();
+ 181 : : }
+ 182 : 11 : for(uint256 i = 0; i < keyElements.length; ++i){
+ 183 : 8 : _createTransferRequestWithApproval(keyElements[i]);
+ 184 : : }
+ 185 : : }
+ 186 : :
+ 187 : : /**
+ 188 : : * @notice Batch version of {resetRequestStatus}
+ 189 : : */
+ 190 : : function resetRequestStatusBatch(
+ 191 : : uint256[] memory requestIds
+ 192 : : ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE){
+ 193 [ + + ]: 6 : if(requestIds.length == 0){
+ 194 : 2 : revert RuleConditionalTransfer_EmptyArray();
+ 195 : : }
+ 196 : : // Check id validity before performing actions
+ 197 : 12 : for(uint256 i = 0; i < requestIds.length; ++i){
+ 198 [ + + ]: 12 : if(requestIds[i] + 1 > requestId) {
+ 199 : 2 : revert RuleConditionalTransfer_InvalidId();
+ 200 : : }
+ 201 : : }
+ 202 : 9 : for(uint256 i = 0; i < requestIds.length; ++i){
+ 203 : 6 : bytes32 key = IdToKey[requestIds[i]];
+ 204 : 6 : _resetRequestStatus(key);
+ 205 : : }
+ 206 : : }
+ 207 : :
+ 208 : :
+ 209 : : /*** Internal functions ****/
+ 210 : : function _approveTransferRequestKeyElement(
+ 211 : : TransferRequestKeyElement calldata keyElement, uint256 partialValue, bool isApproved
+ 212 : : ) internal {
+ 213 [ + + ]: 82 : if(partialValue > keyElement.value){
+ 214 : 2 : revert RuleConditionalTransfer_InvalidValueApproved();
+ 215 : : }
+ 216 : 120 : bytes32 key = keccak256(abi.encode(keyElement.from, keyElement.to, keyElement.value));
+ 217 : 80 : TransferRequest memory transferRequest = transferRequests[key];
+ 218 [ + + ]: 80 : if(partialValue > 0 ){
+ 219 [ + + ]: 14 : if(! isApproved){
+ 220 : 2 : revert RuleConditionalTransfer_CannotDeniedPartially();
+ 221 : : }
+ 222 : : // Denied the first request
+ 223 : 12 : _approveRequest(transferRequest, false);
+ 224 : : // Create new request
+ 225 : 12 : _createTransferRequestWithApproval(TransferRequestKeyElement({from: keyElement.from, to: keyElement.to, value: partialValue}));
+ 226 : : }else{
+ 227 : 66 : _approveRequest(transferRequest, isApproved);
+ 228 : : }
+ 229 : : }
+ 230 : :
+ 231 : : function _createTransferRequestWithApproval(
+ 232 : : TransferRequestKeyElement memory keyElement
+ 233 : : ) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE){
+ 234 : : // WAIT => Will overwrite
+ 235 : : // APPROVED => will overwrite previous status with a new delay
+ 236 : : // DENIED => will overwrite
+ 237 : 45 : bytes32 key = keccak256(abi.encode(keyElement.from, keyElement.to, keyElement.value));
+ 238 [ # + ]: 30 : if(_checkRequestStatus(key)){
+ 239 : 42 : TransferRequest memory newTransferApproval = TransferRequest({
+ 240 : : key: key,
+ 241 : : id: requestId,
+ 242 : : from: keyElement.from,
+ 243 : : to: keyElement.to,
+ 244 : : value: keyElement.value,
+ 245 : : askTime:0,
+ 246 : : maxTime : block.timestamp + options.timeLimit.timeLimitToTransfer,
+ 247 : : status:STATUS.APPROVED
+ 248 : : });
+ 249 : 28 : transferRequests[key] = newTransferApproval;
+ 250 : 28 : IdToKey[requestId] = key;
+ 251 : 28 : emit transferApproved(key, keyElement.from, keyElement.to, keyElement.value, requestId);
+ 252 : 28 : ++requestId;
+ 253 : : } else {
+ 254 : : // Overwrite previous approval
+ 255 : 2 : transferRequests[key].maxTime = block.timestamp + options.timeLimit.timeLimitToTransfer;
+ 256 : 2 : transferRequests[key].status = STATUS.APPROVED;
+ 257 : 2 : emit transferApproved(key, keyElement.from, keyElement.to, keyElement.value, transferRequests[key].id);
+ 258 : : }
+ 259 : : }
+ 260 : :
+ 261 : : function _resetRequestStatus(
+ 262 : : bytes32 key
+ 263 : : ) internal {
+ 264 : 20 : transferRequests[key].status = STATUS.NONE;
+ 265 : 20 : emit transferReset(key, transferRequests[key].from, transferRequests[key].to, transferRequests[key].value, transferRequests[key].id );
+ 266 : : }
+ 267 : :
+ 268 : : function _checkRequestStatus(bytes32 key) internal view returns(bool) {
+ 269 : : // Status NONE not enough because reset is possible
+ 270 : 357 : return (transferRequests[key].status == STATUS.NONE) && (transferRequests[key].key == 0x0);
+ 271 : : }
+ 272 : :
+ 273 : : function _approveRequest(TransferRequest memory transferRequest , bool isApproved) internal{
+ 274 : : // status
+ 275 [ + + ]: 92 : if(transferRequest.status != STATUS.WAIT){
+ 276 : 2 : revert RuleConditionalTransfer_Wrong_Status();
+ 277 : : }
+ 278 [ + + ]: 45 : if(isApproved){
+ 279 : : // Time
+ 280 [ + + ]: 54 : if(block.timestamp > (transferRequest.askTime + options.timeLimit.timeLimitToApprove)){
+ 281 : 6 : revert RuleConditionalTransfer_timeExceeded();
+ 282 : : }
+ 283 : : // Set status
+ 284 : 48 : transferRequests[transferRequest.key].status = STATUS.APPROVED;
+ 285 : : // Set max time
+ 286 : 48 : transferRequests[transferRequest.key].maxTime = block.timestamp + options.timeLimit.timeLimitToTransfer;
+ 287 : 48 : emit transferApproved(transferRequest.key, transferRequest.from, transferRequest.to, transferRequest.value, transferRequests[transferRequest.key].id );
+ 288 [ + + ]: 54 : if(options.automaticTransfer.isActivate && address(options.automaticTransfer.cmtat) != address(0)){
+ 289 : : // Transfer with approval
+ 290 : : // External call
+ 291 [ + + ]: 6 : if(options.automaticTransfer.cmtat.allowance(transferRequest.from, address(this)) >= transferRequest.value){
+ 292 : : // Will call the ruleEngine and the rule again...
+ 293 : 4 : options.automaticTransfer.cmtat.safeTransferFrom(transferRequest.from, transferRequest.to, transferRequest.value);
+ 294 : : }
+ 295 : : }
+ 296 : : } else {
+ 297 : 36 : transferRequests[transferRequest.key].status = STATUS.DENIED;
+ 298 : 36 : emit transferDenied(transferRequest.key, transferRequest.from, transferRequest.to, transferRequest.value, transferRequests[transferRequest.key].id );
+ 299 : : }
+ 300 : : }
+ 301 : :
+ 302 : : /**
+ 303 : : * @notice update the request during a transfer
+ 304 : : */
+ 305 : : function _updateProcessedTransfer(bytes32 key) internal {
+ 306 : : // Reset to zero
+ 307 : 20 : transferRequests[key].maxTime = 0;
+ 308 : 20 : transferRequests[key].askTime = 0;
+ 309 : : // Change status
+ 310 : 20 : transferRequests[key].status = STATUS.EXECUTED;
+ 311 : : // Emit event
+ 312 : 20 : emit transferProcessed(key, transferRequests[key].from, transferRequests[key].to, transferRequests[key].value, transferRequests[key].id);
+ 313 : : }
+ 314 : : }
diff --git a/doc/test/coverage/src/rules/operation/abstract/index-sort-b.html b/doc/test/coverage/src/rules/operation/abstract/index-sort-b.html
index 5ba2b4f..ceeab30 100644
--- a/doc/test/coverage/src/rules/operation/abstract/index-sort-b.html
+++ b/doc/test/coverage/src/rules/operation/abstract/index-sort-b.html
@@ -31,18 +31,18 @@
|
-
-
+
+
-
+
|
-
-
+
+
|
@@ -87,9 +87,9 @@
100.0 % |
- 94 / 94 |
- 94.4 % |
- 17 / 18 |
+ 96 / 96 |
+ 94.7 % |
+ 18 / 19 |
98.1 % |
53 / 54 |
diff --git a/doc/test/coverage/src/rules/operation/abstract/index-sort-f.html b/doc/test/coverage/src/rules/operation/abstract/index-sort-f.html
index 8bfc934..8096c28 100644
--- a/doc/test/coverage/src/rules/operation/abstract/index-sort-f.html
+++ b/doc/test/coverage/src/rules/operation/abstract/index-sort-f.html
@@ -31,18 +31,18 @@
|
-
-
+
+
-
+
|
-
-
+
+
|
@@ -87,9 +87,9 @@
100.0 % |
- 94 / 94 |
- 94.4 % |
- 17 / 18 |
+ 96 / 96 |
+ 94.7 % |
+ 18 / 19 |
98.1 % |
53 / 54 |
diff --git a/doc/test/coverage/src/rules/operation/abstract/index-sort-l.html b/doc/test/coverage/src/rules/operation/abstract/index-sort-l.html
index b1b2f31..e6d471d 100644
--- a/doc/test/coverage/src/rules/operation/abstract/index-sort-l.html
+++ b/doc/test/coverage/src/rules/operation/abstract/index-sort-l.html
@@ -31,18 +31,18 @@
|
-
-
+
+
-
+
|
-
-
+
+
|
@@ -87,9 +87,9 @@
100.0 % |
- 94 / 94 |
- 94.4 % |
- 17 / 18 |
+ 96 / 96 |
+ 94.7 % |
+ 18 / 19 |
98.1 % |
53 / 54 |
diff --git a/doc/test/coverage/src/rules/operation/abstract/index.html b/doc/test/coverage/src/rules/operation/abstract/index.html
index 2fe8a0d..1e6e812 100644
--- a/doc/test/coverage/src/rules/operation/abstract/index.html
+++ b/doc/test/coverage/src/rules/operation/abstract/index.html
@@ -31,18 +31,18 @@
|
-
-
+
+
-
+
|
-
-
+
+
|
@@ -87,9 +87,9 @@
100.0 % |
- 94 / 94 |
- 94.4 % |
- 17 / 18 |
+ 96 / 96 |
+ 94.7 % |
+ 18 / 19 |
98.1 % |
53 / 54 |
diff --git a/doc/test/coverage/src/rules/operation/index-sort-b.html b/doc/test/coverage/src/rules/operation/index-sort-b.html
index bcc11c2..d557abc 100644
--- a/doc/test/coverage/src/rules/operation/index-sort-b.html
+++ b/doc/test/coverage/src/rules/operation/index-sort-b.html
@@ -31,13 +31,13 @@
|
-
-
-
+
+
+
-
+
|
@@ -49,9 +49,9 @@
|
|
-
-
-
+
+
+
|
@@ -84,14 +84,14 @@
RuleConditionalTransfer.sol |
-
+
|
- 98.7 % |
- 78 / 79 |
+ 98.8 % |
+ 84 / 85 |
93.8 % |
15 / 16 |
- 94.1 % |
- 32 / 34 |
+ 90.5 % |
+ 38 / 42 |
diff --git a/doc/test/coverage/src/rules/operation/index-sort-f.html b/doc/test/coverage/src/rules/operation/index-sort-f.html
index dd060b7..412cd56 100644
--- a/doc/test/coverage/src/rules/operation/index-sort-f.html
+++ b/doc/test/coverage/src/rules/operation/index-sort-f.html
@@ -31,13 +31,13 @@
|
-
-
-
+
+
+
-
+
|
@@ -49,9 +49,9 @@
|
|
-
-
-
+
+
+
|
@@ -84,14 +84,14 @@
RuleConditionalTransfer.sol |
-
+
|
- 98.7 % |
- 78 / 79 |
+ 98.8 % |
+ 84 / 85 |
93.8 % |
15 / 16 |
- 94.1 % |
- 32 / 34 |
+ 90.5 % |
+ 38 / 42 |
diff --git a/doc/test/coverage/src/rules/operation/index-sort-l.html b/doc/test/coverage/src/rules/operation/index-sort-l.html
index 83181d3..af166d2 100644
--- a/doc/test/coverage/src/rules/operation/index-sort-l.html
+++ b/doc/test/coverage/src/rules/operation/index-sort-l.html
@@ -31,13 +31,13 @@
|
-
-
-
+
+
+
-
+
|
@@ -49,9 +49,9 @@
|
|
-
-
-
+
+
+
|
@@ -84,14 +84,14 @@
RuleConditionalTransfer.sol |
-
+
|
- 98.7 % |
- 78 / 79 |
+ 98.8 % |
+ 84 / 85 |
93.8 % |
15 / 16 |
- 94.1 % |
- 32 / 34 |
+ 90.5 % |
+ 38 / 42 |
diff --git a/doc/test/coverage/src/rules/operation/index.html b/doc/test/coverage/src/rules/operation/index.html
index ae0bbcb..2ae074f 100644
--- a/doc/test/coverage/src/rules/operation/index.html
+++ b/doc/test/coverage/src/rules/operation/index.html
@@ -31,13 +31,13 @@
|
-
-
-
+
+
+
-
+
|
@@ -49,9 +49,9 @@
|
|
-
-
-
+
+
+
|
@@ -84,14 +84,14 @@
RuleConditionalTransfer.sol |
-
+
|
- 98.7 % |
- 78 / 79 |
+ 98.8 % |
+ 84 / 85 |
93.8 % |
15 / 16 |
- 94.1 % |
- 32 / 34 |
+ 90.5 % |
+ 38 / 42 |
diff --git a/doc/test/coverage/src/rules/validation/RuleBlacklist.sol.func-sort-c.html b/doc/test/coverage/src/rules/validation/RuleBlacklist.sol.func-sort-c.html
index 0b60d76..d6b2d99 100644
--- a/doc/test/coverage/src/rules/validation/RuleBlacklist.sol.func-sort-c.html
+++ b/doc/test/coverage/src/rules/validation/RuleBlacklist.sol.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/doc/test/coverage/src/rules/validation/RuleBlacklist.sol.func.html b/doc/test/coverage/src/rules/validation/RuleBlacklist.sol.func.html
index 33fcc3e..b63e470 100644
--- a/doc/test/coverage/src/rules/validation/RuleBlacklist.sol.func.html
+++ b/doc/test/coverage/src/rules/validation/RuleBlacklist.sol.func.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/doc/test/coverage/src/rules/validation/RuleBlacklist.sol.gcov.html b/doc/test/coverage/src/rules/validation/RuleBlacklist.sol.gcov.html
index 4cbb535..8f51703 100644
--- a/doc/test/coverage/src/rules/validation/RuleBlacklist.sol.gcov.html
+++ b/doc/test/coverage/src/rules/validation/RuleBlacklist.sol.gcov.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/doc/test/coverage/src/rules/validation/RuleSanctionList.sol.func-sort-c.html b/doc/test/coverage/src/rules/validation/RuleSanctionList.sol.func-sort-c.html
index d8b841d..03e72d5 100644
--- a/doc/test/coverage/src/rules/validation/RuleSanctionList.sol.func-sort-c.html
+++ b/doc/test/coverage/src/rules/validation/RuleSanctionList.sol.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/doc/test/coverage/src/rules/validation/RuleSanctionList.sol.func.html b/doc/test/coverage/src/rules/validation/RuleSanctionList.sol.func.html
index 34d35df..0dfd668 100644
--- a/doc/test/coverage/src/rules/validation/RuleSanctionList.sol.func.html
+++ b/doc/test/coverage/src/rules/validation/RuleSanctionList.sol.func.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/doc/test/coverage/src/rules/validation/RuleSanctionList.sol.gcov.html b/doc/test/coverage/src/rules/validation/RuleSanctionList.sol.gcov.html
index 707a87b..a629c51 100644
--- a/doc/test/coverage/src/rules/validation/RuleSanctionList.sol.gcov.html
+++ b/doc/test/coverage/src/rules/validation/RuleSanctionList.sol.gcov.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/doc/test/coverage/src/rules/validation/RuleWhitelist.sol.func-sort-c.html b/doc/test/coverage/src/rules/validation/RuleWhitelist.sol.func-sort-c.html
index 1123b81..625c644 100644
--- a/doc/test/coverage/src/rules/validation/RuleWhitelist.sol.func-sort-c.html
+++ b/doc/test/coverage/src/rules/validation/RuleWhitelist.sol.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/doc/test/coverage/src/rules/validation/RuleWhitelist.sol.func.html b/doc/test/coverage/src/rules/validation/RuleWhitelist.sol.func.html
index 21066ab..0b98954 100644
--- a/doc/test/coverage/src/rules/validation/RuleWhitelist.sol.func.html
+++ b/doc/test/coverage/src/rules/validation/RuleWhitelist.sol.func.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/doc/test/coverage/src/rules/validation/RuleWhitelist.sol.gcov.html b/doc/test/coverage/src/rules/validation/RuleWhitelist.sol.gcov.html
index 0380e6e..158f5d7 100644
--- a/doc/test/coverage/src/rules/validation/RuleWhitelist.sol.gcov.html
+++ b/doc/test/coverage/src/rules/validation/RuleWhitelist.sol.gcov.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol.func-sort-c.html b/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol.func-sort-c.html
index 3a1b62b..7380e8e 100644
--- a/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol.func-sort-c.html
+++ b/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
@@ -90,19 +90,19 @@
RuleAddressList.addAddressToTheList |
- 28 |
-
-
- RuleAddressList.addressIsListed |
- 57 |
+ 40 |
RuleAddressList._contextSuffixLength |
- 60 |
+ 72 |
RuleAddressList._msgSender |
- 60 |
+ 72 |
+
+
+ RuleAddressList.addressIsListed |
+ 83 |
diff --git a/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol.func.html b/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol.func.html
index 7688e84..0905f5b 100644
--- a/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol.func.html
+++ b/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol.func.html
@@ -37,7 +37,7 @@
-
+
|
@@ -70,7 +70,7 @@
RuleAddressList._contextSuffixLength |
- 60 |
+ 72 |
RuleAddressList._msgData |
@@ -78,11 +78,11 @@
RuleAddressList._msgSender |
- 60 |
+ 72 |
RuleAddressList.addAddressToTheList |
- 28 |
+ 40 |
RuleAddressList.addAddressesToTheList |
@@ -90,7 +90,7 @@
RuleAddressList.addressIsListed |
- 57 |
+ 83 |
RuleAddressList.numberListedAddress |
diff --git a/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol.gcov.html b/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol.gcov.html
index 8c4f707..ae31a25 100644
--- a/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol.gcov.html
+++ b/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressList.sol.gcov.html
@@ -37,7 +37,7 @@
-
+
|
@@ -133,7 +133,7 @@
62 : : function addAddressToTheList(
63 : : address _newWhitelistAddress
64 : : ) public onlyRole(ADDRESS_LIST_ROLE) {
- 65 : 54 : _addAddressToThelist(_newWhitelistAddress);
+ 65 : 78 : _addAddressToThelist(_newWhitelistAddress);
66 : : }
67 : :
68 : : /**
@@ -167,7 +167,7 @@
96 : : function addressIsListed(
97 : : address _targetAddress
98 : : ) public view returns (bool) {
- 99 : 345 : return _addressIsListed(_targetAddress);
+ 99 : 423 : return _addressIsListed(_targetAddress);
100 : : }
101 : :
102 : :
@@ -180,7 +180,7 @@
109 : : override(ERC2771Context, Context)
110 : : returns (address sender)
111 : : {
- 112 : 180 : return ERC2771Context._msgSender();
+ 112 : 216 : return ERC2771Context._msgSender();
113 : : }
114 : :
115 : : /**
@@ -199,7 +199,7 @@
128 : : * @dev This surcharge is not necessary if you do not use the MetaTxModule
129 : : */
130 : : function _contextSuffixLength() internal view override(ERC2771Context, Context) returns (uint256) {
- 131 : 180 : return ERC2771Context._contextSuffixLength();
+ 131 : 216 : return ERC2771Context._contextSuffixLength();
132 : : }
133 : : }
diff --git a/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol.func-sort-c.html b/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol.func-sort-c.html
index 9ad25a7..511dbce 100644
--- a/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol.func-sort-c.html
+++ b/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
@@ -86,11 +86,11 @@
RuleAddressListInternal._addAddressToThelist |
- 27 |
+ 39 |
RuleAddressListInternal._addressIsListed |
- 115 |
+ 141 |
diff --git a/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol.func.html b/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol.func.html
index a964c88..66d10d6 100644
--- a/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol.func.html
+++ b/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol.func.html
@@ -37,7 +37,7 @@
-
+
|
@@ -70,7 +70,7 @@
RuleAddressListInternal._addAddressToThelist |
- 27 |
+ 39 |
RuleAddressListInternal._addAddressesToThelist |
@@ -78,7 +78,7 @@
RuleAddressListInternal._addressIsListed |
- 115 |
+ 141 |
RuleAddressListInternal._numberListedAddress |
diff --git a/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol.gcov.html b/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol.gcov.html
index 99e1724..5e74800 100644
--- a/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol.gcov.html
+++ b/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/RuleAddressListInternal.sol.gcov.html
@@ -37,7 +37,7 @@
-
+
|
@@ -131,12 +131,12 @@
60 : : function _addAddressToThelist(
61 : : address _newlistAddress
62 : : ) internal {
- 63 [ + + ]: 27 : if(list[_newlistAddress])
+ 63 [ + + ]: 39 : if(list[_newlistAddress])
64 : : {
65 : 2 : revert Rulelist_AddressAlreadylisted();
66 : : }
- 67 : 52 : list[_newlistAddress] = true;
- 68 : 52 : ++numAddressesList;
+ 67 : 76 : list[_newlistAddress] = true;
+ 68 : 76 : ++numAddressesList;
69 : : }
70 : :
71 : : /**
@@ -173,7 +173,7 @@
102 : : function _addressIsListed(
103 : : address _targetAddress
104 : : ) internal view returns (bool) {
- 105 : 230 : return list[_targetAddress];
+ 105 : 282 : return list[_targetAddress];
106 : : }
107 : : }
diff --git a/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/index-sort-b.html b/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/index-sort-b.html
index 7c0ccfa..2c18e01 100644
--- a/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/index-sort-b.html
+++ b/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/index-sort-b.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/index-sort-f.html b/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/index-sort-f.html
index a1b176a..3b3a30a 100644
--- a/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/index-sort-f.html
+++ b/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/index-sort-f.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/index-sort-l.html b/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/index-sort-l.html
index fd999fe..ab0cc0e 100644
--- a/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/index-sort-l.html
+++ b/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/index-sort-l.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/index.html b/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/index.html
index b53a392..1c40a15 100644
--- a/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/index.html
+++ b/doc/test/coverage/src/rules/validation/abstract/RuleAddressList/index.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/doc/test/coverage/src/rules/validation/abstract/RuleValidateTransfer.sol.func-sort-c.html b/doc/test/coverage/src/rules/validation/abstract/RuleValidateTransfer.sol.func-sort-c.html
index 7ac9ecf..4495caa 100644
--- a/doc/test/coverage/src/rules/validation/abstract/RuleValidateTransfer.sol.func-sort-c.html
+++ b/doc/test/coverage/src/rules/validation/abstract/RuleValidateTransfer.sol.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/doc/test/coverage/src/rules/validation/abstract/RuleValidateTransfer.sol.func.html b/doc/test/coverage/src/rules/validation/abstract/RuleValidateTransfer.sol.func.html
index 33499de..97372fa 100644
--- a/doc/test/coverage/src/rules/validation/abstract/RuleValidateTransfer.sol.func.html
+++ b/doc/test/coverage/src/rules/validation/abstract/RuleValidateTransfer.sol.func.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/doc/test/coverage/src/rules/validation/abstract/RuleValidateTransfer.sol.gcov.html b/doc/test/coverage/src/rules/validation/abstract/RuleValidateTransfer.sol.gcov.html
index a779a34..a4ed5c4 100644
--- a/doc/test/coverage/src/rules/validation/abstract/RuleValidateTransfer.sol.gcov.html
+++ b/doc/test/coverage/src/rules/validation/abstract/RuleValidateTransfer.sol.gcov.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/doc/test/coverage/src/rules/validation/abstract/index-sort-b.html b/doc/test/coverage/src/rules/validation/abstract/index-sort-b.html
index d9e93ed..760e987 100644
--- a/doc/test/coverage/src/rules/validation/abstract/index-sort-b.html
+++ b/doc/test/coverage/src/rules/validation/abstract/index-sort-b.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/doc/test/coverage/src/rules/validation/abstract/index-sort-f.html b/doc/test/coverage/src/rules/validation/abstract/index-sort-f.html
index 0564c85..f0ef7d6 100644
--- a/doc/test/coverage/src/rules/validation/abstract/index-sort-f.html
+++ b/doc/test/coverage/src/rules/validation/abstract/index-sort-f.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/doc/test/coverage/src/rules/validation/abstract/index-sort-l.html b/doc/test/coverage/src/rules/validation/abstract/index-sort-l.html
index 34e0d10..464156f 100644
--- a/doc/test/coverage/src/rules/validation/abstract/index-sort-l.html
+++ b/doc/test/coverage/src/rules/validation/abstract/index-sort-l.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/doc/test/coverage/src/rules/validation/abstract/index.html b/doc/test/coverage/src/rules/validation/abstract/index.html
index 43f9ffe..093d2c0 100644
--- a/doc/test/coverage/src/rules/validation/abstract/index.html
+++ b/doc/test/coverage/src/rules/validation/abstract/index.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/doc/test/coverage/src/rules/validation/index-sort-b.html b/doc/test/coverage/src/rules/validation/index-sort-b.html
index 877d72e..4fe50bf 100644
--- a/doc/test/coverage/src/rules/validation/index-sort-b.html
+++ b/doc/test/coverage/src/rules/validation/index-sort-b.html
@@ -37,7 +37,7 @@
-
+
|
@@ -82,7 +82,7 @@
Branches |
- RuleWhitelist.sol |
+ RuleBlacklist.sol |
|
@@ -94,7 +94,7 @@
8 / 8 |
- RuleBlacklist.sol |
+ RuleWhitelist.sol |
|
diff --git a/doc/test/coverage/src/rules/validation/index-sort-f.html b/doc/test/coverage/src/rules/validation/index-sort-f.html
index 424f9dd..946c249 100644
--- a/doc/test/coverage/src/rules/validation/index-sort-f.html
+++ b/doc/test/coverage/src/rules/validation/index-sort-f.html
@@ -37,7 +37,7 @@
-
+
|
@@ -94,7 +94,7 @@
10 / 10 |
- RuleWhitelist.sol |
+ RuleBlacklist.sol |
|
@@ -106,7 +106,7 @@
8 / 8 |
- RuleBlacklist.sol |
+ RuleWhitelist.sol |
|
diff --git a/doc/test/coverage/src/rules/validation/index-sort-l.html b/doc/test/coverage/src/rules/validation/index-sort-l.html
index 4baedd9..ca1eb77 100644
--- a/doc/test/coverage/src/rules/validation/index-sort-l.html
+++ b/doc/test/coverage/src/rules/validation/index-sort-l.html
@@ -37,7 +37,7 @@
-
+
|
@@ -94,7 +94,7 @@
10 / 10 |
- RuleWhitelist.sol |
+ RuleBlacklist.sol |
|
@@ -106,7 +106,7 @@
8 / 8 |
- RuleBlacklist.sol |
+ RuleWhitelist.sol |
|
diff --git a/doc/test/coverage/src/rules/validation/index.html b/doc/test/coverage/src/rules/validation/index.html
index 374f3ea..7799d57 100644
--- a/doc/test/coverage/src/rules/validation/index.html
+++ b/doc/test/coverage/src/rules/validation/index.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/doc/test/coverage/test/utils/SanctionListOracle.sol.func-sort-c.html b/doc/test/coverage/test/utils/SanctionListOracle.sol.func-sort-c.html
index 2e88446..70f8339 100644
--- a/doc/test/coverage/test/utils/SanctionListOracle.sol.func-sort-c.html
+++ b/doc/test/coverage/test/utils/SanctionListOracle.sol.func-sort-c.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/doc/test/coverage/test/utils/SanctionListOracle.sol.func.html b/doc/test/coverage/test/utils/SanctionListOracle.sol.func.html
index 4fedaf7..0928957 100644
--- a/doc/test/coverage/test/utils/SanctionListOracle.sol.func.html
+++ b/doc/test/coverage/test/utils/SanctionListOracle.sol.func.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/doc/test/coverage/test/utils/SanctionListOracle.sol.gcov.html b/doc/test/coverage/test/utils/SanctionListOracle.sol.gcov.html
index f1a8bb0..fb570e9 100644
--- a/doc/test/coverage/test/utils/SanctionListOracle.sol.gcov.html
+++ b/doc/test/coverage/test/utils/SanctionListOracle.sol.gcov.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/doc/test/coverage/test/utils/index-sort-b.html b/doc/test/coverage/test/utils/index-sort-b.html
index 7e7cf2c..252f067 100644
--- a/doc/test/coverage/test/utils/index-sort-b.html
+++ b/doc/test/coverage/test/utils/index-sort-b.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/doc/test/coverage/test/utils/index-sort-f.html b/doc/test/coverage/test/utils/index-sort-f.html
index 5fdec17..25b4893 100644
--- a/doc/test/coverage/test/utils/index-sort-f.html
+++ b/doc/test/coverage/test/utils/index-sort-f.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/doc/test/coverage/test/utils/index-sort-l.html b/doc/test/coverage/test/utils/index-sort-l.html
index 744f83f..2c71311 100644
--- a/doc/test/coverage/test/utils/index-sort-l.html
+++ b/doc/test/coverage/test/utils/index-sort-l.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/doc/test/coverage/test/utils/index.html b/doc/test/coverage/test/utils/index.html
index 7ab6a37..487e98c 100644
--- a/doc/test/coverage/test/utils/index.html
+++ b/doc/test/coverage/test/utils/index.html
@@ -37,7 +37,7 @@
-
+
|
diff --git a/doc/test/lcov.info b/doc/test/lcov.info
index d13b46a..0ce6817 100644
--- a/doc/test/lcov.info
+++ b/doc/test/lcov.info
@@ -160,31 +160,31 @@ DA:107,1
DA:110,6
DA:110,6
FN:116,RuleEngine.operateOnTransfer
-FNDA:26,RuleEngine.operateOnTransfer
-DA:118,25
-DA:118,25
+FNDA:45,RuleEngine.operateOnTransfer
+DA:118,44
+DA:118,44
BRDA:118,4,0,7
-BRDA:118,4,1,18
+BRDA:118,4,1,37
DA:119,7
DA:119,7
-DA:122,18
-DA:122,18
-DA:122,18
+DA:122,37
+DA:122,37
+DA:122,37
FN:128,RuleEngine._msgSender
-FNDA:203,RuleEngine._msgSender
-DA:134,203
-DA:134,203
-DA:134,203
+FNDA:244,RuleEngine._msgSender
+DA:134,244
+DA:134,244
+DA:134,244
FN:140,RuleEngine._msgData
FNDA:0,RuleEngine._msgData
DA:146,0
DA:146,0
DA:146,0
FN:152,RuleEngine._contextSuffixLength
-FNDA:203,RuleEngine._contextSuffixLength
-DA:153,203
-DA:153,203
-DA:153,203
+FNDA:244,RuleEngine._contextSuffixLength
+DA:153,244
+DA:153,244
+DA:153,244
FNF:7
FNH:6
LF:27
@@ -225,11 +225,11 @@ DA:51,17
DA:53,14
DA:53,14
FN:61,RuleEngineOperation.addRuleOperation
-FNDA:46,RuleEngineOperation.addRuleOperation
-DA:62,46
-DA:62,46
-DA:63,44
-DA:63,44
+FNDA:68,RuleEngineOperation.addRuleOperation
+DA:62,68
+DA:62,68
+DA:63,66
+DA:63,66
FN:76,RuleEngineOperation.removeRuleOperation
FNDA:5,RuleEngineOperation.removeRuleOperation
DA:80,5
@@ -258,24 +258,24 @@ FNDA:5,RuleEngineOperation.rulesOperation
DA:130,5
DA:130,5
FN:140,RuleEngineOperation._operateOnTransfer
-FNDA:18,RuleEngineOperation._operateOnTransfer
-DA:145,18
-DA:145,18
-DA:146,18
-DA:146,18
-DA:146,25
-DA:146,7
-DA:147,14
-DA:147,14
-DA:147,14
-DA:152,14
-DA:152,14
-BRDA:152,1,0,7
-BRDA:152,1,1,7
-DA:153,7
-DA:153,7
-DA:156,11
-DA:156,11
+FNDA:37,RuleEngineOperation._operateOnTransfer
+DA:145,37
+DA:145,37
+DA:146,37
+DA:146,37
+DA:146,53
+DA:146,16
+DA:147,33
+DA:147,33
+DA:147,33
+DA:152,33
+DA:152,33
+BRDA:152,1,0,17
+BRDA:152,1,1,16
+DA:153,17
+DA:153,17
+DA:156,20
+DA:156,20
FNF:11
FNH:11
LF:25
@@ -350,11 +350,11 @@ DA:133,5
DA:133,5
FN:143,RuleEngineValidation.detectTransferRestrictionValidation
FNDA:3,RuleEngineValidation.detectTransferRestrictionValidation
-DA:148,52
-DA:148,52
-DA:149,52
-DA:149,52
-DA:149,62
+DA:148,71
+DA:148,71
+DA:149,71
+DA:149,71
+DA:149,81
DA:149,10
DA:150,32
DA:150,32
@@ -365,16 +365,16 @@ BRDA:155,1,0,22
BRDA:155,1,1,10
DA:156,22
DA:156,22
-DA:160,30
-DA:160,30
-DA:160,30
+DA:160,49
+DA:160,49
+DA:160,49
FN:170,RuleEngineValidation.validateTransferValidation
FNDA:2,RuleEngineValidation.validateTransferValidation
-DA:175,27
-DA:175,27
-DA:175,27
-DA:175,27
-DA:175,27
+DA:175,46
+DA:175,46
+DA:175,46
+DA:175,46
+DA:175,46
FNF:12
FNH:12
LF:26
@@ -415,24 +415,24 @@ DA:34,44
DA:36,44
DA:36,44
FN:46,RuleInternal._addRule
-FNDA:112,RuleInternal._addRule
-DA:47,112
-DA:47,112
-DA:47,112
-DA:47,112
+FNDA:134,RuleInternal._addRule
+DA:47,134
+DA:47,134
+DA:47,134
+DA:47,134
BRDA:47,3,0,2
-BRDA:47,3,1,110
+BRDA:47,3,1,132
DA:49,2
DA:49,2
-DA:51,110
+DA:51,132
BRDA:51,4,0,2
-BRDA:51,4,1,108
+BRDA:51,4,1,130
DA:53,2
DA:53,2
-DA:55,108
-DA:55,108
-DA:56,108
-DA:56,108
+DA:55,130
+DA:55,130
+DA:56,130
+DA:56,130
FN:69,RuleInternal._removeRule
FNDA:55,RuleInternal._removeRule
DA:74,55
@@ -480,575 +480,610 @@ BRH:15
end_of_record
TN:
SF:src/rules/operation/RuleConditionalTransfer.sol
-FN:45,RuleConditionalTransfer.createTransferRequest
-FNDA:91,RuleConditionalTransfer.createTransferRequest
-DA:51,94
-DA:51,94
-DA:51,94
-DA:52,94
-DA:52,94
-DA:52,94
-DA:53,94
-DA:53,94
-BRDA:53,0,0,1
-BRDA:53,0,1,93
-DA:54,1
-DA:54,1
-DA:57,93
-DA:57,93
-BRDA:57,1,0,-
-BRDA:57,1,1,90
-DA:58,90
-DA:58,90
-DA:59,90
-DA:59,90
-DA:59,90
-DA:70,90
-DA:70,90
-DA:71,90
-DA:71,90
-DA:72,90
-DA:72,90
-DA:73,90
-DA:73,90
-DA:76,3
-DA:76,3
-DA:77,3
-DA:77,3
-DA:78,3
-DA:78,3
-FN:82,RuleConditionalTransfer.createTransferRequestBatch
+FN:50,RuleConditionalTransfer.createTransferRequest
+FNDA:102,RuleConditionalTransfer.createTransferRequest
+DA:56,105
+DA:56,105
+DA:56,105
+DA:57,105
+DA:57,105
+DA:57,105
+DA:58,105
+DA:58,105
+BRDA:58,0,0,1
+BRDA:58,0,1,104
+DA:59,1
+DA:59,1
+DA:61,104
+DA:61,104
+BRDA:61,1,0,-
+BRDA:61,1,1,101
+DA:62,101
+DA:62,101
+DA:63,101
+DA:63,101
+DA:63,101
+DA:74,101
+DA:74,101
+DA:75,101
+DA:75,101
+DA:76,101
+DA:76,101
+DA:77,101
+DA:77,101
+DA:80,3
+DA:80,3
+DA:81,3
+DA:81,3
+DA:82,3
+DA:82,3
+FN:89,RuleConditionalTransfer.createTransferRequestBatch
FNDA:3,RuleConditionalTransfer.createTransferRequestBatch
-DA:83,3
-DA:83,3
-BRDA:83,2,0,1
-BRDA:83,2,1,2
-DA:84,1
-DA:84,1
-DA:86,2
-DA:86,2
-BRDA:86,3,0,1
-BRDA:86,3,1,1
-DA:87,1
-DA:87,1
-DA:89,1
-DA:89,1
-DA:89,4
-DA:89,3
DA:90,3
DA:90,3
-FN:97,RuleConditionalTransfer.cancelTransferRequest
-FNDA:5,RuleConditionalTransfer.cancelTransferRequest
-DA:100,5
-DA:100,5
-FN:106,RuleConditionalTransfer.cancelTransferRequestBatch
+BRDA:90,2,0,1
+BRDA:90,2,1,2
+DA:91,1
+DA:91,1
+DA:93,2
+DA:93,2
+BRDA:93,3,0,1
+BRDA:93,3,1,1
+DA:94,1
+DA:94,1
+DA:96,1
+DA:96,1
+DA:96,4
+DA:96,3
+DA:97,3
+DA:97,3
+FN:104,RuleConditionalTransfer.cancelTransferRequest
+FNDA:6,RuleConditionalTransfer.cancelTransferRequest
+DA:107,6
+DA:107,6
+FN:113,RuleConditionalTransfer.cancelTransferRequestBatch
FNDA:3,RuleConditionalTransfer.cancelTransferRequestBatch
-DA:109,3
-DA:109,3
-BRDA:109,4,0,1
-BRDA:109,4,1,2
-DA:110,1
-DA:110,1
-DA:113,2
-DA:113,2
-DA:113,6
-DA:113,4
-DA:114,5
-DA:114,5
-DA:114,5
-BRDA:114,5,0,1
-BRDA:114,5,1,4
-DA:115,1
-DA:115,1
-DA:118,1
-DA:118,1
-DA:118,4
-DA:118,3
-DA:119,3
-DA:119,3
-FN:124,RuleConditionalTransfer._cancelTransferRequest
-FNDA:8,RuleConditionalTransfer._cancelTransferRequest
-DA:127,8
-DA:127,8
-DA:127,8
-BRDA:127,6,0,1
-BRDA:127,6,1,7
-DA:128,1
-DA:128,1
-DA:130,7
-DA:130,7
-DA:132,7
-DA:132,7
-DA:132,7
-BRDA:132,7,0,1
-BRDA:132,7,1,6
-DA:133,1
-DA:133,1
-DA:136,6
-DA:136,6
-DA:136,6
-DA:137,2
-DA:137,2
-BRDA:136,8,0,1
-BRDA:136,8,1,5
-DA:139,1
-DA:139,1
-DA:141,5
-DA:141,5
-FN:145,RuleConditionalTransfer.getRequestTrade
+DA:116,3
+DA:116,3
+BRDA:116,4,0,1
+BRDA:116,4,1,2
+DA:117,1
+DA:117,1
+DA:120,2
+DA:120,2
+DA:120,6
+DA:120,4
+DA:121,5
+DA:121,5
+DA:121,5
+BRDA:121,5,0,1
+BRDA:121,5,1,4
+DA:122,1
+DA:122,1
+DA:125,1
+DA:125,1
+DA:125,4
+DA:125,3
+DA:126,3
+DA:126,3
+FN:131,RuleConditionalTransfer._cancelTransferRequest
+FNDA:9,RuleConditionalTransfer._cancelTransferRequest
+DA:134,9
+DA:134,9
+DA:134,9
+BRDA:134,6,0,1
+BRDA:134,6,1,8
+DA:135,1
+DA:135,1
+DA:137,8
+DA:137,8
+DA:139,8
+DA:139,8
+DA:139,8
+BRDA:139,7,0,1
+BRDA:139,7,1,7
+DA:140,1
+DA:140,1
+DA:143,7
+DA:143,7
+DA:143,7
+DA:144,2
+DA:144,2
+BRDA:143,8,0,1
+BRDA:143,8,1,6
+DA:146,1
+DA:146,1
+DA:148,6
+DA:148,6
+FN:152,RuleConditionalTransfer.getRequestTrade
FNDA:57,RuleConditionalTransfer.getRequestTrade
-DA:146,57
-DA:146,57
-DA:146,57
-DA:147,57
-DA:147,57
-FN:155,RuleConditionalTransfer.getRequestByStatus
+DA:153,57
+DA:153,57
+DA:153,57
+DA:154,57
+DA:154,57
+FN:162,RuleConditionalTransfer.getRequestByStatus
FNDA:35,RuleConditionalTransfer.getRequestByStatus
-DA:156,35
-DA:156,35
-DA:157,35
-DA:157,35
-DA:158,35
-DA:158,35
-DA:161,35
-DA:161,35
-DA:161,73
-DA:161,38
-DA:162,38
-DA:162,38
-BRDA:162,9,0,36
-BRDA:162,9,1,38
-DA:163,36
-DA:163,36
-DA:168,35
+DA:163,35
+DA:163,35
+DA:164,35
+DA:164,35
+DA:165,35
+DA:165,35
DA:168,35
DA:168,35
-DA:171,35
-DA:171,35
-DA:171,73
-DA:171,38
-DA:172,38
-DA:172,38
-BRDA:172,10,0,-
-BRDA:172,10,1,36
-DA:174,36
-DA:174,36
-DA:175,36
-DA:175,36
-DA:176,36
-DA:176,36
-DA:179,35
-DA:179,35
-FN:186,RuleConditionalTransfer.operateOnTransfer
-FNDA:14,RuleConditionalTransfer.operateOnTransfer
-DA:192,14
-DA:192,14
-BRDA:192,11,0,2
-BRDA:192,11,1,12
-DA:193,2
-DA:193,2
-DA:195,12
-DA:195,12
-DA:195,12
-DA:196,12
-DA:196,12
-BRDA:196,12,0,5
-BRDA:196,12,1,7
-DA:197,5
-DA:197,5
-DA:198,5
-DA:198,5
-DA:200,7
-DA:200,7
-FN:210,RuleConditionalTransfer.detectTransferRestriction
-FNDA:8,RuleConditionalTransfer.detectTransferRestriction
-DA:215,8
-DA:215,8
-DA:215,8
-DA:216,8
-DA:216,8
-DA:216,8
-DA:216,8
-BRDA:216,13,0,6
-BRDA:216,13,1,2
-DA:217,6
-DA:217,6
-DA:220,2
-DA:220,2
-DA:220,2
-FN:229,RuleConditionalTransfer.canReturnTransferRestrictionCode
+DA:168,73
+DA:168,38
+DA:169,38
+DA:169,38
+BRDA:169,9,0,36
+BRDA:169,9,1,38
+DA:170,36
+DA:170,36
+DA:175,35
+DA:175,35
+DA:175,35
+DA:178,35
+DA:178,35
+DA:178,73
+DA:178,38
+DA:179,38
+DA:179,38
+BRDA:179,10,0,-
+BRDA:179,10,1,36
+DA:181,36
+DA:181,36
+DA:182,36
+DA:182,36
+DA:183,36
+DA:183,36
+DA:186,35
+DA:186,35
+FN:193,RuleConditionalTransfer.operateOnTransfer
+FNDA:33,RuleConditionalTransfer.operateOnTransfer
+DA:199,33
+DA:199,33
+DA:199,33
+DA:199,33
+BRDA:199,11,0,2
+BRDA:199,11,1,16
+DA:200,18
+DA:200,18
+DA:200,18
+DA:200,3
+BRDA:200,12,0,2
+BRDA:200,12,1,16
+DA:201,2
+DA:201,2
+DA:206,31
+DA:206,31
+BRDA:206,13,0,4
+BRDA:206,13,1,27
+DA:207,4
+DA:207,4
+DA:209,27
+DA:209,27
+DA:209,27
+DA:210,27
+DA:210,27
+BRDA:210,14,0,10
+BRDA:210,14,1,17
+DA:211,10
+DA:211,10
+DA:212,10
+DA:212,10
+DA:214,17
+DA:214,17
+FN:224,RuleConditionalTransfer.detectTransferRestriction
+FNDA:11,RuleConditionalTransfer.detectTransferRestriction
+DA:230,11
+DA:230,11
+DA:230,11
+DA:230,11
+BRDA:230,15,0,-
+BRDA:230,15,1,1
+DA:231,3
+DA:231,3
+DA:231,3
+DA:231,2
+BRDA:231,16,0,-
+BRDA:231,16,1,1
+DA:232,1
+DA:232,1
+DA:232,1
+DA:235,10
+DA:235,10
+DA:235,10
+DA:236,10
+DA:236,10
+DA:236,10
+DA:236,10
+BRDA:236,17,0,8
+BRDA:236,17,1,2
+DA:237,8
+DA:237,8
+DA:240,2
+DA:240,2
+DA:240,2
+FN:249,RuleConditionalTransfer.canReturnTransferRestrictionCode
FNDA:2,RuleConditionalTransfer.canReturnTransferRestrictionCode
-DA:232,2
-DA:232,2
-DA:233,2
-DA:233,2
-FN:241,RuleConditionalTransfer.messageForTransferRestriction
+DA:252,2
+DA:252,2
+DA:253,2
+DA:253,2
+FN:261,RuleConditionalTransfer.messageForTransferRestriction
FNDA:3,RuleConditionalTransfer.messageForTransferRestriction
-DA:244,3
-DA:244,3
-BRDA:244,14,0,2
-BRDA:244,14,1,1
-DA:245,2
-DA:245,2
-DA:247,1
-DA:247,1
-FN:258,RuleConditionalTransfer._validateBurnMint
-FNDA:22,RuleConditionalTransfer._validateBurnMint
-DA:264,22
-DA:264,22
-BRDA:263,15,0,2
-BRDA:263,15,1,20
-DA:267,2
-DA:267,2
-DA:269,20
-DA:269,20
-FN:278,RuleConditionalTransfer._validateApproval
-FNDA:20,RuleConditionalTransfer._validateApproval
-DA:281,20
-DA:281,20
-DA:281,20
-DA:282,20
-DA:282,20
-DA:282,20
-DA:284,20
-DA:284,20
-BRDA:284,16,0,7
-BRDA:284,16,1,13
-DA:286,7
-DA:286,7
-DA:288,13
-DA:288,13
-FN:295,RuleConditionalTransfer._msgSender
-FNDA:328,RuleConditionalTransfer._msgSender
-DA:301,328
-DA:301,328
-DA:301,328
-FN:307,RuleConditionalTransfer._msgData
+DA:264,3
+DA:264,3
+BRDA:264,18,0,2
+BRDA:264,18,1,1
+DA:265,2
+DA:265,2
+DA:267,1
+DA:267,1
+FN:278,RuleConditionalTransfer._validateBurnMint
+FNDA:41,RuleConditionalTransfer._validateBurnMint
+DA:284,41
+DA:284,41
+BRDA:283,19,0,4
+BRDA:283,19,1,37
+DA:287,4
+DA:287,4
+DA:289,37
+DA:289,37
+FN:298,RuleConditionalTransfer._validateApproval
+FNDA:37,RuleConditionalTransfer._validateApproval
+DA:301,37
+DA:301,37
+DA:301,37
+DA:302,37
+DA:302,37
+DA:302,37
+DA:304,37
+DA:304,37
+BRDA:304,20,0,12
+BRDA:304,20,1,25
+DA:306,12
+DA:306,12
+DA:308,25
+DA:308,25
+FN:315,RuleConditionalTransfer._msgSender
+FNDA:452,RuleConditionalTransfer._msgSender
+DA:321,452
+DA:321,452
+DA:321,452
+FN:327,RuleConditionalTransfer._msgData
FNDA:0,RuleConditionalTransfer._msgData
-DA:313,0
-DA:313,0
-DA:313,0
-FN:319,RuleConditionalTransfer._contextSuffixLength
-FNDA:328,RuleConditionalTransfer._contextSuffixLength
-DA:320,328
-DA:320,328
-DA:320,328
+DA:333,0
+DA:333,0
+DA:333,0
+FN:339,RuleConditionalTransfer._contextSuffixLength
+FNDA:452,RuleConditionalTransfer._contextSuffixLength
+DA:340,452
+DA:340,452
+DA:340,452
FNF:16
FNH:15
-LF:79
-LH:78
-BRF:34
-BRH:32
+LF:85
+LH:84
+BRF:42
+BRH:38
end_of_record
TN:
SF:src/rules/operation/abstract/RuleConditionalTransferOperator.sol
-FN:26,RuleConditionalTransferOperator.setIssuanceOptions
-FNDA:3,RuleConditionalTransferOperator.setIssuanceOptions
-DA:27,2
-DA:27,2
-BRDA:27,0,0,1
-BRDA:27,0,1,2
-DA:28,1
-DA:28,1
-DA:30,2
-DA:30,2
-BRDA:30,1,0,1
-BRDA:30,1,1,2
-DA:31,1
-DA:31,1
-FN:35,RuleConditionalTransferOperator.setAutomaticTransfer
-FNDA:2,RuleConditionalTransferOperator.setAutomaticTransfer
-DA:36,1
-DA:36,1
-BRDA:36,2,0,1
-BRDA:36,2,1,1
-DA:37,1
-DA:37,1
-DA:40,1
-DA:40,1
-DA:40,1
-DA:40,1
-BRDA:40,3,0,1
-BRDA:40,3,1,1
-DA:41,1
-DA:41,1
-FN:49,RuleConditionalTransferOperator.setTimeLimit
-FNDA:3,RuleConditionalTransferOperator.setTimeLimit
-DA:50,2
-DA:50,2
-BRDA:50,4,0,2
-BRDA:50,4,1,2
-DA:51,2
-DA:51,2
+FN:25,RuleConditionalTransferOperator.setConditionalWhitelist
+FNDA:25,RuleConditionalTransferOperator.setConditionalWhitelist
+DA:26,25
+DA:26,25
+DA:27,25
+DA:27,25
+FN:33,RuleConditionalTransferOperator.setIssuanceOptions
+FNDA:5,RuleConditionalTransferOperator.setIssuanceOptions
+DA:34,4
+DA:34,4
+BRDA:34,0,0,2
+BRDA:34,0,1,4
+DA:35,2
+DA:35,2
+DA:37,4
+DA:37,4
+BRDA:37,1,0,2
+BRDA:37,1,1,4
+DA:38,2
+DA:38,2
+FN:47,RuleConditionalTransferOperator.setAutomaticTransfer
+FNDA:3,RuleConditionalTransferOperator.setAutomaticTransfer
+DA:48,2
+DA:48,2
+BRDA:48,2,0,2
+BRDA:48,2,1,2
+DA:49,2
+DA:49,2
+DA:52,2
+DA:52,2
+DA:52,2
+DA:52,2
+BRDA:52,3,0,2
+BRDA:52,3,1,2
DA:53,2
DA:53,2
-BRDA:53,5,0,2
-BRDA:53,5,1,2
-DA:54,2
-DA:54,2
-FN:58,RuleConditionalTransferOperator.setAutomaticApproval
-FNDA:3,RuleConditionalTransferOperator.setAutomaticApproval
-DA:59,2
-DA:59,2
-BRDA:59,6,0,2
-BRDA:59,6,1,2
-DA:60,2
-DA:60,2
-DA:62,2
-DA:62,2
-BRDA:62,7,0,2
-BRDA:62,7,1,2
-DA:63,2
-DA:63,2
-FN:68,RuleConditionalTransferOperator.createTransferRequestWithApproval
+FN:62,RuleConditionalTransferOperator.setTimeLimit
+FNDA:4,RuleConditionalTransferOperator.setTimeLimit
+DA:63,3
+DA:63,3
+BRDA:63,4,0,3
+BRDA:63,4,1,3
+DA:64,3
+DA:64,3
+DA:66,3
+DA:66,3
+BRDA:66,5,0,3
+BRDA:66,5,1,3
+DA:67,3
+DA:67,3
+FN:75,RuleConditionalTransferOperator.setAutomaticApproval
+FNDA:5,RuleConditionalTransferOperator.setAutomaticApproval
+DA:76,4
+DA:76,4
+BRDA:76,6,0,4
+BRDA:76,6,1,4
+DA:77,4
+DA:77,4
+DA:79,4
+DA:79,4
+BRDA:79,7,0,4
+BRDA:79,7,1,4
+DA:80,4
+DA:80,4
+FN:87,RuleConditionalTransferOperator.createTransferRequestWithApproval
FNDA:6,RuleConditionalTransferOperator.createTransferRequestWithApproval
-DA:71,5
-DA:71,5
-FN:79,RuleConditionalTransferOperator.approveTransferRequest
-FNDA:26,RuleConditionalTransferOperator.approveTransferRequest
-DA:82,25
-DA:82,25
-FN:85,RuleConditionalTransferOperator.approveTransferRequestWithId
+DA:90,5
+DA:90,5
+FN:99,RuleConditionalTransferOperator.approveTransferRequest
+FNDA:33,RuleConditionalTransferOperator.approveTransferRequest
+DA:102,32
+DA:102,32
+FN:108,RuleConditionalTransferOperator.approveTransferRequestWithId
FNDA:5,RuleConditionalTransferOperator.approveTransferRequestWithId
-DA:88,4
-DA:88,4
-DA:88,4
-BRDA:88,8,0,2
-BRDA:88,8,1,2
-DA:89,2
-DA:89,2
-DA:91,2
-DA:91,2
-DA:92,2
-DA:92,2
-FN:96,RuleConditionalTransferOperator.resetRequestStatus
+DA:111,4
+DA:111,4
+DA:111,4
+BRDA:111,8,0,2
+BRDA:111,8,1,2
+DA:112,2
+DA:112,2
+DA:114,2
+DA:114,2
+DA:115,2
+DA:115,2
+FN:121,RuleConditionalTransferOperator.resetRequestStatus
FNDA:3,RuleConditionalTransferOperator.resetRequestStatus
-DA:99,2
-DA:99,2
-DA:99,2
-BRDA:99,9,0,1
-BRDA:99,9,1,1
-DA:100,1
-DA:100,1
-DA:102,1
-DA:102,1
-DA:103,1
-DA:103,1
-FN:108,RuleConditionalTransferOperator.approveTransferRequestBatchWithId
-FNDA:6,RuleConditionalTransferOperator.approveTransferRequestBatchWithId
-DA:111,5
-DA:111,5
-BRDA:111,10,0,1
-BRDA:111,10,1,4
-DA:112,1
-DA:112,1
-DA:114,4
-DA:114,4
-BRDA:114,11,0,1
-BRDA:114,11,1,3
-DA:115,1
-DA:115,1
-DA:118,3
-DA:118,3
-DA:118,13
-DA:118,10
-DA:119,11
-DA:119,11
-DA:119,11
-BRDA:119,12,0,1
-BRDA:119,12,1,10
-DA:120,1
-DA:120,1
-DA:123,2
-DA:123,2
-DA:123,6
-DA:123,4
-DA:124,5
-DA:124,5
-DA:125,5
-DA:125,5
-FN:130,RuleConditionalTransferOperator.approveTransferRequestBatch
-FNDA:6,RuleConditionalTransferOperator.approveTransferRequestBatch
-DA:133,6
-DA:133,6
-BRDA:133,13,0,1
-BRDA:133,13,1,5
-DA:134,1
-DA:134,1
-DA:136,5
-DA:136,5
-BRDA:136,14,0,3
-BRDA:136,14,1,2
-DA:137,3
-DA:137,3
-DA:139,2
-DA:139,2
-DA:139,11
-DA:139,9
-DA:140,9
-DA:140,9
-FN:145,RuleConditionalTransferOperator.createTransferRequestWithApprovalBatch
-FNDA:2,RuleConditionalTransferOperator.createTransferRequestWithApprovalBatch
-DA:148,2
-DA:148,2
-BRDA:148,15,0,1
-BRDA:148,15,1,1
-DA:149,1
-DA:149,1
-DA:151,1
-DA:151,1
+DA:124,2
+DA:124,2
+DA:124,2
+BRDA:124,9,0,1
+BRDA:124,9,1,1
+DA:125,1
+DA:125,1
+DA:127,1
+DA:127,1
+DA:128,1
+DA:128,1
+FN:135,RuleConditionalTransferOperator.approveTransferRequestBatchWithId
+FNDA:7,RuleConditionalTransferOperator.approveTransferRequestBatchWithId
+DA:138,5
+DA:138,5
+BRDA:138,10,0,1
+BRDA:138,10,1,4
+DA:139,1
+DA:139,1
+DA:141,4
+DA:141,4
+BRDA:141,11,0,1
+BRDA:141,11,1,3
+DA:142,1
+DA:142,1
+DA:145,3
+DA:145,3
+DA:145,13
+DA:145,10
+DA:146,11
+DA:146,11
+DA:146,11
+BRDA:146,12,0,1
+BRDA:146,12,1,10
+DA:147,1
+DA:147,1
+DA:150,2
+DA:150,2
+DA:150,6
+DA:150,4
DA:151,5
-DA:151,4
-DA:152,4
-DA:152,4
-FN:157,RuleConditionalTransferOperator.resetRequestStatusBatch
-FNDA:3,RuleConditionalTransferOperator.resetRequestStatusBatch
-DA:160,3
-DA:160,3
-BRDA:160,16,0,1
-BRDA:160,16,1,2
-DA:161,1
-DA:161,1
-DA:164,2
-DA:164,2
-DA:164,5
-DA:164,3
-DA:165,4
-DA:165,4
-DA:165,4
-BRDA:165,17,0,1
-BRDA:165,17,1,3
-DA:166,1
-DA:166,1
-DA:169,1
-DA:169,1
-DA:169,4
-DA:169,3
-DA:170,3
-DA:170,3
-DA:171,3
-DA:171,3
-FN:178,RuleConditionalTransferOperator._approveTransferRequestKeyElement
-FNDA:34,RuleConditionalTransferOperator._approveTransferRequestKeyElement
-DA:181,34
-DA:181,34
-BRDA:181,18,0,1
-BRDA:181,18,1,33
+DA:151,5
+DA:152,5
+DA:152,5
+FN:159,RuleConditionalTransferOperator.approveTransferRequestBatch
+FNDA:7,RuleConditionalTransferOperator.approveTransferRequestBatch
+DA:162,6
+DA:162,6
+BRDA:162,13,0,1
+BRDA:162,13,1,5
+DA:163,1
+DA:163,1
+DA:165,5
+DA:165,5
+BRDA:165,14,0,3
+BRDA:165,14,1,2
+DA:166,3
+DA:166,3
+DA:168,2
+DA:168,2
+DA:168,11
+DA:168,9
+DA:169,9
+DA:169,9
+FN:176,RuleConditionalTransferOperator.createTransferRequestWithApprovalBatch
+FNDA:3,RuleConditionalTransferOperator.createTransferRequestWithApprovalBatch
+DA:179,2
+DA:179,2
+BRDA:179,15,0,1
+BRDA:179,15,1,1
+DA:180,1
+DA:180,1
DA:182,1
DA:182,1
-DA:184,33
-DA:184,33
-DA:184,33
-DA:185,33
-DA:185,33
-DA:186,33
-DA:186,33
-BRDA:186,19,0,1
-BRDA:186,19,1,4
-DA:187,5
-DA:187,5
-BRDA:187,20,0,1
-BRDA:187,20,1,4
-DA:188,1
-DA:188,1
-DA:191,4
-DA:191,4
-DA:193,4
-DA:193,4
-DA:195,28
-DA:195,28
-FN:199,RuleConditionalTransferOperator._createTransferRequestWithApproval
+DA:182,5
+DA:182,4
+DA:183,4
+DA:183,4
+FN:190,RuleConditionalTransferOperator.resetRequestStatusBatch
+FNDA:3,RuleConditionalTransferOperator.resetRequestStatusBatch
+DA:193,3
+DA:193,3
+BRDA:193,16,0,1
+BRDA:193,16,1,2
+DA:194,1
+DA:194,1
+DA:197,2
+DA:197,2
+DA:197,5
+DA:197,3
+DA:198,4
+DA:198,4
+DA:198,4
+BRDA:198,17,0,1
+BRDA:198,17,1,3
+DA:199,1
+DA:199,1
+DA:202,1
+DA:202,1
+DA:202,4
+DA:202,3
+DA:203,3
+DA:203,3
+DA:204,3
+DA:204,3
+FN:210,RuleConditionalTransferOperator._approveTransferRequestKeyElement
+FNDA:41,RuleConditionalTransferOperator._approveTransferRequestKeyElement
+DA:213,41
+DA:213,41
+BRDA:213,18,0,1
+BRDA:213,18,1,40
+DA:214,1
+DA:214,1
+DA:216,40
+DA:216,40
+DA:216,40
+DA:217,40
+DA:217,40
+DA:218,40
+DA:218,40
+BRDA:218,19,0,1
+BRDA:218,19,1,6
+DA:219,7
+DA:219,7
+BRDA:219,20,0,1
+BRDA:219,20,1,6
+DA:220,1
+DA:220,1
+DA:223,6
+DA:223,6
+DA:225,6
+DA:225,6
+DA:227,33
+DA:227,33
+FN:231,RuleConditionalTransferOperator._createTransferRequestWithApproval
FNDA:0,RuleConditionalTransferOperator._createTransferRequestWithApproval
-DA:205,13
-DA:205,13
-DA:205,13
-DA:207,13
-DA:207,13
-BRDA:207,21,0,-
-BRDA:207,21,1,12
-DA:208,12
-DA:208,12
-DA:208,12
-DA:218,12
-DA:218,12
-DA:219,12
-DA:219,12
-DA:220,12
-DA:220,12
-DA:221,12
-DA:221,12
-DA:224,1
-DA:224,1
-DA:225,1
-DA:225,1
-DA:226,1
-DA:226,1
-FN:230,RuleConditionalTransferOperator._resetRequestStatus
-FNDA:9,RuleConditionalTransferOperator._resetRequestStatus
-DA:233,9
-DA:233,9
-DA:234,9
-DA:234,9
-FN:237,RuleConditionalTransferOperator._checkRequestStatus
-FNDA:106,RuleConditionalTransferOperator._checkRequestStatus
-DA:238,106
-DA:238,106
-DA:238,106
-FN:241,RuleConditionalTransferOperator._approveRequest
-FNDA:39,RuleConditionalTransferOperator._approveRequest
-DA:243,39
-DA:243,39
-BRDA:243,22,0,1
-BRDA:243,22,1,38
-DA:244,1
-DA:244,1
-DA:246,38
-BRDA:246,23,0,1
-BRDA:246,23,1,1
-DA:248,22
-DA:248,22
-BRDA:248,24,0,3
-BRDA:248,24,1,19
-DA:249,3
-DA:249,3
-DA:252,19
-DA:252,19
-DA:254,19
-DA:254,19
-DA:255,19
-DA:255,19
-DA:256,19
-DA:256,19
-DA:256,1
+DA:237,15
+DA:237,15
+DA:237,15
+DA:238,15
+DA:238,15
+BRDA:238,21,0,-
+BRDA:238,21,1,14
+DA:239,14
+DA:239,14
+DA:239,14
+DA:249,14
+DA:249,14
+DA:250,14
+DA:250,14
+DA:251,14
+DA:251,14
+DA:252,14
+DA:252,14
+DA:255,1
+DA:255,1
DA:256,1
DA:256,1
-BRDA:256,25,0,1
-BRDA:256,25,1,1
-DA:259,1
-DA:259,1
-DA:259,1
-BRDA:259,26,0,1
-BRDA:259,26,1,1
-DA:262,1
-DA:262,1
-DA:266,16
-DA:266,16
-DA:267,16
-DA:267,16
-FN:271,RuleConditionalTransferOperator._updateProcessedTransfer
-FNDA:5,RuleConditionalTransferOperator._updateProcessedTransfer
-DA:273,5
-DA:273,5
-DA:274,5
-DA:274,5
-DA:276,5
-DA:276,5
-DA:278,5
-DA:278,5
-FNF:18
-FNH:17
-LF:94
-LH:94
+DA:257,1
+DA:257,1
+FN:261,RuleConditionalTransferOperator._resetRequestStatus
+FNDA:10,RuleConditionalTransferOperator._resetRequestStatus
+DA:264,10
+DA:264,10
+DA:265,10
+DA:265,10
+FN:268,RuleConditionalTransferOperator._checkRequestStatus
+FNDA:119,RuleConditionalTransferOperator._checkRequestStatus
+DA:270,119
+DA:270,119
+DA:270,119
+FN:273,RuleConditionalTransferOperator._approveRequest
+FNDA:46,RuleConditionalTransferOperator._approveRequest
+DA:275,46
+DA:275,46
+BRDA:275,22,0,1
+BRDA:275,22,1,45
+DA:276,1
+DA:276,1
+DA:278,45
+BRDA:278,23,0,2
+BRDA:278,23,1,2
+DA:280,27
+DA:280,27
+BRDA:280,24,0,3
+BRDA:280,24,1,24
+DA:281,3
+DA:281,3
+DA:284,24
+DA:284,24
+DA:286,24
+DA:286,24
+DA:287,24
+DA:287,24
+DA:288,24
+DA:288,24
+DA:288,2
+DA:288,2
+DA:288,2
+BRDA:288,25,0,2
+BRDA:288,25,1,2
+DA:291,2
+DA:291,2
+DA:291,2
+BRDA:291,26,0,2
+BRDA:291,26,1,2
+DA:293,2
+DA:293,2
+DA:297,18
+DA:297,18
+DA:298,18
+DA:298,18
+FN:305,RuleConditionalTransferOperator._updateProcessedTransfer
+FNDA:10,RuleConditionalTransferOperator._updateProcessedTransfer
+DA:307,10
+DA:307,10
+DA:308,10
+DA:308,10
+DA:310,10
+DA:310,10
+DA:312,10
+DA:312,10
+FNF:19
+FNH:18
+LF:96
+LH:96
BRF:54
BRH:53
end_of_record
@@ -1241,9 +1276,9 @@ FNDA:4,RuleAddressList.removeAddressesFromTheList
DA:54,3
DA:54,3
FN:62,RuleAddressList.addAddressToTheList
-FNDA:28,RuleAddressList.addAddressToTheList
-DA:65,27
-DA:65,27
+FNDA:40,RuleAddressList.addAddressToTheList
+DA:65,39
+DA:65,39
FN:74,RuleAddressList.removeAddressFromTheList
FNDA:3,RuleAddressList.removeAddressFromTheList
DA:77,2
@@ -1254,25 +1289,25 @@ DA:86,24
DA:86,24
DA:86,24
FN:96,RuleAddressList.addressIsListed
-FNDA:57,RuleAddressList.addressIsListed
-DA:99,115
-DA:99,115
-DA:99,115
+FNDA:83,RuleAddressList.addressIsListed
+DA:99,141
+DA:99,141
+DA:99,141
FN:106,RuleAddressList._msgSender
-FNDA:60,RuleAddressList._msgSender
-DA:112,60
-DA:112,60
-DA:112,60
+FNDA:72,RuleAddressList._msgSender
+DA:112,72
+DA:112,72
+DA:112,72
FN:118,RuleAddressList._msgData
FNDA:0,RuleAddressList._msgData
DA:124,0
DA:124,0
DA:124,0
FN:130,RuleAddressList._contextSuffixLength
-FNDA:60,RuleAddressList._contextSuffixLength
-DA:131,60
-DA:131,60
-DA:131,60
+FNDA:72,RuleAddressList._contextSuffixLength
+DA:131,72
+DA:131,72
+DA:131,72
FNF:9
FNH:8
LF:9
@@ -1318,16 +1353,16 @@ DA:49,6
DA:52,3
DA:52,3
FN:60,RuleAddressListInternal._addAddressToThelist
-FNDA:27,RuleAddressListInternal._addAddressToThelist
-DA:63,27
+FNDA:39,RuleAddressListInternal._addAddressToThelist
+DA:63,39
BRDA:63,2,0,1
-BRDA:63,2,1,26
+BRDA:63,2,1,38
DA:65,1
DA:65,1
-DA:67,26
-DA:67,26
-DA:68,26
-DA:68,26
+DA:67,38
+DA:67,38
+DA:68,38
+DA:68,38
FN:77,RuleAddressListInternal._removeAddressFromThelist
FNDA:2,RuleAddressListInternal._removeAddressFromThelist
DA:80,2
@@ -1345,9 +1380,9 @@ FNDA:24,RuleAddressListInternal._numberListedAddress
DA:93,24
DA:93,24
FN:102,RuleAddressListInternal._addressIsListed
-FNDA:115,RuleAddressListInternal._addressIsListed
-DA:105,115
-DA:105,115
+FNDA:141,RuleAddressListInternal._addressIsListed
+DA:105,141
+DA:105,141
FNF:6
FNH:6
LF:22
diff --git a/lib/CMTAT b/lib/CMTAT
index 4774b7e..23a1e59 160000
--- a/lib/CMTAT
+++ b/lib/CMTAT
@@ -1 +1 @@
-Subproject commit 4774b7e7aadae29994872c7a4a0445ed819bd570
+Subproject commit 23a1e59f913d079d0c09d32fafbd95ab2d426093
diff --git a/lib/forge-std b/lib/forge-std
index e4aef94..978ac6f 160000
--- a/lib/forge-std
+++ b/lib/forge-std
@@ -1 +1 @@
-Subproject commit e4aef94c1768803a16fe19f7ce8b65defd027cfd
+Subproject commit 978ac6fadb62f5f0b723c996f64be52eddba6801
diff --git a/src/rules/operation/RuleConditionalTransfer.sol b/src/rules/operation/RuleConditionalTransfer.sol
index fed9aee..5b6b03b 100644
--- a/src/rules/operation/RuleConditionalTransfer.sol
+++ b/src/rules/operation/RuleConditionalTransfer.sol
@@ -42,18 +42,22 @@ contract RuleConditionalTransfer is RuleValidateTransfer, IRuleOperation, RuleC
options = options_;
}
+ /**
+ * @notice Create a request of transfer for yourselves
+ * @param to recipient of tokens
+ * @param value amount of tokens to transfer
+ */
function createTransferRequest(
address to, uint256 value
) public {
// WAIT => Will set a new delay to approve
// APPROVED => will overwrite previous status
- // DENIED => KO
+ // DENIED => reject
address from = _msgSender();
bytes32 key = keccak256(abi.encode(from, to, value));
if(transferRequests[key].status == STATUS.DENIED){
revert RuleConditionalTransfer_TransferDenied();
}
- // Status NONE not enough because reset is possible
if(_checkRequestStatus(key)){
uint256 requestIdLocal = requestId;
TransferRequest memory newTransferApproval = TransferRequest({
@@ -79,6 +83,9 @@ contract RuleConditionalTransfer is RuleValidateTransfer, IRuleOperation, RuleC
}
}
+ /**
+ * @notice Batch version of {createTransferRequest}
+ */
function createTransferRequestBatch(address[] memory tos, uint256[] memory values) public{
if(tos.length == 0){
revert RuleConditionalTransfer_EmptyArray();
diff --git a/src/rules/operation/abstract/RuleConditionalTransferInvariantStorage.sol b/src/rules/operation/abstract/RuleConditionalTransferInvariantStorage.sol
index dc4e4f3..04c40e2 100644
--- a/src/rules/operation/abstract/RuleConditionalTransferInvariantStorage.sol
+++ b/src/rules/operation/abstract/RuleConditionalTransferInvariantStorage.sol
@@ -6,22 +6,36 @@ import "OZ/token/ERC20/IERC20.sol";
import "../../validation/abstract/RuleCommonInvariantStorage.sol";
import "src/rules/validation/RuleWhitelist.sol";
abstract contract RuleConditionalTransferInvariantStorage is RuleCommonInvariantStorage {
+ /**
+ * perform automatically a transfer if the transfer request is approved.
+ * To perform the transfer, the token holder has to approve the rule to spend tokens on his behalf (standard ERC-20 approval).
+ * If the allowance is not sufficient, the request will be approved, but without performing the transfer.
+ */
struct AUTOMATIC_TRANSFER {
bool isActivate;
IERC20 cmtat;
}
+
struct ISSUANCE {
+ // Authorize mint without the need of approval
bool authorizedMintWithoutApproval;
+ // Authorize burn without the need of approval
bool authorizedBurnWithoutApproval;
}
struct TIME_LIMIT {
+ // time limit for an operator to approve a request
uint256 timeLimitToApprove;
+ // once a request is approved, time limit for the token holder to perform the transfer
uint256 timeLimitToTransfer;
}
struct AUTOMATIC_APPROVAL {
bool isActivate;
+ /**
+ * If the transfer is not approved or denied within {timeLimitBeforeAutomaticApproval},
+ * the request is considered as approved during a transfer.
+ */
uint256 timeLimitBeforeAutomaticApproval;
}
diff --git a/src/rules/operation/abstract/RuleConditionalTransferOperator.sol b/src/rules/operation/abstract/RuleConditionalTransferOperator.sol
index cd17779..5a8497f 100644
--- a/src/rules/operation/abstract/RuleConditionalTransferOperator.sol
+++ b/src/rules/operation/abstract/RuleConditionalTransferOperator.sol
@@ -6,27 +6,30 @@ import "OZ/access/AccessControl.sol";
import "./RuleConditionalTransferInvariantStorage.sol";
import "OZ/token/ERC20/utils/SafeERC20.sol";
/**
-* @title a RuleConditionalTransfer manager
+* @title Restricted functions
*/
-
abstract contract RuleConditionalTransferOperator is AccessControl, RuleConditionalTransferInvariantStorage {
// Security
using SafeERC20 for IERC20;
- OPTION internal options;
-
-
- // Getter
+ // public variable with automatic Getter
+ OPTION public options;
uint256 public requestId;
mapping(uint256 => bytes32) public IdToKey;
mapping(bytes32 => TransferRequest) public transferRequests;
RuleWhitelist public whitelistConditionalTransfer;
+ /**
+ * @notice set a whitelist. A transfer does not need of an approved request if from and to are in the whitelist
+ */
function setConditionalWhitelist(RuleWhitelist newWhitelistConditionalTransfer) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE){
whitelistConditionalTransfer = newWhitelistConditionalTransfer;
emit WhitelistConditionalTransfer(newWhitelistConditionalTransfer);
}
+ /**
+ set/unset the issuance options (mint & burn)
+ */
function setIssuanceOptions(ISSUANCE calldata issuance_) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE){
if(options.issuance.authorizedMintWithoutApproval != issuance_.authorizedMintWithoutApproval ){
options.issuance.authorizedMintWithoutApproval = issuance_.authorizedMintWithoutApproval;
@@ -36,6 +39,11 @@ abstract contract RuleConditionalTransferOperator is AccessControl, RuleConditio
}
}
+ /**
+ * @notice set/unset the option to perform the transfer if the request is approved by the rule operator.
+ * To perform the transfer, the token holder has to approve the rule to spend tokens on his behalf (standard ERC-20 approval).
+ * If the allowance is not sufficient, the request will be approved, but without performing the transfer.
+ */
function setAutomaticTransfer(AUTOMATIC_TRANSFER calldata automaticTransfer_) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE){
if(automaticTransfer_.isActivate != options.automaticTransfer.isActivate){
options.automaticTransfer.isActivate = automaticTransfer_.isActivate;
@@ -48,7 +56,8 @@ abstract contract RuleConditionalTransferOperator is AccessControl, RuleConditio
/**
* @notice set time limit for new requests (Approval and transfer)
- * Don't affect already created requests
+ * timeLimitToApprove: time limit for an operator to approve a request
+ * timeLimitToTransfer: once a request is approved, time limit for the token holder to perform the transfer
*/
function setTimeLimit(TIME_LIMIT memory timeLimit_) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE){
if(options.timeLimit.timeLimitToApprove != timeLimit_.timeLimitToApprove){
@@ -58,7 +67,11 @@ abstract contract RuleConditionalTransferOperator is AccessControl, RuleConditio
options.timeLimit.timeLimitToTransfer = timeLimit_.timeLimitToTransfer;
}
}
-
+ /**
+ * @notice If the transfer is not approved or denied within {timeLimitBeforeAutomaticApproval},
+ * the request is considered as approved during a transfer.
+ *
+ */
function setAutomaticApproval(AUTOMATIC_APPROVAL memory automaticApproval_) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE){
if(options.automaticApproval.isActivate != automaticApproval_.isActivate ){
options.automaticApproval.isActivate = automaticApproval_.isActivate;
@@ -68,7 +81,9 @@ abstract contract RuleConditionalTransferOperator is AccessControl, RuleConditio
}
}
-
+ /**
+ * @notice create a transfer request directly approved
+ */
function createTransferRequestWithApproval(
TransferRequestKeyElement calldata keyElement
) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE){
@@ -76,27 +91,33 @@ abstract contract RuleConditionalTransferOperator is AccessControl, RuleConditio
}
/**
+ @notice approve a transferRequest
@param keyElement contains from, to, value
@param partialValue amount approved. Put 0 if all the amount specified by value is approved.
- @param isApproved_ approved (true) or refused (false). Put true if you use partialApproval
+ @param isApproved approved (true) or refused (false). Put true if you use partialApproval
*/
function approveTransferRequest(
- TransferRequestKeyElement calldata keyElement, uint256 partialValue, bool isApproved_
+ TransferRequestKeyElement calldata keyElement, uint256 partialValue, bool isApproved
) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE) {
- _approveTransferRequestKeyElement(keyElement, partialValue, isApproved_);
+ _approveTransferRequestKeyElement(keyElement, partialValue, isApproved);
}
+ /**
+ * @notice approve a transferRequestby using its id
+ */
function approveTransferRequestWithId(
- uint256 requestId_, bool isApproved_
+ uint256 requestId_, bool isApproved
) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE){
if(requestId_ + 1 > requestId) {
revert RuleConditionalTransfer_InvalidId();
}
TransferRequest memory transferRequest = transferRequests[IdToKey[requestId_]];
- _approveRequest(transferRequest, isApproved_);
+ _approveRequest(transferRequest, isApproved);
}
-
+ /**
+ * @notice reset to None the status of a request
+ */
function resetRequestStatus(
uint256 requestId_
) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE){
@@ -108,14 +129,16 @@ abstract contract RuleConditionalTransferOperator is AccessControl, RuleConditio
}
/***** Batch function */
-
+ /**
+ * @notice Batch version of {approveTransferRequestWithId}
+ */
function approveTransferRequestBatchWithId(
- uint256[] calldata requestId_, bool[] calldata isApproved_
+ uint256[] calldata requestId_, bool[] calldata isApproved
) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE){
if(requestId_.length == 0){
revert RuleConditionalTransfer_EmptyArray();
}
- if(requestId_.length != isApproved_.length){
+ if(requestId_.length != isApproved.length){
revert RuleConditionalTransfer_InvalidLengthArray();
}
// Check id validity before performing actions
@@ -126,26 +149,30 @@ abstract contract RuleConditionalTransferOperator is AccessControl, RuleConditio
}
for(uint256 i = 0; i < requestId_.length; ++i){
TransferRequest memory transferRequest = transferRequests[IdToKey[requestId_[i]]];
- _approveRequest(transferRequest, isApproved_[i]);
+ _approveRequest(transferRequest, isApproved[i]);
}
}
-
+ /**
+ * @notice Batch version of {approveTransferRequest}
+ */
function approveTransferRequestBatch(
- TransferRequestKeyElement[] calldata keyElements, uint256[] calldata partialValues, bool[] calldata isApproved_
+ TransferRequestKeyElement[] calldata keyElements, uint256[] calldata partialValues, bool[] calldata isApproved
) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE) {
if(keyElements.length == 0){
revert RuleConditionalTransfer_EmptyArray();
}
- if((keyElements.length != partialValues.length) || (partialValues.length != isApproved_.length)){
+ if((keyElements.length != partialValues.length) || (partialValues.length != isApproved.length)){
revert RuleConditionalTransfer_InvalidLengthArray();
}
for(uint256 i = 0; i < keyElements.length; ++i){
- _approveTransferRequestKeyElement(keyElements[i], partialValues[i], isApproved_[i]);
+ _approveTransferRequestKeyElement(keyElements[i], partialValues[i], isApproved[i]);
}
}
-
+ /**
+ * @notice Batch version of {createTransferRequestWithApproval}
+ */
function createTransferRequestWithApprovalBatch(
TransferRequestKeyElement[] calldata keyElements
) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE){
@@ -157,7 +184,9 @@ abstract contract RuleConditionalTransferOperator is AccessControl, RuleConditio
}
}
-
+ /**
+ * @notice Batch version of {resetRequestStatus}
+ */
function resetRequestStatusBatch(
uint256[] memory requestIds
) public onlyRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE){
@@ -178,9 +207,8 @@ abstract contract RuleConditionalTransferOperator is AccessControl, RuleConditio
/*** Internal functions ****/
-
function _approveTransferRequestKeyElement(
- TransferRequestKeyElement calldata keyElement, uint256 partialValue, bool isApproved_
+ TransferRequestKeyElement calldata keyElement, uint256 partialValue, bool isApproved
) internal {
if(partialValue > keyElement.value){
revert RuleConditionalTransfer_InvalidValueApproved();
@@ -188,7 +216,7 @@ abstract contract RuleConditionalTransferOperator is AccessControl, RuleConditio
bytes32 key = keccak256(abi.encode(keyElement.from, keyElement.to, keyElement.value));
TransferRequest memory transferRequest = transferRequests[key];
if(partialValue > 0 ){
- if(! isApproved_){
+ if(! isApproved){
revert RuleConditionalTransfer_CannotDeniedPartially();
}
// Denied the first request
@@ -196,7 +224,7 @@ abstract contract RuleConditionalTransferOperator is AccessControl, RuleConditio
// Create new request
_createTransferRequestWithApproval(TransferRequestKeyElement({from: keyElement.from, to: keyElement.to, value: partialValue}));
}else{
- _approveRequest(transferRequest, isApproved_);
+ _approveRequest(transferRequest, isApproved);
}
}
@@ -207,7 +235,6 @@ abstract contract RuleConditionalTransferOperator is AccessControl, RuleConditio
// APPROVED => will overwrite previous status with a new delay
// DENIED => will overwrite
bytes32 key = keccak256(abi.encode(keyElement.from, keyElement.to, keyElement.value));
- // Status NONE not enough because reset is possible
if(_checkRequestStatus(key)){
TransferRequest memory newTransferApproval = TransferRequest({
key: key,
@@ -239,15 +266,16 @@ abstract contract RuleConditionalTransferOperator is AccessControl, RuleConditio
}
function _checkRequestStatus(bytes32 key) internal view returns(bool) {
+ // Status NONE not enough because reset is possible
return (transferRequests[key].status == STATUS.NONE) && (transferRequests[key].key == 0x0);
}
- function _approveRequest(TransferRequest memory transferRequest , bool isApproved_) internal{
+ function _approveRequest(TransferRequest memory transferRequest , bool isApproved) internal{
// status
if(transferRequest.status != STATUS.WAIT){
revert RuleConditionalTransfer_Wrong_Status();
}
- if(isApproved_){
+ if(isApproved){
// Time
if(block.timestamp > (transferRequest.askTime + options.timeLimit.timeLimitToApprove)){
revert RuleConditionalTransfer_timeExceeded();
@@ -261,7 +289,6 @@ abstract contract RuleConditionalTransferOperator is AccessControl, RuleConditio
// Transfer with approval
// External call
if(options.automaticTransfer.cmtat.allowance(transferRequest.from, address(this)) >= transferRequest.value){
- //_updateProcessedTransfer(transferRequest.key);
// Will call the ruleEngine and the rule again...
options.automaticTransfer.cmtat.safeTransferFrom(transferRequest.from, transferRequest.to, transferRequest.value);
}
@@ -272,6 +299,9 @@ abstract contract RuleConditionalTransferOperator is AccessControl, RuleConditio
}
}
+ /**
+ * @notice update the request during a transfer
+ */
function _updateProcessedTransfer(bytes32 key) internal {
// Reset to zero
transferRequests[key].maxTime = 0;
diff --git a/test/RuleConditionalTransfer/CMTATIntegrationWhitelist.t .sol b/test/RuleConditionalTransfer/CMTATIntegrationWhitelist.t .sol
new file mode 100644
index 0000000..64f5664
--- /dev/null
+++ b/test/RuleConditionalTransfer/CMTATIntegrationWhitelist.t .sol
@@ -0,0 +1,518 @@
+// SPDX-License-Identifier: MPL-2.0
+pragma solidity ^0.8.20;
+
+import "forge-std/Test.sol";
+import "CMTAT/CMTAT_STANDALONE.sol";
+import "../HelperContract.sol";
+import "src/RuleEngine.sol";
+
+/**
+* @title Integration test with the CMTAT
+*/
+contract CMTATIntegrationConditionalTransfer is Test, HelperContract {
+ // Defined in CMTAT.sol
+ uint8 constant TRANSFER_OK = 0;
+ string constant TEXT_TRANSFER_OK = "No restriction";
+
+ RuleEngine ruleEngineMock;
+ uint256 resUint256;
+ bool resBool;
+
+ uint256 ADDRESS1_BALANCE_INIT = 31;
+ uint256 ADDRESS2_BALANCE_INIT = 32;
+ uint256 ADDRESS3_BALANCE_INIT = 33;
+
+ uint256 FLAG = 5;
+
+ uint256 defaultValue = 10;
+ bytes32 defaultKey = keccak256(abi.encode(ADDRESS1, ADDRESS2, defaultValue));
+
+ TransferRequestKeyElement transferRequestInput = TransferRequestKeyElement({
+ from: ADDRESS1,
+ to: ADDRESS2,
+ value:defaultValue
+ });
+
+
+
+ // Arrange
+ function setUp() public {
+ TIME_LIMIT memory timeLimit_ = TIME_LIMIT({
+ timeLimitToApprove: 7 days,
+ timeLimitToTransfer: 30 days
+ });
+ ISSUANCE memory issuanceOption_ = ISSUANCE({
+ authorizedMintWithoutApproval:true,
+ authorizedBurnWithoutApproval:true
+ });
+
+ AUTOMATIC_APPROVAL memory automaticApproval_ = AUTOMATIC_APPROVAL({
+ isActivate: false,
+ timeLimitBeforeAutomaticApproval: 0
+ });
+
+ AUTOMATIC_TRANSFER memory automaticTransfer_ = AUTOMATIC_TRANSFER({
+ isActivate:false,
+ cmtat: IERC20(address(0))
+ });
+ OPTION memory options = OPTION({
+ issuance:issuanceOption_,
+ timeLimit: timeLimit_,
+ automaticApproval: automaticApproval_,
+ automaticTransfer:automaticTransfer_
+ });
+
+ // global arrange
+ uint8 decimals = 0;
+ vm.prank(DEFAULT_ADMIN_ADDRESS);
+ CMTAT_CONTRACT = new CMTAT_STANDALONE(
+ ZERO_ADDRESS,
+ DEFAULT_ADMIN_ADDRESS,
+ IAuthorizationEngine(address(0)),
+ "CMTA Token",
+ "CMTAT",
+ decimals,
+ "CMTAT_ISIN",
+ "https://cmta.ch",
+ IRuleEngine(address(0)),
+ "CMTAT_info",
+ FLAG
+ );
+
+
+ // Whitelist
+ ruleWhitelist = new RuleWhitelist(DEFAULT_ADMIN_ADDRESS, ZERO_ADDRESS);
+
+ // RuleEngine
+ vm.prank(DEFAULT_ADMIN_ADDRESS);
+ ruleEngineMock = new RuleEngine(DEFAULT_ADMIN_ADDRESS, ZERO_ADDRESS, address(CMTAT_CONTRACT));
+
+ // RuleConditionalTransfer
+ vm.prank(DEFAULT_ADMIN_ADDRESS);
+ ruleConditionalTransfer = new RuleConditionalTransfer(
+ DEFAULT_ADMIN_ADDRESS,
+ ZERO_ADDRESS,
+ ruleEngineMock,
+ options
+ );
+ // Add whitelist
+ vm.prank(DEFAULT_ADMIN_ADDRESS);
+ ruleConditionalTransfer.setConditionalWhitelist(ruleWhitelist);
+ // specific arrange
+ vm.prank(DEFAULT_ADMIN_ADDRESS);
+ ruleConditionalTransfer.grantRole(RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE, CONDITIONAL_TRANSFER_OPERATOR_ADDRESS);
+
+ // RuleEngine
+ vm.prank(DEFAULT_ADMIN_ADDRESS);
+ ruleEngineMock.addRuleOperation(ruleConditionalTransfer);
+
+ // Mint
+ vm.prank(DEFAULT_ADMIN_ADDRESS);
+ CMTAT_CONTRACT.mint(ADDRESS1, ADDRESS1_BALANCE_INIT);
+ vm.prank(DEFAULT_ADMIN_ADDRESS);
+ CMTAT_CONTRACT.mint(ADDRESS2, ADDRESS2_BALANCE_INIT);
+ vm.prank(DEFAULT_ADMIN_ADDRESS);
+ CMTAT_CONTRACT.mint(ADDRESS3, ADDRESS3_BALANCE_INIT);
+ vm.prank(DEFAULT_ADMIN_ADDRESS);
+
+ // We set the Rule Engine
+ CMTAT_CONTRACT.setRuleEngine(ruleEngineMock);
+ }
+
+ function _createTransferRequest() internal{
+ vm.prank(ADDRESS1);
+ // Act
+ vm.expectEmit(true, true, true, true);
+ emit transferWaiting(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0);
+ ruleConditionalTransfer.createTransferRequest(ADDRESS2, defaultValue);
+ }
+
+ /******* Transfer *******/
+ function testCanMakeATransferWithoutApprovalIfFromAndToAreInTheWhitelist() public {
+ vm.prank(DEFAULT_ADMIN_ADDRESS);
+ ruleWhitelist.addAddressToTheList(ADDRESS1);
+ vm.prank(DEFAULT_ADMIN_ADDRESS);
+ ruleWhitelist.addAddressToTheList(ADDRESS2);
+ // Arrange
+ // Act
+ vm.prank(ADDRESS1);
+ CMTAT_CONTRACT.transfer(ADDRESS2, 21);
+ }
+
+ function testCannotMakeATransferWithoutApprovalIfOnlyFromIsInTheWhitelist() public {
+ vm.prank(DEFAULT_ADMIN_ADDRESS);
+ ruleWhitelist.addAddressToTheList(ADDRESS1);
+ // Arrange
+ // Act
+ vm.expectRevert(
+ abi.encodeWithSelector(Errors.CMTAT_InvalidTransfer.selector, ADDRESS1, ADDRESS2, 21));
+ vm.prank(ADDRESS1);
+ CMTAT_CONTRACT.transfer(ADDRESS2, 21);
+ }
+
+ function testCannotMakeATransferWithoutApprovalIfOnlyToIsInTheWhitelist() public {
+ vm.prank(DEFAULT_ADMIN_ADDRESS);
+ ruleWhitelist.addAddressToTheList(ADDRESS2);
+ // Arrange
+ // Act
+ vm.expectRevert(
+ abi.encodeWithSelector(Errors.CMTAT_InvalidTransfer.selector, ADDRESS1, ADDRESS2, 21));
+ vm.prank(ADDRESS1);
+ CMTAT_CONTRACT.transfer(ADDRESS2, 21);
+ }
+
+ function testCanSetANewWhitelist() public {
+ RuleWhitelist ruleWhitelist2 = new RuleWhitelist(DEFAULT_ADMIN_ADDRESS, ZERO_ADDRESS);
+ vm.prank(DEFAULT_ADMIN_ADDRESS);
+ vm.expectEmit(true, false, false, false);
+ emit WhitelistConditionalTransfer(ruleWhitelist2);
+ ruleConditionalTransfer.setConditionalWhitelist(ruleWhitelist2);
+ vm.prank(DEFAULT_ADMIN_ADDRESS);
+ ruleWhitelist2.addAddressToTheList(ADDRESS1);
+ vm.prank(DEFAULT_ADMIN_ADDRESS);
+ ruleWhitelist2.addAddressToTheList(ADDRESS2);
+
+ // Arrange
+ // Act
+ vm.prank(ADDRESS1);
+ CMTAT_CONTRACT.transfer(ADDRESS2, 21);
+ }
+
+ function testCanUnSetWhitelist() public {
+ // Arrange
+ RuleWhitelist ruleWhitelist2 = new RuleWhitelist(DEFAULT_ADMIN_ADDRESS, ZERO_ADDRESS);
+ vm.prank(DEFAULT_ADMIN_ADDRESS);
+ vm.expectEmit(true, false, false, false);
+ emit WhitelistConditionalTransfer(ruleWhitelist2);
+ ruleConditionalTransfer.setConditionalWhitelist(ruleWhitelist2);
+ vm.prank(DEFAULT_ADMIN_ADDRESS);
+ ruleWhitelist2.addAddressToTheList(ADDRESS1);
+ vm.prank(DEFAULT_ADMIN_ADDRESS);
+ ruleWhitelist2.addAddressToTheList(ADDRESS2);
+
+ // Act
+ vm.prank(DEFAULT_ADMIN_ADDRESS);
+ ruleConditionalTransfer.setConditionalWhitelist(RuleWhitelist(ZERO_ADDRESS));
+
+ // Assert
+ vm.prank(ADDRESS1);
+ vm.expectRevert(
+ abi.encodeWithSelector(Errors.CMTAT_InvalidTransfer.selector, ADDRESS1, ADDRESS2, 21));
+ CMTAT_CONTRACT.transfer(ADDRESS2, 21);
+ }
+
+ function testCanDetectTransferRestrictionOKWithWhitelist() public {
+ // Arrange
+ vm.prank(DEFAULT_ADMIN_ADDRESS);
+ ruleWhitelist.addAddressToTheList(ADDRESS1);
+ vm.prank(DEFAULT_ADMIN_ADDRESS);
+ ruleWhitelist.addAddressToTheList(ADDRESS2);
+
+ // Act
+ uint8 resUint8 = ruleConditionalTransfer.detectTransferRestriction(
+ ADDRESS1,
+ ADDRESS2,
+ defaultValue
+ );
+
+ // Assert
+ assertEq(resUint8, 0);
+ }
+
+ function testCanDetectTransferRestrictionWithOnlyFromInTheWhitelist() public {
+ // Arrange
+ vm.prank(DEFAULT_ADMIN_ADDRESS);
+ ruleWhitelist.addAddressToTheList(ADDRESS1);
+
+ // Act
+ uint8 resUint8 = ruleConditionalTransfer.detectTransferRestriction(
+ ADDRESS1,
+ ADDRESS2,
+ defaultValue
+ );
+
+ // Assert
+ assertEq(resUint8, CODE_TRANSFER_REQUEST_NOT_APPROVED);
+ }
+
+ function testCanDetectTransferRestrictionWithOnlyToInTheWhitelist() public {
+ // Arrange
+ vm.prank(DEFAULT_ADMIN_ADDRESS);
+ ruleWhitelist.addAddressToTheList(ADDRESS2);
+
+ // Act
+ uint8 resUint8 = ruleConditionalTransfer.detectTransferRestriction(
+ ADDRESS1,
+ ADDRESS2,
+ defaultValue
+ );
+
+ // Assert
+ assertEq(resUint8, CODE_TRANSFER_REQUEST_NOT_APPROVED);
+ }
+
+
+
+ /***** Test from CMTAT integration */
+
+ function testCannotTransferWithoutApproval() public {
+ // Arrange
+ vm.prank(ADDRESS1);
+ vm.expectRevert(
+ abi.encodeWithSelector(Errors.CMTAT_InvalidTransfer.selector, ADDRESS1, ADDRESS2, 21));
+ // Act
+ CMTAT_CONTRACT.transfer(ADDRESS2, 21);
+ }
+
+ function testCanMakeATransferIfApproved() public {
+ // Arrange
+ vm.prank(ADDRESS1);
+ // Act
+ bytes32 key = keccak256(abi.encode(ADDRESS1, ADDRESS2,defaultValue));
+ ruleConditionalTransfer.createTransferRequest(ADDRESS2,defaultValue);
+
+ // Act
+ vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS);
+ vm.expectEmit(true, true, true, true);
+ emit transferApproved(key, ADDRESS1, ADDRESS2,defaultValue, 0);
+ ruleConditionalTransfer.approveTransferRequest(transferRequestInput, 0, true);
+
+ // Act
+ vm.expectEmit(true, true, true, true);
+ emit transferProcessed(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0);
+ vm.prank(ADDRESS1);
+ CMTAT_CONTRACT.transfer(ADDRESS2,defaultValue);
+
+ // Assert
+ resUint256 = CMTAT_CONTRACT.balanceOf(ADDRESS1);
+ assertEq(resUint256, ADDRESS1_BALANCE_INIT -defaultValue);
+ resUint256 = CMTAT_CONTRACT.balanceOf(ADDRESS2);
+ assertEq(resUint256, ADDRESS2_BALANCE_INIT +defaultValue);
+ resUint256 = CMTAT_CONTRACT.balanceOf(ADDRESS3);
+ assertEq(resUint256, 33);
+ }
+
+ function testCanMakeAPartialTransferIfPartiallyApproved() public {
+
+ // Arrange
+ _createTransferRequest();
+
+ uint256 partialValue = 5;
+ bytes32 key = keccak256(abi.encode(ADDRESS1, ADDRESS2,partialValue));
+ // Act
+ vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS);
+ vm.expectEmit(true, true, true, true);
+ emit transferApproved(key, ADDRESS1, ADDRESS2, partialValue, 1);
+ emit transferDenied(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0);
+ ruleConditionalTransfer.approveTransferRequest(transferRequestInput, partialValue, true);
+
+ // Act
+ vm.expectEmit(true, true, true, true);
+ emit transferProcessed(key, ADDRESS1, ADDRESS2, partialValue, 1);
+ vm.prank(ADDRESS1);
+ CMTAT_CONTRACT.transfer(ADDRESS2,partialValue);
+
+ // Assert
+ resUint256 = CMTAT_CONTRACT.balanceOf(ADDRESS1);
+ assertEq(resUint256, ADDRESS1_BALANCE_INIT - partialValue);
+ resUint256 = CMTAT_CONTRACT.balanceOf(ADDRESS2);
+ assertEq(resUint256, ADDRESS2_BALANCE_INIT + partialValue);
+ resUint256 = CMTAT_CONTRACT.balanceOf(ADDRESS3);
+ assertEq(resUint256, 33);
+ }
+
+ function testCannotMakeAWholeTransferIfPartiallyApproved() public {
+ // Arrange
+ _createTransferRequest();
+ uint256 partialValue = 5;
+ bytes32 key = keccak256(abi.encode(ADDRESS1, ADDRESS2,partialValue));
+ // Act
+ vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS);
+ vm.expectEmit(true, true, true, true);
+ emit transferApproved(key, ADDRESS1, ADDRESS2, partialValue, 1);
+ emit transferDenied(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0);
+ ruleConditionalTransfer.approveTransferRequest(transferRequestInput, partialValue, true);
+
+ // Act
+ vm.expectRevert(
+ abi.encodeWithSelector(Errors.CMTAT_InvalidTransfer.selector, ADDRESS1, ADDRESS2, defaultValue));
+ vm.prank(ADDRESS1);
+ CMTAT_CONTRACT.transfer(ADDRESS2, defaultValue);
+ }
+
+
+ function testCannotMakeATransferIfDelayExceeded() public {
+ // Arrange
+ vm.prank(ADDRESS1);
+ // Act
+ bytes32 key = keccak256(abi.encode(ADDRESS1, ADDRESS2,defaultValue));
+ ruleConditionalTransfer.createTransferRequest(ADDRESS2,defaultValue);
+
+ // Act
+ vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS);
+ vm.expectEmit(true, true, true, true);
+ emit transferApproved(key, ADDRESS1, ADDRESS2,defaultValue, 0);
+ ruleConditionalTransfer.approveTransferRequest(transferRequestInput, 0,true);
+
+ // +30 days and one second
+ vm.warp(block.timestamp + 2592001);
+ // Act
+ vm.expectRevert(
+ abi.encodeWithSelector(Errors.CMTAT_InvalidTransfer.selector, ADDRESS1, ADDRESS2,defaultValue));
+ vm.prank(ADDRESS1);
+ CMTAT_CONTRACT.transfer(ADDRESS2,defaultValue);
+ }
+
+ function testCannotMakeATransferIfDelayJustInTime() public {
+ // Arrange
+ _createTransferRequest();
+
+ // Act
+ vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS);
+ vm.expectEmit(true, true, true, true);
+ emit transferApproved(defaultKey, ADDRESS1, ADDRESS2,defaultValue, 0);
+ ruleConditionalTransfer.approveTransferRequest(transferRequestInput, 0,true);
+ // 30 days
+ vm.warp(block.timestamp + 2592000);
+ // Act
+ vm.prank(ADDRESS1);
+ CMTAT_CONTRACT.transfer(ADDRESS2,defaultValue);
+ }
+
+ function testCanSetTimeLimitWithTransferExceeded() public {
+ TIME_LIMIT memory timeLimit_ = TIME_LIMIT({
+ timeLimitToApprove: 1 days,
+ timeLimitToTransfer: 1 days
+ });
+ // Act
+ vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS);
+ ruleConditionalTransfer.setTimeLimit(timeLimit_);
+ // Arrange
+ _createTransferRequest();
+ vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS);
+ ruleConditionalTransfer.approveTransferRequest(transferRequestInput, 0,true);
+
+
+ // Assert
+ // Timeout
+ // >1 days
+ vm.warp(block.timestamp + 1 days + 1 seconds);
+
+ vm.expectRevert(
+ abi.encodeWithSelector(Errors.CMTAT_InvalidTransfer.selector, ADDRESS1, ADDRESS2,defaultValue));
+ vm.prank(ADDRESS1);
+ CMTAT_CONTRACT.transfer(ADDRESS2,defaultValue);
+
+ }
+
+ function testCanMintWithoutApproval() public {
+ // Act
+ vm.prank(DEFAULT_ADMIN_ADDRESS);
+ CMTAT_CONTRACT.mint(ADDRESS1, 11);
+
+ // Assert
+ resUint256 = CMTAT_CONTRACT.balanceOf(ADDRESS1);
+ assertEq(resUint256, ADDRESS1_BALANCE_INIT + 11);
+ }
+
+ function testCanBurnWithoutApproval() public {
+ // Act
+ vm.prank(DEFAULT_ADMIN_ADDRESS);
+ CMTAT_CONTRACT.burn(ADDRESS1,defaultValue, "test");
+
+ // Assert
+ resUint256 = CMTAT_CONTRACT.balanceOf(ADDRESS1);
+ assertEq(resUint256, ADDRESS1_BALANCE_INIT - defaultValue);
+ }
+
+ function testCannotMintWithoutApproval() public {
+ ISSUANCE memory issuanceOption_ = ISSUANCE({
+ authorizedMintWithoutApproval:false,
+ authorizedBurnWithoutApproval:true
+ });
+ vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS);
+ ruleConditionalTransfer.setIssuanceOptions(issuanceOption_);
+ // Act
+ vm.prank(DEFAULT_ADMIN_ADDRESS);
+ vm.expectRevert(
+ abi.encodeWithSelector(Errors.CMTAT_InvalidTransfer.selector, ZERO_ADDRESS , ADDRESS1, 11));
+ CMTAT_CONTRACT.mint(ADDRESS1, 11);
+ }
+
+ function testCannotBurnWithoutApproval() public {
+ ISSUANCE memory issuanceOption_ = ISSUANCE({
+ authorizedMintWithoutApproval:true,
+ authorizedBurnWithoutApproval:false
+ });
+ vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS);
+ ruleConditionalTransfer.setIssuanceOptions(issuanceOption_);
+ // Act
+ vm.prank(DEFAULT_ADMIN_ADDRESS);
+ vm.expectRevert(
+ abi.encodeWithSelector(Errors.CMTAT_InvalidTransfer.selector, ADDRESS1, ZERO_ADDRESS, defaultValue));
+ CMTAT_CONTRACT.burn(ADDRESS1,defaultValue, "test");
+ }
+
+ function testAutomaticTransferIfOptionsSet() public {
+ AUTOMATIC_TRANSFER memory automaticTransferTest = AUTOMATIC_TRANSFER({
+ isActivate:true,
+ cmtat: CMTAT_CONTRACT
+ });
+ vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS);
+ ruleConditionalTransfer.setAutomaticTransfer(automaticTransferTest);
+
+ // Aproval
+ vm.prank(ADDRESS1);
+ CMTAT_CONTRACT.approve(address(ruleConditionalTransfer), defaultValue);
+
+ // Arrange
+ _createTransferRequest();
+
+ // Act
+ vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS);
+ vm.expectEmit(true, true, true, true);
+ emit transferApproved(defaultKey, ADDRESS1, ADDRESS2,defaultValue, 0);
+ vm.expectEmit(true, true, true, true);
+ emit transferProcessed(defaultKey, ADDRESS1, ADDRESS2,defaultValue, 0);
+ ruleConditionalTransfer.approveTransferRequest(transferRequestInput, 0,true);
+ }
+
+ function testCanTransferIfAutomaticApprovalSetAndTimeExceeds() public {
+ AUTOMATIC_APPROVAL memory automaticApproval_ = AUTOMATIC_APPROVAL({
+ isActivate: true,
+ timeLimitBeforeAutomaticApproval: 90 days
+ });
+ vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS);
+ ruleConditionalTransfer.setAutomaticApproval(automaticApproval_);
+
+ // Arrange
+ _createTransferRequest();
+
+ vm.warp(block.timestamp + 90 days);
+ // Act
+ vm.prank(ADDRESS1);
+ vm.expectEmit(true, true, true, true);
+ emit transferProcessed(defaultKey, ADDRESS1, ADDRESS2,defaultValue, 0);
+ CMTAT_CONTRACT.transfer(ADDRESS2,defaultValue);
+ }
+
+ function testCannotTransferIfAutomaticApprovalSetAndTimeNotExceeds() public {
+ AUTOMATIC_APPROVAL memory automaticApproval_ = AUTOMATIC_APPROVAL({
+ isActivate: true,
+ timeLimitBeforeAutomaticApproval: 90 days
+ });
+ vm.prank(CONDITIONAL_TRANSFER_OPERATOR_ADDRESS);
+ ruleConditionalTransfer.setAutomaticApproval(automaticApproval_);
+
+ // Arrange
+ _createTransferRequest();
+
+
+ vm.warp(block.timestamp + 92 days);
+ // Act
+ vm.prank(ADDRESS1);
+ vm.expectRevert(
+ abi.encodeWithSelector(Errors.CMTAT_InvalidTransfer.selector, ADDRESS1, ADDRESS2, defaultValue));
+ CMTAT_CONTRACT.transfer(ADDRESS2,defaultValue);
+ }
+}
diff --git a/test/RuleConditionalTransfer/RuleConditionalTransferAccessControl.t.sol b/test/RuleConditionalTransfer/RuleConditionalTransferAccessControl.t.sol
index fee118a..f9a18c7 100644
--- a/test/RuleConditionalTransfer/RuleConditionalTransferAccessControl.t.sol
+++ b/test/RuleConditionalTransfer/RuleConditionalTransferAccessControl.t.sol
@@ -100,6 +100,24 @@ contract RuleConditionalTransferAccessControl is Test, HelperContract {
ruleConditionalTransfer.approveTransferRequestWithId(0, true);
}
+ function testCannotAttackerResetARequest() public {
+ _createTransferRequest();
+
+ vm.expectRevert(
+ abi.encodeWithSelector(AccessControlUnauthorizedAccount.selector, ATTACKER, RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE));
+ vm.prank(ATTACKER);
+ ruleConditionalTransfer.resetRequestStatus(0);
+ }
+
+ function testCannotAttackerCreateTransferRequestWithApproval() public {
+ vm.expectRevert(
+ abi.encodeWithSelector(AccessControlUnauthorizedAccount.selector, ATTACKER, RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE));
+ vm.prank(ATTACKER);
+ ruleConditionalTransfer.createTransferRequestWithApproval(transferRequestInput);
+ }
+
+ /*** Batch */
+
function testCannotAttackerApproveBatchWithIdARequestCreatedByTokenHolder() public {
_createTransferRequest();
uint256[] memory ids = new uint256[](1);
@@ -112,20 +130,31 @@ contract RuleConditionalTransferAccessControl is Test, HelperContract {
ruleConditionalTransfer.approveTransferRequestBatchWithId(ids, isApproveds);
}
- function testCannotAttackerResetARequest() public {
- _createTransferRequest();
-
+ function testCannotAttackerApproveBatchRequestCreatedByTokenHolder() public {
+ TransferRequestKeyElement[] memory keyElements = new TransferRequestKeyElement[](0);
+ uint256[] memory partialValues = new uint256[](0);
+ bool[] memory boolIsApproved = new bool[](0);
vm.expectRevert(
abi.encodeWithSelector(AccessControlUnauthorizedAccount.selector, ATTACKER, RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE));
vm.prank(ATTACKER);
- ruleConditionalTransfer.resetRequestStatus(0);
+ ruleConditionalTransfer.approveTransferRequestBatch(keyElements, partialValues, boolIsApproved);
}
- function testCannotAttackerCreateTransferRequestWithApproval() public {
+ function testCannotAttackerResetBatch() public {
+ uint256[] memory ids = new uint256[](0);
+ bool[] memory boolIsApproved = new bool[](0);
vm.expectRevert(
abi.encodeWithSelector(AccessControlUnauthorizedAccount.selector, ATTACKER, RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE));
vm.prank(ATTACKER);
- ruleConditionalTransfer.createTransferRequestWithApproval(transferRequestInput);
+ ruleConditionalTransfer.approveTransferRequestBatchWithId(ids, boolIsApproved);
+ }
+
+ function testCannotAttackerCreateTransferRequestWithApprovalBatch() public {
+ TransferRequestKeyElement[] memory keyElements = new TransferRequestKeyElement[](0);
+ vm.expectRevert(
+ abi.encodeWithSelector(AccessControlUnauthorizedAccount.selector, ATTACKER, RULE_CONDITIONAL_TRANSFER_OPERATOR_ROLE));
+ vm.prank(ATTACKER);
+ ruleConditionalTransfer.createTransferRequestWithApprovalBatch(keyElements);
}
/******** OPTIONS CONFIGURATION *********/
diff --git a/test/RuleConditionalTransfer/RuleConditionalTransferReset.t.sol b/test/RuleConditionalTransfer/RuleConditionalTransferReset.t.sol
index e7c80fa..5083279 100644
--- a/test/RuleConditionalTransfer/RuleConditionalTransferReset.t.sol
+++ b/test/RuleConditionalTransfer/RuleConditionalTransferReset.t.sol
@@ -158,6 +158,20 @@ contract RuleConditionalTransferResetTest is Test, HelperContract {
vm.expectEmit(true, true, true, true);
emit transferReset(defaultKey, ADDRESS1, ADDRESS2, defaultValue, 0);
ruleConditionalTransfer.cancelTransferRequest(0);
+
+ // Can create a new request
+ // Id different from 0
+ vm.prank(ADDRESS1);
+ // Act
+ vm.expectEmit(true, true, true, true);
+ emit transferWaiting(key2, ADDRESS1, ADDRESS2, value2, 1);
+ ruleConditionalTransfer.createTransferRequest(ADDRESS2, value2);
+
+ // Can be cancel again
+ vm.prank(ADDRESS1);
+ vm.expectEmit(true, true, true, true);
+ emit transferReset(key2, ADDRESS1, ADDRESS2, value2, 1);
+ ruleConditionalTransfer.cancelTransferRequest(1);
}
function testHolderCanBatchResetHisRequest() public {
@@ -282,6 +296,14 @@ contract RuleConditionalTransferResetTest is Test, HelperContract {
assertEq(transferRequest.to, ADDRESS2);
assertEq(transferRequest.value, defaultValue);
assertEq(uint256(transferRequest.status), uint256(STATUS.WAIT));
+
+
+ // Id different from 0
+ vm.prank(ADDRESS1);
+ // Act
+ vm.expectEmit(true, true, true, true);
+ emit transferWaiting(key2, ADDRESS1, ADDRESS2, value2, 1);
+ ruleConditionalTransfer.createTransferRequest(ADDRESS2, value2);
}
function testCanBatchResetADeniedRequestCreatedByHolder() public {