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:
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user