@@ -8,14 +8,17 @@ import { ModeCode } from "../utils/Types.sol";
88
99/**
1010 * @title ERC721BalanceChangeEnforcer
11- * @dev This contract enforces that the ERC721 token balance of a recipient has changed by at least the specified amount
12- * after the execution, measured between the `beforeHook` and `afterHook` calls, regardless of what the execution is.
13- * The change can be either an increase or decrease based on the `shouldBalanceIncrease` flag.
11+ * @dev This contract allows setting up some guardrails around balance changes. By specifying an amount and a direction
12+ * (decrease/increase), one can enforce a maximum decrease or minimum increase in after-execution balance.
13+ * The change can be either a decrease or increase based on the `isDecrease` flag.
14+ * @dev This contract has no enforcement of how the balance changes. It's meant to be used alongside additional enforcers to
15+ * create granular permissions.
1416 * @dev This enforcer operates only in default execution mode.
15- * @dev Security Notice: This enforcer tracks balance changes by comparing the recipient's balance before and after execution.
16- * Since enforcers watching the same recipient share state, a single balance modification may satisfy multiple enforcers
17- * simultaneously. Users should avoid tracking the same recipient's balance on multiple enforcers in a single delegation chain to
18- * prevent unintended behavior.
17+ * @dev Security Notice: This enforcer tracks balance changes by comparing the recipient's balance before and after execution. Since
18+ * enforcers watching the same recipient share state, a single balance modification may satisfy multiple enforcers simultaneously.
19+ * Users should avoid tracking the same recipient's balance on multiple enforcers in a single delegation chain to prevent unintended
20+ * behavior. Given its potential for concurrent condition fulfillment, use this enforcer at your own risk and ensure it aligns with
21+ * your intended security model.
1922 */
2023contract ERC721BalanceChangeEnforcer is CaveatEnforcer {
2124 ////////////////////////////// State //////////////////////////////
@@ -51,10 +54,11 @@ contract ERC721BalanceChangeEnforcer is CaveatEnforcer {
5154 /**
5255 * @notice This function caches the delegator's ERC721 token balance before the delegation is executed.
5356 * @param _terms 73 bytes where:
54- * - first byte: boolean indicating if the balance should increase
57+ * - first byte: boolean indicating if the balance should decrease
5558 * - next 20 bytes: address of the ERC721 token
5659 * - next 20 bytes: address of the recipient
57- * - next 32 bytes: amount the balance should change by
60+ * - next 32 bytes: balance change guardrail amount (i.e., minimum increase OR maximum decrease, depending on
61+ * isDecrease)
5862 * @param _mode The execution mode. (Must be Default execType)
5963 * @param _delegationHash The hash of the delegation.
6064 */
@@ -80,12 +84,13 @@ contract ERC721BalanceChangeEnforcer is CaveatEnforcer {
8084 }
8185
8286 /**
83- * @notice This function enforces that the delegator's ERC721 token balance has changed by at least the amount provided .
87+ * @notice This function enforces that the delegator's ERC721 token balance has changed by the expected amount .
8488 * @param _terms 73 bytes where:
85- * - first byte: boolean indicating if the balance should increase
89+ * - first byte: boolean indicating if the balance should decrease
8690 * - next 20 bytes: address of the ERC721 token
8791 * - next 20 bytes: address of the recipient
88- * - next 32 bytes: amount the balance should change by
92+ * - next 32 bytes: balance change guardrail amount (i.e., minimum increase OR maximum decrease, depending on
93+ * isDecrease)
8994 * @param _delegationHash The hash of the delegation.
9095 */
9196 function afterHook (
@@ -100,32 +105,33 @@ contract ERC721BalanceChangeEnforcer is CaveatEnforcer {
100105 public
101106 override
102107 {
103- (bool shouldBalanceIncrease_ , address token_ , address recipient_ , uint256 amount_ ) = getTermsInfo (_terms);
108+ (bool isDecrease_ , address token_ , address recipient_ , uint256 amount_ ) = getTermsInfo (_terms);
104109 bytes32 hashKey_ = _getHashKey (msg .sender , token_, recipient_, _delegationHash);
105110 delete isLocked[hashKey_];
106111 uint256 balance_ = IERC721 (token_).balanceOf (recipient_);
107- if (shouldBalanceIncrease_) {
108- require (balance_ >= balanceCache[hashKey_] + amount_, "ERC721BalanceChangeEnforcer:insufficient-balance-increase " );
109- } else {
112+ if (isDecrease_) {
110113 require (balance_ >= balanceCache[hashKey_] - amount_, "ERC721BalanceChangeEnforcer:exceeded-balance-decrease " );
114+ } else {
115+ require (balance_ >= balanceCache[hashKey_] + amount_, "ERC721BalanceChangeEnforcer:insufficient-balance-increase " );
111116 }
112117 }
113118
114119 /**
115120 * @notice Decodes the terms used in this CaveatEnforcer.
116121 * @param _terms Encoded data that is used during the execution hooks.
117- * @return shouldBalanceIncrease_ Boolean indicating if the balance should increase (true) or decrease (false).
122+ * @return isDecrease_ Boolean indicating if the balance should decrease (true) or increase (false).
118123 * @return token_ The address of the ERC721 token.
119124 * @return recipient_ The address of the recipient of the token.
120- * @return amount_ The amount the balance should change by.
125+ * @return amount_ Balance change guardrail amount (i.e., minimum increase OR maximum decrease, depending on
126+ * isDecrease)
121127 */
122128 function getTermsInfo (bytes calldata _terms )
123129 public
124130 pure
125- returns (bool shouldBalanceIncrease_ , address token_ , address recipient_ , uint256 amount_ )
131+ returns (bool isDecrease_ , address token_ , address recipient_ , uint256 amount_ )
126132 {
127133 require (_terms.length == 73 , "ERC721BalanceChangeEnforcer:invalid-terms-length " );
128- shouldBalanceIncrease_ = _terms[0 ] != 0 ;
134+ isDecrease_ = _terms[0 ] != 0 ;
129135 token_ = address (bytes20 (_terms[1 :21 ]));
130136 recipient_ = address (bytes20 (_terms[21 :41 ]));
131137 amount_ = uint256 (bytes32 (_terms[41 :]));
0 commit comments