Solidity

SolidityのEther・イベント・ABI

価値の送受信と、フロントエンドが結果を追跡する仕組みを学びます。

Solidity入門の講座一覧

01

payableでEtherを受け取る

Etherを受け取る関数にはpayableを付けます。送られた金額はmsg.valueでwei単位として取得できます。1 etherは1018 weiです。

入金を記録するSOLIDITY
contract TipJar {
    mapping(address => uint256) public tips;

    function tip() external payable {
        require(msg.value > 0, "send ether");
        tips[msg.sender] += msg.value;
    }

    function total() external view returns (uint256) {
        return address(this).balance;
    }
}
実行結果OUTPUT
tip(0.1 ether) → tips[Account 0]: 0.1 ether
total() → 0.1 ether

Remix VMではValue欄の単位をEtherへ切り替えて、0.1などを入力してからtipを実行します。学習中も、残高と送金先を毎回確認します。

02

引き出し処理を設計する

コントラクトに入ったEtherを取り出す関数は、誰でも呼べる状態にしてはいけません。次の断片は、前のTipJarにfunctions章のOwnedを同じファイルへ定義し、contract TipJar is Ownedとして継承した場合のwithdrawです。ownerとonlyOwnerはOwnedから提供されます。

Ownedを継承したTipJarの引き出しSOLIDITY
function withdraw(uint256 amount) external onlyOwner {
    require(amount <= address(this).balance, "insufficient");
    (bool success, ) = payable(owner).call{value: amount}("");
    require(success, "transfer failed");
}
実行結果OUTPUT
Account 0(owner)でwithdraw(0.05 ether) → 送金成功
Account 1でwithdraw(0.05 ether) → revert "owner only"
残高不足でwithdraw → revert "insufficient"

この短い例だけを本番で使わず、再入可能性やpull paymentなどの設計を安全性の章で確認してください。

03

イベントで履歴を知らせる

入金イベントSOLIDITY
event Tipped(address indexed from, uint256 amount);

function tip() external payable {
    require(msg.value > 0, "send ether");
    emit Tipped(msg.sender, msg.value);
}
実行結果OUTPUT
tip(0.1 ether) → Tipped(from: Account 0, amount: 0.1 ether)

イベントは状態変数の代わりではなく、外部のWebアプリケーションやブロックエクスプローラーが履歴を追うためのログです。indexedを付けた項目は検索条件に使いやすくなります。

04

ABIで外部から呼び出す

ABIは関数名、引数、戻り値、イベントなどをJSON形式で表すインターフェースです。フロントエンドはABIとコントラクトアドレスを使って、読み取りやトランザクションを組み立てます。ABIが同じなら、実装の詳細を知らなくても決められた関数を呼べます。

05

練習

入金者ごとの累計額を記録し、Tippedイベントを出すTipJarを完成させましょう。次は安全なコントラクト設計です。