Skip to content

Commit cdd39c6

Browse files
authored
Audit - Feb 2025 - 7.2.1 Execution and CallType Mode Modifier (#65)
* Audit - Feb 2025 - 7.2.1 Execution and CallType Mode Modifier * Updated exeution and typecall mode for new modifiers * Added validation modifier for exection mode default * Fix mode update in some enforcers
1 parent 7288b4f commit cdd39c6

File tree

58 files changed

+876
-707
lines changed

Some content is hidden

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

58 files changed

+876
-707
lines changed

documents/CaveatEnforcers.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ The order in which the caveat hooks are called can vary depending on the `Delega
2121

2222
### Execution Modes
2323

24-
Enforcers can target a specific execution mode: **single** or **batch**. Because execution call data is encoded differently for each mode, you can use modifiers like `onlySingleExecutionMode` or `onlyBatchExecutionMode` to restrict an enforcer to the desired mode, using a different would revert.
24+
Enforcers can target specific call type modes: **single** or **batch**, and execution types: **default** or **revert**. Because execution call data is encoded differently for each mode, you can use modifiers like `onlySingleCallTypeMode`, `onlyBatchCallTypeMode` to restrict a call type, or `onlyDefaultExecutionMode`, `onlyTryExecutionMode` to restrict an execution type, it is possible to combine an execution mode modifier with a call type modifier.
2525

2626
---
2727

lcov.info

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -747,8 +747,8 @@ FNDA:74,CaveatEnforcer.onlySingleExecutionMode
747747
DA:27,74
748748
BRDA:27,0,0,-
749749
BRDA:27,0,1,74
750-
FN:34,CaveatEnforcer.onlyBatchExecutionMode
751-
FNDA:0,CaveatEnforcer.onlyBatchExecutionMode
750+
FN:34,CaveatEnforcer.onlyBatchCallTypeMode
751+
FNDA:0,CaveatEnforcer.onlyBatchCallTypeMode
752752
DA:35,0
753753
BRDA:35,1,0,-
754754
BRDA:35,1,1,-

src/enforcers/AllowedCalldataEnforcer.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -40,7 +40,7 @@ contract AllowedCalldataEnforcer is CaveatEnforcer {
4040
public
4141
pure
4242
override
43-
onlySingleExecutionMode(_mode)
43+
onlySingleCallTypeMode(_mode)
4444
{
4545
// Ensure that the first two term values are valid and at least 1 byte for value_
4646
uint256 dataStart_;

src/enforcers/AllowedMethodsEnforcer.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ contract AllowedMethodsEnforcer is CaveatEnforcer {
3636
public
3737
pure
3838
override
39-
onlySingleExecutionMode(_mode)
39+
onlySingleCallTypeMode(_mode)
4040
{
4141
(,, bytes calldata callData_) = _executionCallData.decodeSingle();
4242

src/enforcers/AllowedTargetsEnforcer.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ contract AllowedTargetsEnforcer is CaveatEnforcer {
3535
public
3636
pure
3737
override
38-
onlySingleExecutionMode(_mode)
38+
onlySingleCallTypeMode(_mode)
3939
{
4040
(address target_,,) = _executionCallData.decodeSingle();
4141

src/enforcers/CaveatEnforcer.sol

Lines changed: 34 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ pragma solidity 0.8.23;
44
import { ModeLib } from "@erc7579/lib/ModeLib.sol";
55

66
import { ICaveatEnforcer } from "../interfaces/ICaveatEnforcer.sol";
7-
import { ModeCode } from "../utils/Types.sol";
8-
import { CALLTYPE_SINGLE, CALLTYPE_BATCH } from "../utils/Constants.sol";
7+
import { ModeCode, ExecType } from "../utils/Types.sol";
8+
import { CALLTYPE_SINGLE, CALLTYPE_BATCH, EXECTYPE_DEFAULT, EXECTYPE_TRY } from "../utils/Constants.sol";
99

1010
/**
1111
* @title CaveatEnforcer
@@ -27,18 +27,44 @@ abstract contract CaveatEnforcer is ICaveatEnforcer {
2727
function afterAllHook(bytes calldata, bytes calldata, ModeCode, bytes calldata, bytes32, address, address) public virtual { }
2828

2929
/**
30-
* @dev Require the function call to be in single execution mode
30+
* @dev Require the function call to be in single call type
3131
*/
32-
modifier onlySingleExecutionMode(ModeCode _mode) {
33-
require(ModeLib.getCallType(_mode) == CALLTYPE_SINGLE, "CaveatEnforcer:invalid-call-type");
32+
modifier onlySingleCallTypeMode(ModeCode _mode) {
33+
{
34+
require(ModeLib.getCallType(_mode) == CALLTYPE_SINGLE, "CaveatEnforcer:invalid-call-type");
35+
}
3436
_;
3537
}
3638

3739
/**
38-
* @dev Require the function call to be in batch execution mode
40+
* @dev Require the function call to be in batch call type
3941
*/
40-
modifier onlyBatchExecutionMode(ModeCode _mode) {
41-
require(ModeLib.getCallType(_mode) == CALLTYPE_BATCH, "CaveatEnforcer:invalid-call-type");
42+
modifier onlyBatchCallTypeMode(ModeCode _mode) {
43+
{
44+
require(ModeLib.getCallType(_mode) == CALLTYPE_BATCH, "CaveatEnforcer:invalid-call-type");
45+
}
46+
_;
47+
}
48+
49+
/**
50+
* @dev Require the function call to be in default execution mode
51+
*/
52+
modifier onlyDefaultExecutionMode(ModeCode _mode) {
53+
{
54+
(, ExecType _execType,,) = _mode.decode();
55+
require(_execType == EXECTYPE_DEFAULT, "CaveatEnforcer:invalid-execution-type");
56+
}
57+
_;
58+
}
59+
60+
/**
61+
* @dev Require the function call to be in try execution mode
62+
*/
63+
modifier onlyTryExecutionMode(ModeCode _mode) {
64+
{
65+
(, ExecType _execType,,) = _mode.decode();
66+
require(_execType == EXECTYPE_TRY, "CaveatEnforcer:invalid-execution-type");
67+
}
4268
_;
4369
}
4470
}

src/enforcers/ERC20PeriodTransferEnforcer.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ contract ERC20PeriodTransferEnforcer is CaveatEnforcer {
126126
)
127127
public
128128
override
129-
onlySingleExecutionMode(_mode)
129+
onlySingleCallTypeMode(_mode)
130130
{
131131
_validateAndConsumeTransfer(_terms, _executionCallData, _delegationHash, _redeemer);
132132
}

src/enforcers/ERC20StreamingEnforcer.sol

Lines changed: 5 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -59,40 +59,21 @@ contract ERC20StreamingEnforcer is CaveatEnforcer {
5959

6060
/**
6161
* @notice Retrieves the current available allowance for a specific delegation.
62-
* @param _delegationHash The hash of the delegation being queried.
6362
* @param _delegationManager The address of the delegation manager.
64-
* @param _terms 148 packed bytes where:
65-
* - 20 bytes: ERC20 token address.
66-
* - 32 bytes: initial amount.
67-
* - 32 bytes: max amount.
68-
* - 32 bytes: amount per second.
69-
* - 32 bytes: start time for the streaming allowance.
63+
* @param _delegationHash The hash of the delegation being queried.
7064
* @return availableAmount_ The number of tokens that are currently spendable
7165
* under this streaming allowance (capped by `maxAmount`).
7266
*/
7367
function getAvailableAmount(
74-
bytes32 _delegationHash,
7568
address _delegationManager,
76-
bytes calldata _terms
69+
bytes32 _delegationHash
7770
)
7871
external
7972
view
8073
returns (uint256 availableAmount_)
8174
{
82-
StreamingAllowance memory storedAllowance_ = streamingAllowances[_delegationManager][_delegationHash];
83-
if (storedAllowance_.spent != 0) return _getAvailableAmount(storedAllowance_);
84-
85-
// Not yet initialized: simulate using provided terms.
86-
(, uint256 initialAmount_, uint256 maxAmount_, uint256 amountPerSecond_, uint256 startTime_) = getTermsInfo(_terms);
87-
88-
StreamingAllowance memory allowance_ = StreamingAllowance({
89-
initialAmount: initialAmount_,
90-
maxAmount: maxAmount_,
91-
amountPerSecond: amountPerSecond_,
92-
startTime: startTime_,
93-
spent: 0
94-
});
95-
return _getAvailableAmount(allowance_);
75+
StreamingAllowance storage allowance_ = streamingAllowances[_delegationManager][_delegationHash];
76+
availableAmount_ = _getAvailableAmount(allowance_);
9677
}
9778

9879
/**
@@ -120,7 +101,7 @@ contract ERC20StreamingEnforcer is CaveatEnforcer {
120101
)
121102
public
122103
override
123-
onlySingleExecutionMode(_mode)
104+
onlySingleCallTypeMode(_mode)
124105
{
125106
_validateAndConsumeAllowance(_terms, _executionCallData, _delegationHash, _redeemer);
126107
}

src/enforcers/ERC20TransferAmountEnforcer.sol

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,8 @@ contract ERC20TransferAmountEnforcer is CaveatEnforcer {
4646
)
4747
public
4848
override
49-
onlySingleExecutionMode(_mode)
49+
onlySingleCallTypeMode(_mode)
50+
onlyDefaultExecutionMode(_mode)
5051
{
5152
(uint256 limit_, uint256 spent_) = _validateAndIncrease(_terms, _executionCallData, _delegationHash);
5253
emit IncreasedSpentMap(msg.sender, _redeemer, _delegationHash, limit_, spent_);

src/enforcers/ERC721TransferEnforcer.sol

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ contract ERC721TransferEnforcer is CaveatEnforcer {
3232
public
3333
virtual
3434
override
35-
onlySingleExecutionMode(_mode)
35+
onlySingleCallTypeMode(_mode)
3636
{
3737
(address permittedContract_, uint256 permittedTokenId_) = getTermsInfo(_terms);
3838
(address target_,, bytes calldata callData_) = ExecutionLib.decodeSingle(_executionCallData);

0 commit comments

Comments
 (0)