feat: Clear transient storage after swap call

- This was originally remaining if no callback was performed, possible resulting in unexpected behaviour and an increased attack surface.
- Also specify nonzero slot for transient storage in order to reduce the risk of dangerous slot collision.
This commit is contained in:
TAMARA LIPOWSKI
2025-04-25 21:39:09 -04:00
parent 732450670f
commit 1b003dc483

View File

@@ -23,6 +23,10 @@ error Dispatcher__InvalidDataLength();
contract Dispatcher { contract Dispatcher {
mapping(address => bool) public executors; mapping(address => bool) public executors;
// keccak256("Dispatcher#CURRENTLY_SWAPPING_EXECUTOR_SLOT")
uint256 private constant _CURRENTLY_SWAPPING_EXECUTOR_SLOT =
0x098a7a3b47801589e8cdf9ec791b93ad44273246946c32ef1fc4dbe45390c80e;
event ExecutorSet(address indexed executor); event ExecutorSet(address indexed executor);
event ExecutorRemoved(address indexed executor); event ExecutorRemoved(address indexed executor);
@@ -63,7 +67,7 @@ contract Dispatcher {
} }
assembly { assembly {
tstore(0, executor) tstore(_CURRENTLY_SWAPPING_EXECUTOR_SLOT, executor)
} }
// slither-disable-next-line controlled-delegatecall,low-level-calls,calls-loop // slither-disable-next-line controlled-delegatecall,low-level-calls,calls-loop
@@ -71,6 +75,11 @@ contract Dispatcher {
abi.encodeWithSelector(IExecutor.swap.selector, amount, data) abi.encodeWithSelector(IExecutor.swap.selector, amount, data)
); );
// Clear transient storage in case no callback was performed
assembly {
tstore(_CURRENTLY_SWAPPING_EXECUTOR_SLOT, 0)
}
if (!success) { if (!success) {
revert( revert(
string( string(
@@ -91,7 +100,7 @@ contract Dispatcher {
{ {
address executor; address executor;
assembly { assembly {
executor := tload(0) executor := tload(_CURRENTLY_SWAPPING_EXECUTOR_SLOT)
} }
if (!executors[executor]) { if (!executors[executor]) {
@@ -115,7 +124,7 @@ contract Dispatcher {
// to prevent multiple callbacks // to prevent multiple callbacks
assembly { assembly {
tstore(0, 0) tstore(_CURRENTLY_SWAPPING_EXECUTOR_SLOT, 0)
} }
// this is necessary because the delegatecall will prepend extra bytes we don't want like the length and prefix // this is necessary because the delegatecall will prepend extra bytes we don't want like the length and prefix