|
@@ -54,8 +54,10 @@ library Address {
|
|
* plain `call` is an unsafe replacement for a function call: use this
|
|
* plain `call` is an unsafe replacement for a function call: use this
|
|
* function instead.
|
|
* function instead.
|
|
*
|
|
*
|
|
- * If `target` reverts with a revert reason, it is bubbled up by this
|
|
|
|
- * function (like regular Solidity function calls).
|
|
|
|
|
|
+ * If `target` reverts with a revert reason or custom error, it is bubbled
|
|
|
|
+ * up by this function (like regular Solidity function calls). However, if
|
|
|
|
+ * the call reverted with no returned reason, this function reverts with a
|
|
|
|
+ * {FailedInnerCall} error.
|
|
*
|
|
*
|
|
* Returns the raw returned data. To convert to the expected return value,
|
|
* Returns the raw returned data. To convert to the expected return value,
|
|
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
|
|
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
|
|
@@ -66,23 +68,7 @@ library Address {
|
|
* - calling `target` with `data` must not revert.
|
|
* - calling `target` with `data` must not revert.
|
|
*/
|
|
*/
|
|
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
|
|
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
|
|
- return functionCallWithValue(target, data, 0, defaultRevert);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with a
|
|
|
|
- * `customRevert` function as a fallback when `target` reverts.
|
|
|
|
- *
|
|
|
|
- * Requirements:
|
|
|
|
- *
|
|
|
|
- * - `customRevert` must be a reverting function.
|
|
|
|
- */
|
|
|
|
- function functionCall(
|
|
|
|
- address target,
|
|
|
|
- bytes memory data,
|
|
|
|
- function() internal view customRevert
|
|
|
|
- ) internal returns (bytes memory) {
|
|
|
|
- return functionCallWithValue(target, data, 0, customRevert);
|
|
|
|
|
|
+ return functionCallWithValue(target, data, 0);
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -95,28 +81,11 @@ library Address {
|
|
* - the called Solidity function must be `payable`.
|
|
* - the called Solidity function must be `payable`.
|
|
*/
|
|
*/
|
|
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
|
|
function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
|
|
- return functionCallWithValue(target, data, value, defaultRevert);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
|
|
|
|
- * with a `customRevert` function as a fallback revert reason when `target` reverts.
|
|
|
|
- *
|
|
|
|
- * Requirements:
|
|
|
|
- *
|
|
|
|
- * - `customRevert` must be a reverting function.
|
|
|
|
- */
|
|
|
|
- function functionCallWithValue(
|
|
|
|
- address target,
|
|
|
|
- bytes memory data,
|
|
|
|
- uint256 value,
|
|
|
|
- function() internal view customRevert
|
|
|
|
- ) internal returns (bytes memory) {
|
|
|
|
if (address(this).balance < value) {
|
|
if (address(this).balance < value) {
|
|
revert AddressInsufficientBalance(address(this));
|
|
revert AddressInsufficientBalance(address(this));
|
|
}
|
|
}
|
|
(bool success, bytes memory returndata) = target.call{value: value}(data);
|
|
(bool success, bytes memory returndata) = target.call{value: value}(data);
|
|
- return verifyCallResultFromTarget(target, success, returndata, customRevert);
|
|
|
|
|
|
+ return verifyCallResultFromTarget(target, success, returndata);
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -124,20 +93,8 @@ library Address {
|
|
* but performing a static call.
|
|
* but performing a static call.
|
|
*/
|
|
*/
|
|
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
|
|
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
|
|
- return functionStaticCall(target, data, defaultRevert);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
|
|
|
|
- * but performing a static call.
|
|
|
|
- */
|
|
|
|
- function functionStaticCall(
|
|
|
|
- address target,
|
|
|
|
- bytes memory data,
|
|
|
|
- function() internal view customRevert
|
|
|
|
- ) internal view returns (bytes memory) {
|
|
|
|
(bool success, bytes memory returndata) = target.staticcall(data);
|
|
(bool success, bytes memory returndata) = target.staticcall(data);
|
|
- return verifyCallResultFromTarget(target, success, returndata, customRevert);
|
|
|
|
|
|
+ return verifyCallResultFromTarget(target, success, returndata);
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
@@ -145,82 +102,48 @@ library Address {
|
|
* but performing a delegate call.
|
|
* but performing a delegate call.
|
|
*/
|
|
*/
|
|
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
|
|
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
|
|
- return functionDelegateCall(target, data, defaultRevert);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
|
|
|
|
- * but performing a delegate call.
|
|
|
|
- */
|
|
|
|
- function functionDelegateCall(
|
|
|
|
- address target,
|
|
|
|
- bytes memory data,
|
|
|
|
- function() internal view customRevert
|
|
|
|
- ) internal returns (bytes memory) {
|
|
|
|
(bool success, bytes memory returndata) = target.delegatecall(data);
|
|
(bool success, bytes memory returndata) = target.delegatecall(data);
|
|
- return verifyCallResultFromTarget(target, success, returndata, customRevert);
|
|
|
|
|
|
+ return verifyCallResultFromTarget(target, success, returndata);
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
- * @dev Tool to verify that a low level call to smart-contract was successful, and revert (either by bubbling
|
|
|
|
- * the revert reason or using the provided `customRevert`) in case of unsuccessful call or if target was not a contract.
|
|
|
|
|
|
+ * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target
|
|
|
|
+ * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an
|
|
|
|
+ * unsuccessful call.
|
|
*/
|
|
*/
|
|
function verifyCallResultFromTarget(
|
|
function verifyCallResultFromTarget(
|
|
address target,
|
|
address target,
|
|
bool success,
|
|
bool success,
|
|
- bytes memory returndata,
|
|
|
|
- function() internal view customRevert
|
|
|
|
|
|
+ bytes memory returndata
|
|
) internal view returns (bytes memory) {
|
|
) internal view returns (bytes memory) {
|
|
- if (success) {
|
|
|
|
- if (returndata.length == 0) {
|
|
|
|
- // only check if target is a contract if the call was successful and the return data is empty
|
|
|
|
- // otherwise we already know that it was a contract
|
|
|
|
- if (target.code.length == 0) {
|
|
|
|
- revert AddressEmptyCode(target);
|
|
|
|
- }
|
|
|
|
|
|
+ if (!success) {
|
|
|
|
+ _revert(returndata);
|
|
|
|
+ } else {
|
|
|
|
+ // only check if target is a contract if the call was successful and the return data is empty
|
|
|
|
+ // otherwise we already know that it was a contract
|
|
|
|
+ if (returndata.length == 0 && target.code.length == 0) {
|
|
|
|
+ revert AddressEmptyCode(target);
|
|
}
|
|
}
|
|
return returndata;
|
|
return returndata;
|
|
- } else {
|
|
|
|
- _revert(returndata, customRevert);
|
|
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
- * @dev Tool to verify that a low level call was successful, and revert if it wasn't, either by bubbling the
|
|
|
|
- * revert reason or with a default revert error.
|
|
|
|
|
|
+ * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the
|
|
|
|
+ * revert reason or with a default {FailedInnerCall} error.
|
|
*/
|
|
*/
|
|
- function verifyCallResult(bool success, bytes memory returndata) internal view returns (bytes memory) {
|
|
|
|
- return verifyCallResult(success, returndata, defaultRevert);
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- /**
|
|
|
|
- * @dev Same as {xref-Address-verifyCallResult-bool-bytes-}[`verifyCallResult`], but with a
|
|
|
|
- * `customRevert` function as a fallback when `success` is `false`.
|
|
|
|
- *
|
|
|
|
- * Requirements:
|
|
|
|
- *
|
|
|
|
- * - `customRevert` must be a reverting function.
|
|
|
|
- */
|
|
|
|
- function verifyCallResult(
|
|
|
|
- bool success,
|
|
|
|
- bytes memory returndata,
|
|
|
|
- function() internal view customRevert
|
|
|
|
- ) internal view returns (bytes memory) {
|
|
|
|
- if (success) {
|
|
|
|
- return returndata;
|
|
|
|
|
|
+ function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {
|
|
|
|
+ if (!success) {
|
|
|
|
+ _revert(returndata);
|
|
} else {
|
|
} else {
|
|
- _revert(returndata, customRevert);
|
|
|
|
|
|
+ return returndata;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
/**
|
|
/**
|
|
- * @dev Default reverting function when no `customRevert` is provided in a function call.
|
|
|
|
|
|
+ * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.
|
|
*/
|
|
*/
|
|
- function defaultRevert() internal pure {
|
|
|
|
- revert FailedInnerCall();
|
|
|
|
- }
|
|
|
|
-
|
|
|
|
- function _revert(bytes memory returndata, function() internal view customRevert) private view {
|
|
|
|
|
|
+ function _revert(bytes memory returndata) private pure {
|
|
// Look for revert reason and bubble it up if present
|
|
// Look for revert reason and bubble it up if present
|
|
if (returndata.length > 0) {
|
|
if (returndata.length > 0) {
|
|
// The easiest way to bubble the revert reason is using memory via assembly
|
|
// The easiest way to bubble the revert reason is using memory via assembly
|
|
@@ -230,7 +153,6 @@ library Address {
|
|
revert(add(32, returndata), returndata_size)
|
|
revert(add(32, returndata), returndata_size)
|
|
}
|
|
}
|
|
} else {
|
|
} else {
|
|
- customRevert();
|
|
|
|
revert FailedInnerCall();
|
|
revert FailedInnerCall();
|
|
}
|
|
}
|
|
}
|
|
}
|