Remove Address.functionDelegateCall
This commit is contained in:
@ -3,7 +3,7 @@
|
|||||||
## 3.3.0
|
## 3.3.0
|
||||||
|
|
||||||
* Now supports both Solidity 0.6 and 0.7. Compiling with solc 0.7 will result in warnings. Install the `solc-0.7` tag to compile without warnings.
|
* Now supports both Solidity 0.6 and 0.7. Compiling with solc 0.7 will result in warnings. Install the `solc-0.7` tag to compile without warnings.
|
||||||
* `Address`: added `functionStaticCall` and `functionDelegateCall`, similar to the existing `functionCall`. ([#2333](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2333))
|
* `Address`: added `functionStaticCall`, similar to the existing `functionCall`. ([#2333](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2333))
|
||||||
* `TimelockController`: added a contract to augment access control schemes with a delay. ([#2354](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2354))
|
* `TimelockController`: added a contract to augment access control schemes with a delay. ([#2354](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2354))
|
||||||
* `EnumerableSet`: added `Bytes32Set`, for sets of `bytes32`. ([#2395](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2395))
|
* `EnumerableSet`: added `Bytes32Set`, for sets of `bytes32`. ([#2395](https://github.com/OpenZeppelin/openzeppelin-contracts/pull/2395))
|
||||||
|
|
||||||
|
|||||||
@ -32,11 +32,6 @@ contract AddressImpl {
|
|||||||
emit CallReturnValue(abi.decode(returnData, (string)));
|
emit CallReturnValue(abi.decode(returnData, (string)));
|
||||||
}
|
}
|
||||||
|
|
||||||
function functionDelegateCall(address target, bytes calldata data) external {
|
|
||||||
bytes memory returnData = Address.functionDelegateCall(target, data);
|
|
||||||
emit CallReturnValue(abi.decode(returnData, (string)));
|
|
||||||
}
|
|
||||||
|
|
||||||
// sendValue's tests require the contract to hold Ether
|
// sendValue's tests require the contract to hold Ether
|
||||||
receive () external payable { }
|
receive () external payable { }
|
||||||
}
|
}
|
||||||
|
|||||||
@ -144,30 +144,6 @@ library Address {
|
|||||||
return _verifyCallResult(success, returndata, errorMessage);
|
return _verifyCallResult(success, returndata, errorMessage);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
|
|
||||||
* but performing a delegate call.
|
|
||||||
*
|
|
||||||
* _Available since v3.3._
|
|
||||||
*/
|
|
||||||
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
|
|
||||||
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
|
|
||||||
* but performing a delegate call.
|
|
||||||
*
|
|
||||||
* _Available since v3.3._
|
|
||||||
*/
|
|
||||||
function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) {
|
|
||||||
require(isContract(target), "Address: delegate call to non-contract");
|
|
||||||
|
|
||||||
// solhint-disable-next-line avoid-low-level-calls
|
|
||||||
(bool success, bytes memory returndata) = target.delegatecall(data);
|
|
||||||
return _verifyCallResult(success, returndata, errorMessage);
|
|
||||||
}
|
|
||||||
|
|
||||||
function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {
|
function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) {
|
||||||
if (success) {
|
if (success) {
|
||||||
return returndata;
|
return returndata;
|
||||||
|
|||||||
@ -334,50 +334,4 @@ contract('Address', function (accounts) {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe('functionDelegateCall', function () {
|
|
||||||
beforeEach(async function () {
|
|
||||||
this.contractRecipient = await CallReceiverMock.new();
|
|
||||||
});
|
|
||||||
|
|
||||||
it('delegate calls the requested function', async function () {
|
|
||||||
const abiEncodedCall = web3.eth.abi.encodeFunctionCall({
|
|
||||||
name: 'mockFunctionWritesStorage',
|
|
||||||
type: 'function',
|
|
||||||
inputs: [],
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
const receipt = await this.mock.functionDelegateCall(this.contractRecipient.address, abiEncodedCall);
|
|
||||||
|
|
||||||
expectEvent(receipt, 'CallReturnValue', { data: '0x1234' });
|
|
||||||
|
|
||||||
expect(await this.mock.sharedAnswer()).to.equal('42');
|
|
||||||
});
|
|
||||||
|
|
||||||
it('bubbles up revert reason', async function () {
|
|
||||||
const abiEncodedCall = web3.eth.abi.encodeFunctionCall({
|
|
||||||
name: 'mockFunctionRevertsReason',
|
|
||||||
type: 'function',
|
|
||||||
inputs: [],
|
|
||||||
}, []);
|
|
||||||
|
|
||||||
await expectRevert(
|
|
||||||
this.mock.functionDelegateCall(this.contractRecipient.address, abiEncodedCall),
|
|
||||||
'CallReceiverMock: reverting',
|
|
||||||
);
|
|
||||||
});
|
|
||||||
|
|
||||||
it('reverts when address is not a contract', async function () {
|
|
||||||
const [ recipient ] = accounts;
|
|
||||||
const abiEncodedCall = web3.eth.abi.encodeFunctionCall({
|
|
||||||
name: 'mockFunction',
|
|
||||||
type: 'function',
|
|
||||||
inputs: [],
|
|
||||||
}, []);
|
|
||||||
await expectRevert(
|
|
||||||
this.mock.functionDelegateCall(recipient, abiEncodedCall),
|
|
||||||
'Address: delegate call to non-contract',
|
|
||||||
);
|
|
||||||
});
|
|
||||||
});
|
|
||||||
});
|
});
|
||||||
|
|||||||
Reference in New Issue
Block a user