44pragma solidity ^ 0.8.20 ;
55
66import {Errors} from "./Errors.sol " ;
7+ import {LowLevelCall} from "./LowLevelCall.sol " ;
78
89/**
910 * @dev Collection of functions related to the address type
@@ -34,10 +35,13 @@ library Address {
3435 if (address (this ).balance < amount) {
3536 revert Errors.InsufficientBalance (address (this ).balance, amount);
3637 }
37-
38- (bool success , bytes memory returndata ) = recipient.call {value: amount}("" );
39- if (! success) {
40- _revert (returndata);
38+ if (LowLevelCall.callNoReturn (recipient, amount, "" )) {
39+ // call successful, nothing to do
40+ return ;
41+ } else if (LowLevelCall.returnDataSize () > 0 ) {
42+ LowLevelCall.bubbleRevert ();
43+ } else {
44+ revert Errors.FailedCall ();
4145 }
4246 }
4347
@@ -76,47 +80,74 @@ library Address {
7680 if (address (this ).balance < value) {
7781 revert Errors.InsufficientBalance (address (this ).balance, value);
7882 }
79- (bool success , bytes memory returndata ) = target.call {value: value}(data);
80- return verifyCallResultFromTarget (target, success, returndata);
83+ bool success = LowLevelCall.callNoReturn (target, value, data);
84+ if (success && (LowLevelCall.returnDataSize () > 0 || target.code.length > 0 )) {
85+ return LowLevelCall.returnData ();
86+ } else if (success) {
87+ revert AddressEmptyCode (target);
88+ } else if (LowLevelCall.returnDataSize () > 0 ) {
89+ LowLevelCall.bubbleRevert ();
90+ } else {
91+ revert Errors.FailedCall ();
92+ }
8193 }
8294
8395 /**
8496 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
8597 * but performing a static call.
8698 */
8799 function functionStaticCall (address target , bytes memory data ) internal view returns (bytes memory ) {
88- (bool success , bytes memory returndata ) = target.staticcall (data);
89- return verifyCallResultFromTarget (target, success, returndata);
100+ bool success = LowLevelCall.staticcallNoReturn (target, data);
101+ if (success && (LowLevelCall.returnDataSize () > 0 || target.code.length > 0 )) {
102+ return LowLevelCall.returnData ();
103+ } else if (success) {
104+ revert AddressEmptyCode (target);
105+ } else if (LowLevelCall.returnDataSize () > 0 ) {
106+ LowLevelCall.bubbleRevert ();
107+ } else {
108+ revert Errors.FailedCall ();
109+ }
90110 }
91111
92112 /**
93113 * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
94114 * but performing a delegate call.
95115 */
96116 function functionDelegateCall (address target , bytes memory data ) internal returns (bytes memory ) {
97- (bool success , bytes memory returndata ) = target.delegatecall (data);
98- return verifyCallResultFromTarget (target, success, returndata);
117+ bool success = LowLevelCall.delegatecallNoReturn (target, data);
118+ if (success && (LowLevelCall.returnDataSize () > 0 || target.code.length > 0 )) {
119+ return LowLevelCall.returnData ();
120+ } else if (success) {
121+ revert AddressEmptyCode (target);
122+ } else if (LowLevelCall.returnDataSize () > 0 ) {
123+ LowLevelCall.bubbleRevert ();
124+ } else {
125+ revert Errors.FailedCall ();
126+ }
99127 }
100128
101129 /**
102130 * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target
103131 * was not a contract or bubbling up the revert reason (falling back to {Errors.FailedCall}) in case
104132 * of an unsuccessful call.
133+ *
134+ * NOTE: This function is DEPRECATED and may be removed in the next major release.
105135 */
106136 function verifyCallResultFromTarget (
107137 address target ,
108138 bool success ,
109139 bytes memory returndata
110140 ) internal view returns (bytes memory ) {
111- if (! success) {
112- _revert (returndata);
113- } else {
114- // only check if target is a contract if the call was successful and the return data is empty
115- // otherwise we already know that it was a contract
116- if (returndata.length == 0 && target.code.length == 0 ) {
117- revert AddressEmptyCode (target);
118- }
141+ // only check if target is a contract if the call was successful and the return data is empty
142+ // otherwise we already know that it was a contract
143+ if (success && (returndata.length > 0 || target.code.length > 0 )) {
119144 return returndata;
145+ } else if (success) {
146+ revert AddressEmptyCode (target);
147+ } else if (returndata.length > 0 ) {
148+ LowLevelCall.bubbleRevert (returndata);
149+ } else {
150+ revert Errors.FailedCall ();
120151 }
121152 }
122153
@@ -125,23 +156,10 @@ library Address {
125156 * revert reason or with a default {Errors.FailedCall} error.
126157 */
127158 function verifyCallResult (bool success , bytes memory returndata ) internal pure returns (bytes memory ) {
128- if (! success) {
129- _revert (returndata);
130- } else {
159+ if (success) {
131160 return returndata;
132- }
133- }
134-
135- /**
136- * @dev Reverts with returndata if present. Otherwise reverts with {Errors.FailedCall}.
137- */
138- function _revert (bytes memory returndata ) private pure {
139- // Look for revert reason and bubble it up if present
140- if (returndata.length > 0 ) {
141- // The easiest way to bubble the revert reason is using memory via assembly
142- assembly ("memory-safe" ) {
143- revert (add (returndata, 0x20 ), mload (returndata))
144- }
161+ } else if (returndata.length > 0 ) {
162+ LowLevelCall.bubbleRevert (returndata);
145163 } else {
146164 revert Errors.FailedCall ();
147165 }
0 commit comments