Skip to content

Commit 461d32f

Browse files
authored
Merge pull request #52 from CMTA/update-cmtat3.0
Update RuleEngine to use cmtat3.0-v5rc0
2 parents b03f2e9 + 014d943 commit 461d32f

44 files changed

Lines changed: 430 additions & 169 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

CHANGELOG.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,19 @@ Please follow [https://changelog.md/](https://changelog.md/) conventions.
1717
- Update surya doc by running the 3 scripts in [./doc/script](./doc/script)
1818
- Update changelog
1919

20+
21+
22+
## v2.1.0
23+
24+
- Update RuleEngine to CMTAT v3.0.0-rc5
25+
26+
- Add "partial" support of spender check introduced with CMTAT v3.0.0-rc5
27+
28+
- Change several functions
29+
- `operateOnTransfer `-> `transferred(...)`
30+
31+
- Add functions `detectTransferRestrictionFrom` and `canTransferFrom`
32+
2033
## v2.0.5
2134

2235
- Fix a bug present in the Conditional Transfer rule and improve the corresponding tests.

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ The RuleEngine is an external contract used to apply transfer restrictions to an
1111
The toolchain includes the following components, where the versions are the latest ones that we tested:
1212

1313
- Foundry [v1.9.4](https://github.com/foundry-rs/forge-std/releases/tag/v1.9.4)
14-
- Solidity 0.8.27 (via solc-js)
15-
- OpenZeppelin Contracts (submodule) [v5.0.2](https://github.com/OpenZeppelin/openzeppelin-contracts/releases/tag/v5.0.2)
16-
- CMTAT [v2.5.1](https://github.com/CMTA/CMTAT/releases/tag/v2.5.1)
14+
- Solidity 0.8.30 (via solc-js)
15+
- OpenZeppelin Contracts (submodule) [v5.3.0](https://github.com/OpenZeppelin/openzeppelin-contracts/releases/tag/v5.3.0)
16+
- CMTAT [v3.0.0](https://github.com/CMTA/CMTAT/releases/tag/v3.0.0)
1717

1818
## How to include it
1919

@@ -134,7 +134,7 @@ Here a summary of the main documentation
134134
| Functionalities | [doc/functionalities.pdf](./doc/functionalities.pdf) |
135135
| Surya report | [doc/surya](./doc/surya/) |
136136

137-
See also [Taurus - Token Transfer Management: How to Apply Restrictions with CMTAT and ERC-1404](https://www.taurushq.com/blog/token-transfer-management-how-to-apply-restrictions-with-cmtat-and-erc-1404/)
137+
See also [Taurus - Token Transfer Management: How to Apply Restrictions with CMTAT and ERC-1404](https://www.taurushq.com/blog/token-transfer-management-how-to-apply-restrictions-with-cmtat-and-erc-1404/) (CMTAT v2.4.0)
138138

139139
## Usage
140140

lib/CMTAT

Submodule CMTAT updated 1035 files

lib/openzeppelin-contracts

script/CMTATWithRuleEngineScript.s.sol

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ pragma solidity ^0.8.17;
55

66
import "forge-std/Script.sol";
77
import "../test/HelperContract.sol";
8-
import "src/RuleEngine.sol";
9-
import "src/rules/validation/RuleWhitelist.sol";
8+
import {RuleEngine} from "src/RuleEngine.sol";
9+
import {RuleWhitelist} from "src/rules/validation/RuleWhitelist.sol";
1010

1111
/**
1212
@title Deploy a CMTAT, a RuleWhitelist and a RuleEngine

script/RuleEngineScript.s.sol

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44
pragma solidity ^0.8.17;
55

66
import "forge-std/Script.sol";
7-
import "CMTAT/CMTAT_STANDALONE.sol";
8-
import "src/RuleEngine.sol";
9-
import "src/rules/validation/RuleWhitelist.sol";
10-
import "CMTAT/modules/wrapper/controllers/ValidationModule.sol";
7+
//import "CMTAT/CMTAT_STANDALONE.sol";
8+
import {RuleEngine} from "src/RuleEngine.sol";
9+
import {RuleWhitelist} from "src/rules/validation/RuleWhitelist.sol";
10+
import {ValidationModuleRuleEngine} from "CMTAT/modules/wrapper/extensions/ValidationModule/ValidationModuleRuleEngine.sol";
1111

1212
/**
1313
@title Deploy a RuleWhitelist and a RuleEngine. The CMTAT is considred already deployed
@@ -28,7 +28,7 @@ contract RuleEngineScript is Script {
2828
RULE_ENGINE.addRuleValidation(ruleWhitelist);
2929
// Configure the new ruleEngine for CMTAT
3030
(bool success, ) = address(CMTAT_Address).call(
31-
abi.encodeCall(ValidationModule.setRuleEngine, RULE_ENGINE)
31+
abi.encodeCall(ValidationModuleRuleEngine.setRuleEngine, RULE_ENGINE)
3232
);
3333
require(success);
3434
vm.stopBroadcast();

src/RuleEngine.sol

Lines changed: 87 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,8 @@ pragma solidity ^0.8.20;
55
import "CMTAT/interfaces/engine/IRuleEngine.sol";
66
import "./modules/MetaTxModuleStandalone.sol";
77
import "./modules/RuleEngineOperation.sol";
8-
import "./modules/RuleEngineValidation.sol";
9-
8+
import {RuleEngineValidation} from "./modules/RuleEngineValidation.sol";
9+
import {IRuleValidation} from "./interfaces/IRuleValidation.sol";
1010
/**
1111
* @title Implementation of a ruleEngine as defined by the CMTAT
1212
*/
@@ -16,6 +16,7 @@ contract RuleEngine is
1616
RuleEngineValidation,
1717
MetaTxModuleStandalone
1818
{
19+
1920
/**
2021
* @notice
2122
* Get the current version of the smart contract
@@ -42,21 +43,21 @@ contract RuleEngine is
4243

4344
/**
4445
* @notice Go through all the rule to know if a restriction exists on the transfer
45-
* @param _from the origin address
46-
* @param _to the destination address
47-
* @param _amount to transfer
46+
* @param from the origin address
47+
* @param to the destination address
48+
* @param value to transfer
4849
* @return The restricion code or REJECTED_CODE_BASE.TRANSFER_OK
4950
**/
5051
function detectTransferRestriction(
51-
address _from,
52-
address _to,
53-
uint256 _amount
52+
address from,
53+
address to,
54+
uint256 value
5455
) public view override returns (uint8) {
5556
// Validation
5657
uint8 code = RuleEngineValidation.detectTransferRestrictionValidation(
57-
_from,
58-
_to,
59-
_amount
58+
from,
59+
to,
60+
value
6061
);
6162
if (code != uint8(REJECTED_CODE_BASE.TRANSFER_OK)) {
6263
return code;
@@ -66,7 +67,36 @@ contract RuleEngine is
6667
uint256 rulesLength = _rulesOperation.length;
6768
for (uint256 i = 0; i < rulesLength; ++i) {
6869
uint8 restriction = IRuleValidation(_rulesOperation[i])
69-
.detectTransferRestriction(_from, _to, _amount);
70+
.detectTransferRestriction(from, to, value);
71+
if (restriction > 0) {
72+
return restriction;
73+
}
74+
}
75+
76+
return uint8(REJECTED_CODE_BASE.TRANSFER_OK);
77+
}
78+
79+
function detectTransferRestrictionFrom(
80+
address spender,
81+
address from,
82+
address to,
83+
uint256 value
84+
) public view override returns (uint8) {
85+
// Validation
86+
uint8 code = RuleEngineValidation.detectTransferRestrictionValidationFrom(spender,
87+
from,
88+
to,
89+
value
90+
);
91+
if (code != uint8(REJECTED_CODE_BASE.TRANSFER_OK)) {
92+
return code;
93+
}
94+
95+
// Operation
96+
uint256 rulesLength = _rulesOperation.length;
97+
for (uint256 i = 0; i < rulesLength; ++i) {
98+
uint8 restriction = IRuleValidation(_rulesOperation[i])
99+
.detectTransferRestrictionFrom(spender,from, to, value);
70100
if (restriction > 0) {
71101
return restriction;
72102
}
@@ -77,18 +107,36 @@ contract RuleEngine is
77107

78108
/**
79109
* @notice Validate a transfer
80-
* @param _from the origin address
81-
* @param _to the destination address
82-
* @param _amount to transfer
110+
* @param from the origin address
111+
* @param to the destination address
112+
* @param value to transfer
83113
* @return True if the transfer is valid, false otherwise
84114
**/
85-
function validateTransfer(
86-
address _from,
87-
address _to,
88-
uint256 _amount
115+
function canTransfer(
116+
address from,
117+
address to,
118+
uint256 value
89119
) public view override returns (bool) {
90120
return
91-
detectTransferRestriction(_from, _to, _amount) ==
121+
detectTransferRestriction(from, to, value) ==
122+
uint8(REJECTED_CODE_BASE.TRANSFER_OK);
123+
}
124+
125+
/**
126+
* @notice Validate a transfer
127+
* @param from the origin address
128+
* @param to the destination address
129+
* @param value to transfer
130+
* @return True if the transfer is valid, false otherwise
131+
**/
132+
function canTransferFrom(
133+
address /*spender*/,
134+
address from,
135+
address to,
136+
uint256 value
137+
) public view override returns (bool) {
138+
return
139+
detectTransferRestriction(from, to, value) ==
92140
uint8(REJECTED_CODE_BASE.TRANSFER_OK);
93141
}
94142

@@ -130,19 +178,29 @@ contract RuleEngine is
130178
/*
131179
* @notice function protected by access control
132180
*/
133-
function operateOnTransfer(
181+
function transferred(
182+
address spender,
134183
address from,
135184
address to,
136185
uint256 amount
137-
) external override onlyRole(TOKEN_CONTRACT_ROLE) returns (bool isValid) {
138-
// Validate the transfer
139-
if (
140-
!RuleEngineValidation.validateTransferValidation(from, to, amount)
141-
) {
142-
return false;
143-
}
186+
) external override onlyRole(TOKEN_CONTRACT_ROLE) {
187+
// Validate transfer
188+
require(RuleEngineValidation.canTransferValidation(from, to, amount),RuleEngine_InvalidTransfer(from, to, amount));
189+
190+
// Apply operation on RuleEngine
191+
require(RuleEngineOperation._operateOnTransfer(from, to, amount),RuleEngine_InvalidTransfer(from, to, amount));
192+
}
193+
194+
function transferred(
195+
address from,
196+
address to,
197+
uint256 amount
198+
) external override onlyRole(TOKEN_CONTRACT_ROLE) {
199+
// Validate transfer
200+
require(RuleEngineValidation.canTransferValidation(from, to, amount),RuleEngine_InvalidTransfer(from, to, amount));
201+
144202
// Apply operation on RuleEngine
145-
return RuleEngineOperation._operateOnTransfer(from, to, amount);
203+
require(RuleEngineOperation._operateOnTransfer(from, to, amount),RuleEngine_InvalidTransfer(from, to, amount));
146204
}
147205

148206
/* ============ ACCESS CONTROL ============ */

src/interfaces/IRuleEngineValidation.sol

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,18 @@ interface IRuleEngineValidation {
1313
uint256 _amount
1414
) external view returns (uint8);
1515

16+
function detectTransferRestrictionValidationFrom(
17+
address spender,
18+
address _from,
19+
address _to,
20+
uint256 _amount
21+
) external view returns (uint8);
22+
1623
/**
1724
* @dev Returns true if the transfer is valid, and false otherwise.
1825
*/
19-
function validateTransferValidation(
26+
function canTransferValidationFrom(
27+
address spender,
2028
address _from,
2129
address _to,
2230
uint256 _amount

src/interfaces/IRuleValidation.sol

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,21 @@
22

33
pragma solidity ^0.8.20;
44

5-
import "CMTAT/interfaces/draft-IERC1404/draft-IERC1404Wrapper.sol";
6-
7-
interface IRuleValidation is IERC1404Wrapper {
5+
import {IERC1404Extend} from "CMTAT/interfaces/tokenization/draft-IERC1404.sol";
6+
import {IERC7551Compliance} from "CMTAT/interfaces//tokenization/draft-IERC7551.sol";
7+
interface IRuleValidation is IERC1404Extend, IERC7551Compliance {
88
/**
99
* @dev Returns true if the restriction code exists, and false otherwise.
1010
*/
1111
function canReturnTransferRestrictionCode(
1212
uint8 _restrictionCode
1313
) external view returns (bool);
14+
15+
function detectTransferRestrictionFrom(
16+
address spender,
17+
address _from,
18+
address _to,
19+
uint256 _amount
20+
) external view override returns (uint8);
21+
1422
}

src/modules/RuleEngineInvariantStorage.sol

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ abstract contract RuleEngineInvariantStorage {
88
error RuleEngine_RuleDoNotMatch();
99
error RuleEngine_AdminWithAddressZeroNotAllowed();
1010
error RuleEngine_ArrayIsEmpty();
11+
error RuleEngine_InvalidTransfer(address from, address to, uint256 value);
1112

1213
/// @notice Generate when a rule is added
1314
event AddRule(address indexed rule);

0 commit comments

Comments
 (0)