@@ -64,21 +64,37 @@ abstract contract FallbackManager is SelfAuthorized {
6464 // solhint-disable-next-line no-inline-assembly
6565 /// @solidity memory-safe-assembly
6666 assembly {
67+ // When compiled with the optimizer, the compiler relies on a certain assumptions on how the
68+ // memory is used, therefore we need to guarantee memory safety (keeping the free memory point 0x40 slot intact,
69+ // not going beyond the scratch space, etc)
70+ // Solidity docs: https://docs.soliditylang.org/en/latest/assembly.html#memory-safety
71+ function allocate (length) -> pos {
72+ pos := mload (0x40 )
73+ mstore (0x40 , add (pos, length))
74+ }
75+
6776 let handler := sload (slot)
6877 if iszero (handler) {
6978 return (0 , 0 )
7079 }
71- calldatacopy (0 , 0 , calldatasize ())
80+
81+ let calldataPtr := allocate (calldatasize ())
82+ calldatacopy (calldataPtr, 0 , calldatasize ())
83+
7284 // The msg.sender address is shifted to the left by 12 bytes to remove the padding
7385 // Then the address without padding is stored right after the calldata
74- mstore (calldatasize (), shl (96 , caller ()))
86+ let senderPtr := allocate (20 )
87+ mstore (senderPtr, shl (96 , caller ()))
88+
7589 // Add 20 bytes for the address appended add the end
76- let success := call (gas (), handler, 0 , 0 , add (calldatasize (), 20 ), 0 , 0 )
77- returndatacopy (0 , 0 , returndatasize ())
90+ let success := call (gas (), handler, 0 , calldataPtr, add (calldatasize (), 20 ), 0 , 0 )
91+
92+ let returnDataPtr := allocate (returndatasize ())
93+ returndatacopy (returnDataPtr, 0 , returndatasize ())
7894 if iszero (success) {
79- revert (0 , returndatasize ())
95+ revert (returnDataPtr , returndatasize ())
8096 }
81- return (0 , returndatasize ())
97+ return (returnDataPtr , returndatasize ())
8298 }
8399 }
84100}
0 commit comments