Last active
September 1, 2023 22:00
-
-
Save darkerego/edce02f936b6441b93e3ca66ae817780 to your computer and use it in GitHub Desktop.
Attempting to Revert Static Calls
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// SPDX-License-Identifier: MIT | |
pragma solidity ^0.8.0; | |
contract TestStateChange { | |
uint public originalValue = 123; | |
uint public oldValue; | |
uint public incrementer = 0; | |
bytes4 public constant CHANGE_SEL = bytes4(keccak256(bytes('changeState(uint256)'))); | |
bytes4 public constant WRAP_CHANGE_SEL = bytes4(keccak256(bytes('wrapChangeState(uint256)'))); | |
error CallFailedError(string reason,address msgSender,address txOrigin); | |
event CallFailed(string indexed reason); | |
event CallSuccess(string indexed reason); | |
function _getRevertReason(bytes memory returnData) internal pure returns(string memory) { | |
// If the length is less than 68, then the transaction failed silently (without a revert message) | |
if (returnData.length < 68) return "Transaction reverted silently"; | |
bytes memory revertData = new bytes(returnData.length - 68); | |
// The first 4 bytes of returnData are the function hash and the next 64 bytes are the | |
// length of the revert reason. The actual revert reason starts from the 68th byte. | |
assembly { | |
revertData := add(0x40, add(returnData, 0x24)) | |
} | |
return abi.decode(revertData, (string)); | |
} | |
function changeState(uint256 _value) external returns(bool success, string memory reason) { | |
require(_value != originalValue, "Choose any other number"); | |
oldValue = originalValue; | |
originalValue = _value; | |
if (oldValue != originalValue) { | |
success = true; | |
reason = 'OK'; | |
emit CallSuccess(reason); | |
} else { | |
reason = "The value did not change!"; | |
//revert CallFailedError(reason, msg.sender, tx.origin); | |
emit CallFailed(reason); | |
} | |
} | |
function testFunc() public returns(bool success) { | |
require(msg.sender == tx.origin, "Function cannot be called with staticCall or web3.eth.call()"); | |
incrementer += 1; | |
success = true; | |
} | |
function wrapChangeState(uint _value) public returns(bool success, bytes memory ret) { | |
// require(msg.sender == tx.origin, "Sender!Origin"); | |
require(_value != originalValue, "Choose any other number"); | |
uint currentValue = originalValue; | |
bytes memory data = abi.encodeWithSelector(CHANGE_SEL, _value); | |
(success, ret) = address(this).call{value: 0}(data); | |
require(success, "Call Failed!"); | |
require(currentValue != originalValue, "State did not change!"); | |
success = true; | |
} | |
function wrapChangeStateView(uint _value) public view returns(bool success) { | |
bytes memory returnData; | |
(success, returnData) = address(this).staticcall(abi.encodeWithSelector(WRAP_CHANGE_SEL, _value)); | |
if (! success) { | |
string memory _reason = _getRevertReason(returnData); | |
revert CallFailedError(_reason, msg.sender, tx.origin); | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment