[Day34] OpenZeppelin 이더너트 문제풀이 — (7) Delegation
이번 시간에는 Delegation 문제를 풀어보도록 하겠습니다.
이 레벨에서는 컨트랙트의 오너쉽을 빼앗기만 하면 되는 문젠데요.. 힌트를 보면 Address Type의 delegatecall이 어떻게 작동 되는지를 알면 된다고 써져 있네요. 그리고 Fallback 함수와 메써드 ID라고 적혀있습니다. 자 그럼 문제를 한번 보도록 하죠~
pragma solidity ^0.4.18;contract Delegate {address public owner;function Delegate(address _owner) public {
owner = _owner;
}function pwn() public {
owner = msg.sender;
}
}contract Delegation {address public owner;
Delegate delegate;function Delegation(address _delegateAddress) public {
delegate = Delegate(_delegateAddress);
owner = msg.sender;
}function() public {
if(delegate.delegatecall(msg.data)) {
this;
}
}
}
우선 Delegation 컨트랙트를 [Get new instance] 버튼을 통해 트랜잭션을 생성하게 되면 Owner 가 이더너트에서 지정한 Address로 아래와 같이 call 을 통해 확인 할 수 있습니다.
소스를 잠깐 보자면 fallback 함수에서 delegate 컨트랙트의 멤버함수인 delegatecall을 하는 것을 볼 수 있습니다.
msg.data의 경우 delegatecall Spec에서 확인해보면 HashFunction 이라고 keccak256 실행과 bytes4로 잘라낸 부분을 간혹 delegatecall 함수를 사용한 곳에서 보면 보실 수 있는데 아래 Delegate 컨트랙트 소스 중 owner = msg.sender 로 바꿔주는 함수 중 pwn() 함수를 bytes4(keccak256(“pwn()”)) 의 조합으로 Method ID를 만들어 주면 컨트랙트의 함수를 실행할 수 있는 부분을 만들 수 있게 됩니다. 코드로 설명을 하자면
contract Delegate {address public owner;function Delegate(address _owner) public {
owner = _owner;
}function pwn() public {
owner = msg.sender;
}}
Bold 체로 되어있는 pwn() 함수를 다른 컨트랙트에서 실행하기 위해선 bytes4(keccak256(“pwn()”)) 의 조합으로 만들어진 Method ID 를 넣어주면 된다는 뜻입니다. 자 그럼 이 부분은 별도의 컨트랙트 필요없이 MetaMask 로만 Send Transaction 을 날려 제 Owner의 계정으로 바꿔보겠습니다.
먼저 Method ID는 다른 컨트랙트 함수를 통해 구할 필요없이 Remix IDE > Compile 탭 > Delagate 컨트랙트 선택후 > Details 버튼 클릭을 하게 되면 팝업이 나오게 되는데 이중 아래 그림 Function Hashes 부분에 해당 Method ID를 구할 수 있게 됩니다.
“dd365b8b” 를 어딘가에 복사한 후 MetaMask에서 Delegation 컨트랙트 주소로 추가 데이터로 위의 Method ID를 붙여넣기 하여 Transaction을 생성해 보겠습니다.
위와 같이 To 수신자 정보에는 Delegation 컨트랙트 주소를 Data에는 Method ID를 넣고 다음을 누르게 되면 Delagation 컨트랙트 Fallback 함수를 통해 Delegate pwn() 함수가 실행되고 msg.sender는 delegatecall 특성에 따라 최초에 트랜잭션을 발생시킨 제 EOA 계정이 되는 것입니다.
만약 Data 입력란이 보이지 않는다면 MetaMask 최신버전을 사용하고 있는 것이기 때문에 설정에서 아래와 같이 Hex데이터를 On으로 바꿔주시면 창에서 보이게 됩니다.
트랜잭션 처리가 완료가 되면 Owner의 값을 확인해보면 아래와 같이 내 계정으로 바뀐것을 확인할 수가 있습니다.
이 문제는 Address Type의 delegatecall만 제대로 알고 있다면 풀 수 있는 문제입니다. 만약 delegatecall을 제대로 이해하고 있지 않으신 분이라면 https://solidity.readthedocs.io/en/v0.5.0/index.html 사이트에서 Spec을 한번 확인해보시길 바랍니다!
끄읏~ 다음 문제는 Force 문제입니다.
- 저는 블록체인 개발사 (주)34일에서 블록체인 엔지니어로 일하고 있습니다.
- 880만 팔로워 전세계 1위 한류 미디어 케이스타라이브(KStarLive)와 함께 만든 한류 플랫폼에서 사용되는 케이스타코인(KStarCoin) 프로젝트를 진행 중입니다. 팬 커뮤니티 활동을 하면서 코인을 얻을 수 있으며, 한류 콘텐츠 구매, 공연 예매, 한국 관광 상품 구매, 기부 및 팬클럽 활동 등에 사용 될 계획입니다.