Solidity

Solidityの関数・修飾子・エラー

関数の役割と失敗の表し方をコードで確認します。

Solidity入門の講座一覧

01

viewとpure

viewは状態を読みますが変更しません。pureは状態もブロック情報も読まず、引数だけから結果を計算します。どちらも書き込みトランザクションを作りません。

読み取りと計算SOLIDITY
contract Calculator {
    uint256 public base = 10;

    function plusBase(uint256 value) external view returns (uint256) {
        return base + value;
    }

    function double(uint256 value) external pure returns (uint256) {
        return value * 2;
    }
}
実行結果OUTPUT
plusBase(5) → 15
double(7) → 14
02

modifierで条件を再利用する

所有者チェックSOLIDITY
contract Owned {
    address public owner;

    constructor() { owner = msg.sender; }

    modifier onlyOwner() {
        require(msg.sender == owner, "owner only");
        _;
    }

    function resetOwner(address next) external onlyOwner {
        require(next != address(0), "zero address");
        owner = next;
    }
}
実行結果OUTPUT
Account 0でresetOwner(account1) → owner: Account 1
Account 1でresetOwner(account2) → owner: Account 2
Account 2でresetOwner(address(0)) → revert "zero address"
Account 0でresetOwner(account2) → revert "owner only"

_;の位置に本体が展開されます。modifierを付けるだけで条件を忘れにくくなりますが、複雑な処理をmodifierへ詰め込みすぎないようにします。

03

require、revert、assert

利用者の入力や権限の確認にはrequire、条件に応じて明示的に中断するにはrevert、絶対に成立するはずの内部不変条件にはassertを使います。失敗すると、そのトランザクション内の状態変更は巻き戻されます。

カスタムエラーSOLIDITY
contract Limited {
    error TooLarge(uint256 value);

    function accept(uint256 value) external pure returns (uint256) {
        if (value > 100) revert TooLarge(value);
        return value;
    }
}
実行結果OUTPUT
accept(80) → 80
accept(120) → revert TooLarge(120)
04

戻り値と名前付き戻り値

複数の結果を返す場合は、戻り値に名前を付けることもできます。呼び出し側が扱いやすいデータ形を最初に決めることが大切です。

05

練習

投票関数にonlyOwnerと「同じアドレスは一度だけ」というmappingの条件を追加してみましょう。次はEther・イベント・ABIです。