커버 이미지의 출처는 다음과 같습니다 : https://cryptozombies.io/ko/

크립토좀비 사이트 내용을 정리하였으며, 컨텐츠 관련 모든 권리는 Loom Network에 있습니다.

3) 고급 Solidity 개념 2

1. 컨트랙트의 불변성

외부 의존성

2. 소유 가능한 컨트랙트

OpenZeppelin의 Ownable 컨트랙트

/**
 * @title Ownable
 * @dev The Ownable contract has an owner address, and provides basic authorization control
 * functions, this simplifies the implementation of "user permissions".
 */
contract Ownable {
  address public owner;
  event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

  /**
   * @dev The Ownable constructor sets the original `owner` of the contract to the sender
   * account.
   */
  function Ownable() public {
    owner = msg.sender;
  }

  /**
   * @dev Throws if called by any account other than the owner.
   */
  modifier onlyOwner() {
    require(msg.sender == owner);
    _;
  }

  /**
   * @dev Allows the current owner to transfer control of the contract to a newOwner.
   * @param newOwner The address to transfer ownership to.
   */
  function transferOwnership(address newOwner) public onlyOwner {
    require(newOwner != address(0));
    OwnershipTransferred(owner, newOwner);
    owner = newOwner;
  }
}
코드에서 나오는 개념
코드 설명

Ownable 컨트랙트는 기본적으로 다음과 같은 것들을 함:

  1. 컨트랙트가 생성되면 컨트랙트의 생성자가 ownermsg.sender(컨트랙트를 배포한 사람)를 대입함
  2. 특정한 함수들에 대해 오직 소유자 만 접근할 수 있도록 제한 가능한 onlyOwner 제어자를 추가함
  3. 새로운 소유자 에게 해당 컨트랙트의 소유권을 옮길 수 있도록 함

3. onlyOwner 함수 제어자

ZombieFeeding is ZombieFactory
ZombieFactory is Ownable

함수 제어자

예시: onlyOwner

/**
 * @dev Throws if called by any account other than the owner.
 */
modifier onlyOwner() {
  require(msg.sender == owner);
  _;
}

우리는 이 제어자를 다음과 같이 사용 가능함:

contract MyContract is Ownable {
  event LaughManiacally(string laughter);

  // 아래 `onlyOwner`의 사용 방법을 잘 보게:
  function likeABoss() external onlyOwner {
    LaughManiacally("Muahahahaha");
  }
}

4. 가스(Gas)

가스 - 이더리움 DApp이 사용하는 연료

가스는 왜 필요한가?

가스를 아끼기 위한 구조체 압축

예시
struct NormalStruct {
  uint a;
  uint b;
  uint c;
}

struct MiniMe {
  uint32 a;
  uint32 b;
  uint c;
}

// `mini`는 구조체 압축을 했기 때문에 `normal`보다 가스를 조금 사용할 것이네.
NormalStruct normal = NormalStruct(10, 20, 30);
MiniMe mini = MiniMe(10, 20, 30);

5. 시간 단위(Time nits)

UNIX Timestamp

예시

uint lastUpdated;

// `lastUpdated`를 `now`로 설정
function updateTimestamp() public {
  lastUpdated = now;
}

// 마지막으로 `updateTimestamp`가 호출된 뒤 5분이 지났으면 `true`를, 5분이 아직 지나지 않았으면 `false`를 반환
function fiveMinutesHavePassed() public view returns (bool) {
  return (now >= (lastUpdated + 5 minutes));
}

6. 구조체를 인수로 전달하기

function _doStuff(Zombie storage _zombie) internal {
  // _zombie로 할 수 있는 것들을 처리
}

7. Public 함수 그리고 보안

8. 함수 제어자의 또 다른 특징

인수를 가지는 함수 제어자

// 사용자의 나이를 저장하기 위한 매핑
mapping (uint => uint) public age;

// 사용자가 특정 나이 이상인지 확인하는 제어자
modifier olderThan(uint _age, uint _userId) {
  require (age[_userId] >= _age);
  _;
}

// 차를 운전하기 위햐서는 16살 이상이어야 하네(적어도 미국에서는).
// `olderThan` 제어자를 인수와 함께 호출하려면 이렇게 하면 되네:
function driveCar(uint _userId) public olderThan(16, _userId) {
  // 필요한 함수 내용들
}

9. ‘View’ 함수를 사용해 가스 절약하기

View 함수는 가스를 소모하지 않음

10. Storage는 비싸다

메모리에 배열 선언하기

function getArray() external pure returns(uint[]) {
  // 메모리에 길이 3의 새로운 배열을 생성한다.
  uint[] memory values = new uint[](3);
  // 여기에 특정한 값들을 넣는다.
  values.push(1);
  values.push(2);
  values.push(3);
  // 해당 배열을 반환한다.
  return values;
}

11. For 반복문

for 반복문 사용하기

function getEvens() pure external returns(uint[]) {
  uint[] memory evens = new uint[](5);
  // 새로운 배열의 인덱스를 추적하는 변수
  uint counter = 0;
  // for 반복문에서 1부터 10까지 반복함
  for (uint i = 1; i <= 10; i++) {
    // `i`가 짝수라면...
    if (i % 2 == 0) {
      // 배열에 i를 추가함
      evens[counter] = i;
      // `evens`의 다음 빈 인덱스 값으로 counter를 증가시킴
      counter++;
    }
  }
  return evens;
}
at4am의 프로필 이미지

at4am

2019년 06월 13일

글쓴이의 더 많은 글 읽어보기