(수정중)
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;
contract Delegate {
address public owner;
constructor(address _owner) public {
owner = _owner;
}
function pwn() public {
owner = msg.sender;
}
}
contract Delegation {
address public owner;
Delegate delegate;
constructor(address _delegateAddress) public {
delegate = Delegate(_delegateAddress);
owner = msg.sender;
}
fallback() external {
(bool result,) = address(delegate).delegatecall(msg.data);
if (result) {
this;
}
}
}
The goal of this level is for you to claim ownership of the instance you are given.
Things that might help
-Look into Solidity's documentation on the delegatecall low level function, how it works,
how it can be used to delegate operations to on-chain libraries, and what implications it has on execution scope.
-Fallback methods
-Method ids
ownership 가져오기
Delegatecall의 개념은 다음과 같다.
현재 Delegation 컨트랙트가 Delegate 컨트랙트를 호출하고 있으니 우리는 Delegation 컨트랙트를 통해 pwn()
함수를 호출하면 ownership을 가져올 수 있지 않을까?
컨트랙트에 이더를 보낼 때 msg.data
가 비어있거나, receive()
함수가 없을 때 fallback 함수가 실행된다.
await contract.call(abi.encodeWithSignture("pwn()"))
위 방법으로 pwn()
을 호출하려 했지만 abi가 정의되지 않아서 fail.
Uncaught (in promise) ReferenceError: abi is not defined
컨트랙트를 만들어서 pwn()
함수를 호출했더니..이 컨트랙트가 owner가 되었다ㅋㅋㅋㅋ
그러면 컨트랙트를 통해 pwn()
함수를 호출하고 owner를 넘기는 함수를 만들면 되지 않을까?
하지만 실패..delegatecall을 하면 호출한 컨트랙트 안에서만 데이터가 바뀌어서 그런게 아닐까 싶다. 결국 콘솔에서 메소드를 호출하는 방향으로 바꿔야 할 것 같다.
await contract.sendTransaction({data: "pwn()"})
이런 식으로 시도해봤다.
data 입력칸이 HEX 값으로 encoded 되어야 한다는 친절한(?) 에러
web3.utils.toHex
로 시도해봤지만 owner는 바뀌지 않았다.
web3.utils.keccak256
으로 했더니 드디어 바뀌었다. 도대체 왜?