글이 너무 길어지는 것 같기 떄문에 추가로 적겠다.
앞선 글에서 기본적인 솔리디티 문법을 배웠다.
단순히 이런게 있구나 라는 느낌이였기 때문에 좀더 실습을 진행해 보고자 한다.
// SPDX-License-Identifier: MIT
pragma solidity 0.8.7;
contract helloWorld{
function renderHelloWorld () public pure returns(string memory){
return "Hello World!";
}
}
많은 것을 담고 있지는 않지만 간다하게 알 수가 있다.
일단 기본적으로 함수를 사용하였고 public로 선언을 하였다
그리고 return문은 string이다.
나는 따른 변수를 읽거나 쓰지 않기 떄문에 pure를 추가한 것이다.
// SPDX-License-Identifier: MIT
pragma solidity 0.8.7;
contract helloWorld{
string answer = "HelloWorld";
function renderHelloWorld () public returns(string memory){
return answer;
}
}
만약 변수를 읽고자 한다면 pure를 이처럼 제거 해야 한다.
// SPDX-License-Identifier: MIT
pragma solidity 0.8.7;
contract helloWorld{
string answer;
function set(string memory x) private {
answer = x;
}
function renderHelloWorld () public returns(string memory){
return answer;
}
}
따로 변수를 읽고자 한다면 이렇게 작성을 하면 된다.
🔨 memory
memory를 사용하는 이유에 대해 의문이 들 것이다.
솔리디티 버전이 올라감에 따라 변수에 memory를 적어주어야 한다고 한다..
앞서 정말 간단한 솔리디티를 작성해 보았고 이번에는 좀더 복잡한 솔리디티를 작성해 보자.
두 명의 플레이어가 가위바위보 게임을 진행하고, 이긴 경우 두 참여자의 베팅금액을 모두 가져간다.
세가지 퍼블릭 함수를 가지고 있다.
createRoom
: 가위바위보 게임을 하기 위한 방을 만든다.joinRoom
: 만들어진 방에 참가한다.payout
: 게임을 마친다. 결과에 따라 금액을 송금하다.다음과 같은 플로우로 진행이 된다.
[1] 방장이 우선 createRoom 을 호출한다.
방장은 인자로 자신이 낼 가위/바위/보 와 베팅 금액을 넘겨준다.
- createRoom은 새로운 방을 만들고, 방의 번호를 return한다.
[2] 참가자는 joinRoom을 호출한다.
참가자는 인자로 참여할 방 번호, 자신이 낼 가위/바위/보 값과 베팅 금액을 넘겨준다.
- joinRoom은 참가자를 방에 참여시킨다.
- joinRoom은 방장과 참가자의 값을 확인하고 승자를 설정한다.
[3] 방장 또는 참가자가 payout함수를 호출한다.
인자로 게임을 끝낼 방 번호를 넘겨준다.
- 게임의 결과에 따라 베팅 금액을 송금하다.
기본적인 사용자 설정과 게임 구성도 이다.
HAND
는 낼수 있는 카드(주먹/가위/보)를 의미하며
PlaterStatus
는 플레이어들의 현재 상태를 나타낸다.
GameStatus
는 현재 게임의 진행도를 나타낸다.
각각의 플레이어들은 개인의 지갑 주소와 배팅금액 등등을 상태로 가지고 있고
Game은 Player중에서 방장과 상대방을 지정하며 총 배팅금액 및 게임의 진행 상태를 가지고 있다.
일단 mapping을 통해서 키-값
형태인 rooms
를 만들어 준다.
이후 함수를 통해서 만들어 주면 된다.
이렇게 되면 우리는 originator과 taker를 만들 었다.
하지만 이떄 originator즉 방장이 방을 생성하였을떄 가위/바위/보 같이 아닌 다른 값이 지정될 수도 있기 떄문에 우리는 modifier
를 활용하여 값을 미리 확인해야 한다.
이와같이 수정을 하면 함수가 실행하기 전에 들어오는 매개변수값을 _hand를 통해 검사를 하게 될 것이다.
기존에 만들어진 방에 참가를 해야한다.
참가자들은 가위/바위/보 값을 인자로 보내고 금액을 msg.value로 설정한다.
마찬가지로 isValidHand를 사용한다.
앞선 코드에서는 taker은 지정하지 않았다.
방을 만들떄마다 방 번호가 부여될 것이고 거기에는 반장이 미리 내놓은 선택지가 잇을것이다.
우리는 이 부분을 전제로 깔고 있어야 한다.
왜냐하면 따로 바꾸는 함수가 없기 때문이다.
그럼 이제 taker입장에서는 방번호를 선택해 들어가면 되고 들어갈떄 인자로 선택지, 방번호를 입력해 주어야 한다.
그후 그 방의 taker를 갱신하고 전체 배팅금액을 늘린다.
그후 반장과 taker의 선택지를 비교하는 함수 compareHands를 호출하면 된다.
그럼 compareHands에서는 일단 타입을 바꾸어 준다.
한가지 알아 두어야 할 것이다 있다.
enum즉 열거형은 앞에 인자부터 0,1,2,3,4,... 이렇게 인덱스를 가지게 된다.
즉 rock = 1, paper = 2, scissors = 3
이런식이다.
자 이제 게임 방의 상태를 STATUS_STARTED
로 갱신을 한 뒤에
if문을 통해 누가 이겼는지를 파악한다.
우리가 if문을 통해서 승자의 상태를 바꾸었다는 것을 전 코드를 보면 알 수가 있다.
그럼 그 값을 통해서 누가 승자인지를 판별하고 그후 배팅한 금액을 돌려 주어야 한다.
우리는 컨트랙트에 있는 금액을 송금하기 위해서는 내장되어 있는 transfer
함수를 사용하면 된다.
사용법
ADDRESS.transfer(value)
// ADDRESS로 value만큼 송금한다.
단순하게 노가다 식으로 작성을 하면된다.
해당 상태의 값이 내가 원하는 값이면 원하는 방식에 맞게 처리를 해주면 된다.
내가 한가지 간과한 것이 있다면 payout
를 실행시키는 주체는 반장 또는 해당 방의 taker이어야 한다는 점이다.
그러기 떄문에 modifier를 추가하여 적용시켜 주었다.
수정한 코드는 이와 같다.
msg.sender 즉 트랜잭션을 발생시키는 주체가 같은 방 사람일 경우에만 작동이 되게 하였다.
🔨 긴 여정이 끝났다...ㅠㅠ
현 시점에서 솔리디티의 최신 버전은 0.8.10이다.
계속해서 업데이트가 되어가고 있고 생태계마다 사용하는 솔리디티 버전은 조금씩 다르다.
솔리디티 버전이 업데이트 됨에 따라 문법적으로 약간씩 달라지기 떄문에 주의 하여야 한다.
클레이튼에서는 현재 0.5.6을 사용하고 있다.
🔨 차이점