실습: 중복 투표 방지 (modifier)
지금까지 만든 vote 함수에는 치명적인 허점이 있습니다. 한 사람이 원하는 만큼 여러 번 투표할 수 있어
선거의 공정성이 무너집니다. 현실 선거에서 "1인 1표" 가 기본이듯, 이 컨트랙트도
한 주소는 한 번만 투표 하도록 강제해야 합니다.
투표 기록을 남기고, 검사한다
해법은 두 단계입니다. 첫째, 투표한 주소를 mapping(address => bool) public hasVoted 에 기록합니다.
둘째, 투표하기 전에 hasVoted[msg.sender] 가 이미 true 인지 검사해 이미 투표한 사람을 거부합니다.
여기서 msg.sender 는 함수를 호출한 주소, 즉 투표자 본인을 가리킵니다.
반복 검사는 modifier 로 묶는다
"이미 투표했는지 확인" 같은 검사는 여러 함수에서 재사용될 수 있고, 함수 본문과 검사 로직을 분리하면
코드가 훨씬 읽기 좋습니다. 그래서 검사를 modifier 로 빼냅니다. require 가 거짓이면 트랜잭션
전체가 되돌려지고(revert), 참이면 _; 위치에서 원래 함수 본문이 실행됩니다.
modifier notVotedYet() {
require(!hasVoted[msg.sender], "already voted"); // 이미 투표함
_;
}조건 앞의 느낌표(!)는 "아직 투표하지 않았다면 통과" 라는 뜻입니다. 이걸 반대로 쓰면
투표한 사람만 통과시키는 정반대 동작이 되니 주의하세요.
해야 할 일:
mapping(address => bool) public hasVoted를 선언하세요.notVotedYet라는modifier를 만들어require(!hasVoted[msg.sender], "already voted")로 검사하고_;를 두세요.vote(uint256 index)함수에notVotedYetmodifier 를 적용하고, 투표 후hasVoted[msg.sender] = true;로 기록하세요.
_; 를 빠뜨리면 함수 본문이 아예 실행되지 않습니다. 또한 투표 후 hasVoted[msg.sender] = true;
기록을 잊으면 검사가 무의미해집니다.
완성 후 Run 으로 조건을 확인하세요.