[크립토좀비] 레슨4. 좀비 전투 시스템 - 실제로 이더를 주고 받기

가영·2021년 5월 2일
1

솔리디티

목록 보기
7/7
post-thumbnail

싸.우.게.


ch1. Payable

지금까지 다루었던 함수제어자들을 한 번 복습해보자!

접근 제어자 (visibility modifier)

함수가 언제, 어디서 호출될 수 있는지 제어한다.

  • private: 컨트랙트 내부의 다른 함수들에서만 호출될 수 있음.
  • internal: internal 범위 + 해당 컨트랙트를 상속하는 컨트랙트에서 호출될 수 있다.
  • external: 오직 컨트랙트 외부에서만 호출될 수 있다.
  • public: 내부, 외부 어디서나 호출될 수 있다.

상태 제어자 (state modifier)

상태제어자는 블록체인과 상호작용 하는 방법에 대해 알려줬다.

  • view: 해당 함수를 실행해도 어떤 데이터도 저장/변경되지 않음
  • pure: 해당함수가 어떤 데이터도 블록체인에 저장하지 않고 + 블록체인으로부터 아무 데이터도 읽지 않는 상태

사용자 정의 제어자

ex) onlyOwner, aboveLevel같이 우리가 정의한 제어자 !! modifier 로 함수처럼 선언했었음

modifier aboveLevel(uint _zombieId) {
  require(zombies[_zombieId].level >= 2);
  _;
}

이런 제어자들은 함수 하나에 다음과 같이 사용할 수 있다! 💥

function test() external view onlyOwner anotherModifier { /*...*/ }

이번 챕터에서는 새로운 함수 제어자를 하나 더 배웠다! 바로 payable이다.

payable 제어자

일반적인 웹서버에서 API 함수를 실행할 때는 함수 호출만으로 금융거래를 할 수는 없다. 👉🏻 일반적으로는 비트코인도 마찬가지다.

하지만 이더리움에서는 돈(이더), 데이터, 컨트랙트 코드 자체 모두가 이더리움 위에 있기 때문에 우리가 함수를 실행해서 컨트랙트에 돈을 지불할 수가 있다.

그럼 거꾸로, 특정 함수를 실행하기 위해서는 컨트랙트에 일정 금액을 지불하게 하는 것이 가능해지는 것이다. 🤩

예시를 보자 💨

contract OnlineStore {
  function buySomething() external payable {
    require(msg.value == 0.001 ether);
    transferThing(msg.sender);
  }
}

여기서, msg.value컨트랙트로 이더가 얼마나 보내졌는지 확인하는 방법이고, ether는 이더리움에 정의된 단위다.

참고로 프론트에서 아래와 같은 형식으로 보내준다고 한다.

// `OnlineStore`는 이더리움 위의 컨트랙트를 가리킨다고 가정한다.:
OnlineStore.buySomething({from: web3.eth.defaultAccount, value: web3.utils.toWei(0.001)})

value 필드를 보면 이더를 얼마나 보낼지 설정된 것을 알 수 있다. (호오~👀)

+) 위의 코드처럼 이더를 보내려면, 반드시 함수가 payable로 선언돼있어야한다. payable이 아닌 함수로 이더를 보내려고하면 함수 자체에서 트랜잭션을 거부한다.


우리 게임에 적용해보자!

레벨업하는 함수를 호출하려면 요금을 내야하도록 구현해보쟝🙂!

정답이다. 넘무 쉽다💗

contract ZombieHelper is ZombieFeeding {

  uint levelUpFee = 0.001 ether;

  function levelUp(uint _zombieId) external payable {
    require(msg.value == levelUpFee);
    zombies[_zombieId].level++;
  }

  //...
  
}

ch2. 출금

챕터1에서 컨트랙트에 이더를 보내는 방법을 배웠다. 그럼 이더를 보낸 다음에는 어떤 일이 일어날까?

우리가 컨트랙트로 이더를 보내면
👉🏻 해당 컨트랙트의 이더리움 계좌에 이더가 저장 되고
👉🏻 컨트랙트의 소유자가 onlyOwner로 정의한 이더 인출 함수를 호출하여 이더를 가지게 된다!

인출함수는 다음처럼 만들 수 있다.

contract GetPaid is Ownable { // Ownable 컨트랙트를 import 했다면
  function withdraw() external onlyOwner { // onlyOwner 사용
    owner.transfer(this.balance); // owner 사용
  }
}

balance는 컨트랙트에 저장돼있는 전체 잔액이다. 만약 우리가 GetPaid의 owner라면 withdraw()를 호출해서 GetPaid에 저장된 전체 잔액을 빼올 수 있는 것이다.

만약 owner가 아니라 transfer() 함수를 다른 주소에 붙이면?
👉🏻 맞다! 원하는 주소로 돈을 보낼 수 있다.

예를 들어, 누군가 한 아이템에 대해 초과 지불을 했다면, 이더를 msg.sender로 되돌려주는 함수를 만들 수도 있다.

uint itemFee = 0.001 ether;
msg.sender.transfer(msg.value - itemFee);

게임에 적용하쟈

1. withdraw 함수를 위의 예제처럼 만들어준다!
2. 가격은 물가에 따라 바뀔 수 있어야하므로 levelupFee를
   변경하는 함수를 만든다: setLevelUpFee()

정답은 다음과 같습니당

function withdraw() external onlyOwner {
    owner.transfer(this.balance);
  }

  function setLevelUpFee(uint _fee) external onlyOwner {
    levelUpFee = _fee;
  }

계속됩니당.

0개의 댓글