【Solidity】OpenZeppelinのOwnableコントラクトとは

【はじめに】

この記事はSolidityを勉強する為にCryptoZombiesで学んだ事を自分用のメモとして書いています。

【CryptoZombiesとは】

Solidityでスマートコントラクトの構築を学習できるサイト
日本語で丁寧に説明してくれるので、プログラミングやったことない人でも学習できる。

cryptozombies.io

【OpenZeppelinのOwnableコントラクトとは】

Lesson3でOpenZeppelinのOwnableコントラクトが出てきました。
Solidityの勉強で重要と思いましたので記事にしておきます。

OpenZeppelinとは?

Ethereum上で安全なスマートコントラクトを実装するためのフレームワーク

github.com

Ownableコントラクトとは?

OpenZeppelinの1つで、コントラクトの実行権限を限定することができる。
実行権限を管理しておかないと誰でも実行できる状態になり悪用される恐れがある。
Ownableコントラクトを継承すれば、コントラクトを作成した人しか実行できないようにすることが可能。

【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.
   */
  constructor() 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 {
    _transferOwnership(_newOwner);
  }

  /**
   * @dev Transfers control of the contract to a newOwner.
   * @param _newOwner The address to transfer ownership to.
   */
  function _transferOwnership(address _newOwner) internal {
    require(_newOwner != address(0));
    emit OwnershipTransferred(owner, _newOwner);
    owner = _newOwner;
  }
}

constructor

Ownableコントラクトのコンストラク
コントラクト作成時に1度だけ実行されるので、作成者のアドレスをownerに格納することができる。

modifier onlyOwner

onlyOwnerを関数につけることで使用できる。
コントラクトを呼び出したアドレスと作成者のアドレスが同じでない場合、エラーになる。
つまり、作成者以外が呼び出しても実行できなくなる。

transferOwnership

ownerのアドレスを変更することで実行権限を移行することができる。

【まとめ】

OpenZeppelinはSolidityの開発で頻繁に使われているので、自分で作成するよりもセキュリティ面で安心して使用できます。
Ownable以外にも便利なコントラクトがありそうなので、もっと勉強しなければ。

【CryptoZombiesを触ってみた】Lesson2で学んだこと

【CryptoZombiesとは】

Solidityでスマートコントラクトの構築を学習できるサイト
日本語で丁寧に説明してくれるので、プログラミングやったことない人でも学習できる。

cryptozombies.io

【はじめに】

Solidityは未経験ですが、JavaScriptは触ったことがあります。
そんな人が自分用の学習メモとして書いています。

【学んだこと】

  • データ型のmappingとaddress
    • mappingはKVS(Key-Value Store)
    • addressはEthereumのアドレス
'mappingの書き方 Key => Value
mapping (address => uint) public accountBalance;
mapping (uint => string) userIdToName;
  • msg.sender

その関数を呼び出したユーザー(またはスマートコントラクト)のaddressを取得する。

mapping (address => uint) accountBalance;

function setBalance(uint _myBalance) public {
  accountBalance[msg.sender] = _myBalance;
}

function whatIsMyBalance() public view returns (uint) {
  return accountBalance[msg.sender];
}
  • Require

条件を満たさない場合、エラーを投げる。

'挨拶(_greeting)が"Hello"の場合、"Hello!"を返す。
'"Hello"以外の場合、エラーになる。
function sayHello(string _greeting) public returns (string) {
  require(keccak256(_greeting) == keccak256("Hello"));
  return "Hello!";
}
  • 継承
'BabyDogからtype()も実行可能
contract Dog {
  function type() public returns (string) {
    return "puppy";
  }
}

contract BabyDog is Dog {
  function age() public returns (string) {
    return "1 year old";
  }
}
  • Import

別ファイルに定義されているコントラクトをImportで呼び出し、
継承すれば使用可能になる。

import "./someothercontract.sol";

contract newContract is SomeOtherContract {

}
  • 変数のStorageとMemory
    • Storageはブロックチェーン上に永久に格納される。
    • Memoryは関数呼び出し時に消去される。
  • InternalとExternal

関数宣言はprivateやpublicの宣言方法と同じ。
Internalはprivateと同じだが、このコントラクトから継承したコントラクトにもアクセスできる。
Externalはpublicと同じだが、コントラクトの外からだけ呼び出すことができる。
コントラクト内部の別の関数から呼び出すことはできない。

  function eat() internal {
  }

  function drink() external {
  }
  • interface

ブロックチェーン上の他人のコントラクトとやりとりする時に使用する。

'Ethereumのアドレスと電話番号を紐づけるコントラクト
contract PhoneNumber {
  mapping(address => uint) numbers;

  function setNum(uint _num) public {
    numbers[msg.sender] = _num;
  }

  function getNum(address _myAddress) public view returns (uint) {
    return numbers[_myAddress];
  }
}
'別のコントラクトからPhoneNumberのコントラクトを使用したい場合、Interfaceを定義する。
contract PhoneNumberInterface {
  function getNum(address _myAddress) public view returns (uint);
}

contract MyContract {
  address PhoneNumberInterfaceAddress = 0x......;
  PhoneNumberInterface phoneNumberContract = PhoneNumberInterface(PhoneNumberInterfaceAddress);

  function someFunction() public {
    uint num = phoneNumberContract.getNum(msg.sender);
  }
}
  • 複数の返り値

返り値は複数指定することができる。
特定の返り値のみ取得する場合は不要な返り値をブランクにする。

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();
}
  • If

JavaScriptと同じ

【できたもの】

ゾンビにクリプトキティを食べさせると進化する。

f:id:takuyafujita:20180729182042j:plain
f:id:takuyafujita:20180729182220j:plain

【CryptoZombiesを触ってみた】Lesson1で学んだこと

【CryptoZombiesとは】

Solidityでスマートコントラクトの構築を学習できるサイト
日本語で丁寧に説明してくれるので、プログラミングやったことない人でも学習できる。

cryptozombies.io

【はじめに】

Solidityは未経験ですが、JavaScriptは触ったことがあります。
そんな人が自分用の学習メモとして書いています。

【学んだこと】

  • contractの書き方、お作法
  • 変数宣言
  • 四則演算

Solidityは指数演算子もサポートしている。

uint x = 5 ** 2; // 5^2 = 25 と同様

※cryptozombies より引用

  • 構造体と配列の操作は他のプログラミングと同じ
  • 関数
    • グローバル変数と区別をつけるために、引数の変数名にアンダースコアをつける。
    • スコープ(public、private)を指定する位置が後ろ
    • privateにする場合は引数同様、関数名にもアンダースコアをつける。
    • 修飾子
      • view:データの読み取り専用で編集できない。
      • pure:アプリ内のデータにアクセスできない。戻り値が関数の引数のみに依存する。
function _generateRandomDna(string _str) private view returns (uint) {
}

※cryptozombies より引用

  • 型のキャスト
  • Event(イベント)

ブロックチェーンで何かが生じたとき、
コントラクトがアプリのフロントエンドに伝えることができる。

event NewZombie(uint zombieId, string name, uint dna);

function _createZombie(string _name, uint _dna) private {
    uint id = zombies.push(Zombie(_name, _dna)) - 1;
    NewZombie(id, _name, _dna); // イベント発生、フロントエンドに通知
} 

※cryptozombies より引用

【できたもの】

ゾンビの名前を入力すると、オリジナルのゾンビを作成してくれる。

f:id:takuyafujita:20180716062638j:plain