본문 바로가기

Language/Solidity

solidity 기본 문법 5. 상속, Interface, 다수 return 값 처리 with 크립토좀비

챕터 2-10. 다른 컨트랙트와 상호작용하기


블록체인 상에 있으면서

우리가 소유하지 않은 컨트랙트와

우리 컨트랙트가 상호작용을 하려면

우선 인터페이스를 정의해야한다

ex)

contract NumberInterface {
  function getNum(address _myAddress) public view returns (uint);
}



약간 다르지만,

인터페이스를 정의하는 것은 컨트랙트를 정의하는 것과 유사

"다른 컨트랙트와 상호작용하고자 하는 함수만을 선언"할 뿐( 이 경우, getNum )

다른 함수나 상태 변수를 언급하지 않음

다음으로, 함수 몸체를 정의하지 않음

중괄호 { }를 쓰지 않고 함수 선언을 세미콜론(;)으로 간단하게 정의

때문에 인터페이스는 컨트랙트 뼈대라고 볼 수 있다ㅏㅏㅏ


챕터 2-11. 인터페이스 활용하기



아래와 같이 인터페이스가 정의되면,

contract NumberInterface {
  function getNum(address _myAddress) public view returns (uint);
}


다음과 같이 컨트랙트에서 인터페이스를 이용할 수 있다

contract MyContract {
  address NumberInterfaceAddress = 0xab38...
  // ^ 이더리움상의 FavoriteNumber 컨트랙트 주소이다
  NumberInterface numberContract = NumberInterface(NumberInterfaceAddress)
  // 이제 `numberContract`는 다른 컨트랙트를 가리키고 있다.

  function someFunction() public {
    // 이제 `numberContract`가 가리키고 있는 컨트랙트에서 `getNum` 함수를 호출할 수 있다:
    uint num = numberContract.getNum(msg.sender);
    // ...그리고 여기서 `num`으로 무언가를 할 수 있다
  }
}



이런 식으로 컨트랙트가 이더리움 블록체인상의 다른 어떤 컨트랙트와도 상호작용할 수 있다

** but상호작용하는 함수가 public이나 external로 선언되어 있어야 한다 **



챕터 2-12. 다수의 반환값 처리하기



** 함수에서 어떻게 다수의 반환값을 처리하는지 살펴보기 **

ex)

function multipleReturns() internal returns(uint a, uint b, uint c) {
  return (1, 2, 3);
}

function processMultipleReturns() external {
  uint a;
  uint b;
  uint c;
  // 다음과 같이 다수 값을 할당한다:
  (a, b, c) = multipleReturns();
}

// 혹은 단 하나의 값에만 관심이 있을 경우
function getLastReturnValue() external {
  uint c;
  // 다른 필드는 빈칸으로 놓기만 하면 된다
  (,,c) = multipleReturns();
}




챕터 2-13. 보너스


** 생성된 좀비가 몇 가지 독특한 특성을 가져서 고양이 좀비로 보이도록 해 보기 **

If 문
솔리디티에서 if 문은 자바스크립트의 if 문과 동일

ex)

function eatBLT(string sandwich) public {
  // 스트링 간의 동일 여부를 판단하기 위해 keccak256 해시 함수를 이용해야 한다는 것을 기억하자
  if (keccak256(sandwich) == keccak256("BLT")) {
    eat();
  }
}



** 좀비 코드에 고양이 유전자에 대한 내용을 구현 **

pragma solidity ^0.4.19;

import "./zombiefactory.sol";

contract KittyInterface {
  function getKitty(uint256 _id) external view returns (
    bool isGestating,
    bool isReady,
    uint256 cooldownIndex,
    uint256 nextActionAt,
    uint256 siringWithId,
    uint256 birthTime,
    uint256 matronId,
    uint256 sireId,
    uint256 generation,
    uint256 genes
  );
}
contract ZombieFeeding is ZombieFactory {

  address ckAddress = 0x06012c8cf97BEaD5deAe237070F9587f8E7A266d;
  KittyInterface kittyContract = KittyInterface(ckAddress);

  function feedAndMultiply(uint _zombieId, uint _targetDna, string _species) public {
    require(msg.sender == zombieToOwner[_zombieId]);
    Zombie storage myZombie = zombies[_zombieId];
    _targetDna = _targetDna % dnaModulus;
    uint newDna = (myZombie.dna + _targetDna) / 2;
// 좀비가 잡아먹은 객체의 species값이 kitty라면,
    if (keccak256(_species) == keccak256("kitty")) {
// DNA 마지막 2자리를 99로 대체
      newDna = newDna - newDna % 100 + 99;
    }
    _createZombie("NoName", newDna);
  }

  function feedOnKitty(uint _zombieId, uint _kittyId) public {
    uint kittyDna;
    (,,,,,,,,,kittyDna) = kittyContract.getKitty(_kittyId);
    feedAndMultiply(_zombieId, kittyDna, "kitty");
  }

}