그냥 스위치만 뒤집으면 돼. 그렇게 어렵지 않지, 맞지?
도움될 만한 정보
CALLDATA가 어떻게 인코딩되는지 이해하는 것
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract Switch {
bool public switchOn; // switch is off
bytes4 public offSelector = bytes4(keccak256("turnSwitchOff()"));
modifier onlyThis() {
require(msg.sender == address(this), "Only the contract can call this");
_;
}
modifier onlyOff() {
// we use a complex data type to put in memory
bytes32[1] memory selector;
// check that the calldata at position 68 (location of _data)
assembly {
calldatacopy(selector, 68, 4) // grab function selector from calldata
}
require(selector[0] == offSelector, "Can only call the turnOffSwitch function");
_;
}
function flipSwitch(bytes memory _data) public onlyOff {
(bool success,) = address(this).call(_data);
require(success, "call failed :(");
}
function turnSwitchOn() public onlyThis {
switchOn = true;
}
function turnSwitchOff() public onlyThis {
switchOn = false;
}
}
function turnSwitchOn() public onlyThis {
switchOn = true;
}
switchOn = true 로 변경해주는 turnSwitchOn() 함수가 존재하며, 이 함수는 onlyThis modifier가 있다.
modifier onlyThis() {
require(msg.sender == address(this), "Only the contract can call this");
_;
}
onlyThis() 는 컨트랙트 자기 자신만 호출 할 수 있도록 되어 있어 turnSwitchOn() 를 호출한다고 해서 문제가 풀릴 거 같지는 않다.
function flipSwitch(bytes memory _data) public onlyOff {
(bool success,) = address(this).call(_data);
require(success, "call failed :(");
}
flipSwitch() 함수를 살펴보면 call을 이용해서 _data에 있는 값을 실행시키는 것을 볼 수 있는데 이 부분에 turnSwitchOn() 함수를 넘겨주면 될 것 같다.
modifier onlyOff() {
// we use a complex data type to put in memory
bytes32[1] memory selector;
// check that the calldata at position 68 (location of _data)
assembly {
calldatacopy(selector, 68, 4) // grab function selector from calldata
}
require(selector[0] == offSelector, "Can only call the turnOffSwitch function");
_;
}
이제 onlyOff()만 우회하면 문제가 풀릴 것 같다.
onlyOff()를 살펴보면