contribute() 함수는 msg.value가 0.001 ether일 때 다음 흐름을 가진다.
contributions[msg.sender]에 msg.value를 더하고 만약 contributions[msg.sender]가 contriutions[owner]보다 크면 owner는 msg.sender이다.
여기서 msg.sender = contract를 호출한 사람의 주소, msg.value = 입력한 ether가 된다.
function getContribution() public view returns (uint) {
return contributions[msg.sender];
}
function withdraw() public onlyOwner {
payable(owner).transfer(address(this).balance);
}
getContribution() 함수는 contributions[msg.sender]의 값을 return 한다.
그리고 withdraw() 함수는 owner에게 balance를 지불하는데 msg.value가 owner일 때만 가능하다.
외부에서 송금한 경우 receive() 함수가 실행되는데 msg.value가 > 0이고 contributions[msg.sender]가 > 0이면 owner는 msg.sender로 바뀐다.
현재 owner는 level이다. 그리고 owner의 contribute는 1000 ether를 가지고 시작한다.
일단 owner를 내 주소로 만들기 위해서는 contribute() 함수의 if문과 receive() 함수를 봐야 한다.
contribute() 함수로 owner를 내 주소로 만들기에는 너무 노가다다....
왜냐하면 0.001 ether 미만인 ether를 계속 보내면서 1000 ether를 초과해야 한다.
그러면 receive() 함수를 봐야 하는데 receive()의 조건은 msg.value > 0 && contribute[msg.sender] > 0이다.
첫 번째 contribute[msg.sender] > 0의 조건은 쉽다. 그냥 단순히 0.001 ether 미만의 ether를 보내면 된다.
contribute[msg.sender]에 0.0009 ether를 보냈다. 그리고 getContribution()을 호출하니까 정상적으로 0.0009 ether가 들어 간 것을 확인할 수 있다. 그러면 contribute[msg.sender] > 0의 조건은 만족했다.
두 번째 msg.value > 0은 내가 직접 instance에 ether를 주면 된다. 아까 말했듯이 receive() 함수는 외부에서 ether가 송금되었을 때 실행되는 함수이다.
MetaMask에서 입력한 ether가 0 초과만 하면 되니까 적은 금액을 넣고 송금을 하면 owner가 내 주소로 바뀌는 것을 확인할 수 있다.
첫 번째 contract의 ownership을 내 것으로 만드는 것은 성공했다.
그럼 owner의 balance를 0으로 만들어야 문제가 풀린다.
owner()가 나의 주소로 되어 있으니까 withdraw() 함수를 호출하면 잔액이 0이 된다.
두 가지 mission을 모두 해결했기 때문에 Submit instance를 누르면 level을 클리어했다고 나온다.