@@ -16,7 +16,10 @@ contract CallsScript is BaseEVMScriptExecutor {
1616
1717 string private constant ERROR_BLACKLISTED_CALL = "EVMCALLS_BLACKLISTED_CALL " ;
1818 string private constant ERROR_INVALID_LENGTH = "EVMCALLS_INVALID_LENGTH " ;
19+
20+ /* This is manually crafted in assembly
1921 string private constant ERROR_CALL_REVERTED = "EVMCALLS_CALL_REVERTED";
22+ */
2023
2124 event LogScriptCall (address indexed sender , address indexed src , address indexed dst );
2225
@@ -25,14 +28,17 @@ contract CallsScript is BaseEVMScriptExecutor {
2528 * @param _script [ specId (uint32) ] many calls with this structure ->
2629 * [ to (address: 20 bytes) ] [ calldataLength (uint32: 4 bytes) ] [ calldata (calldataLength bytes) ]
2730 * @param _blacklist Addresses the script cannot call to, or will revert.
28- * @return always returns empty byte array
31+ * @return Always returns empty byte array
2932 */
3033 function execScript (bytes _script , bytes , address [] _blacklist ) external isInitialized returns (bytes ) {
3134 uint256 location = SCRIPT_START_LOCATION; // first 32 bits are spec id
3235 while (location < _script.length ) {
36+ // Check there's at least address + calldataLength available
37+ require (_script.length - location >= 0x18 , ERROR_INVALID_LENGTH);
38+
3339 address contractAddress = _script.addressAt (location);
3440 // Check address being called is not blacklist
35- for (uint i = 0 ; i < _blacklist.length ; i++ ) {
41+ for (uint256 i = 0 ; i < _blacklist.length ; i++ ) {
3642 require (contractAddress != _blacklist[i], ERROR_BLACKLISTED_CALL);
3743 }
3844
@@ -50,11 +56,43 @@ contract CallsScript is BaseEVMScriptExecutor {
5056
5157 bool success;
5258 assembly {
53- success := call (sub (gas, 5000 ), contractAddress, 0 , calldataStart, calldataLength, 0 , 0 )
54- }
59+ success := call (
60+ sub (gas, 5000 ), // forward gas left - 5000
61+ contractAddress, // address
62+ 0 , // no value
63+ calldataStart, // calldata start
64+ calldataLength, // calldata length
65+ 0 , // don't write output
66+ 0 // don't write output
67+ )
5568
56- require (success, ERROR_CALL_REVERTED);
69+ switch success
70+ case 0 {
71+ let ptr := mload (0x40 )
72+
73+ switch returndatasize
74+ case 0 {
75+ // No error data was returned, revert with "EVMCALLS_CALL_REVERTED"
76+ // See remix: doing a `revert("EVMCALLS_CALL_REVERTED")` always results in
77+ // this memory layout
78+ mstore (ptr, 0x08c379a000000000000000000000000000000000000000000000000000000000 ) // error identifier
79+ mstore (add (ptr, 0x04 ), 0x0000000000000000000000000000000000000000000000000000000000000020 ) // starting offset
80+ mstore (add (ptr, 0x24 ), 0x0000000000000000000000000000000000000000000000000000000000000016 ) // reason length
81+ mstore (add (ptr, 0x44 ), 0x45564d43414c4c535f43414c4c5f524556455254454400000000000000000000 ) // reason
82+
83+ revert (ptr, 100 ) // 100 = 4 + 3 * 32 (error identifier + 3 words for the ABI encoded error)
84+ }
85+ default {
86+ // Forward the full error data
87+ returndatacopy (ptr, 0 , returndatasize)
88+ revert (ptr, returndatasize)
89+ }
90+ }
91+ default { }
92+ }
5793 }
94+ // No need to allocate empty bytes for the return as this can only be called via an delegatecall
95+ // (due to the isInitialized modifier)
5896 }
5997
6098 function executorType () external pure returns (bytes32 ) {
0 commit comments