問題一覧に戻る
上級高度なパターン
問題94: メタトランザクション

Solidityのメタトランザクションを学習 - EIP-2771実装によるガスレストランザクション。メタトランザクションはユーザーがガス用ETHを保有せずにコントラクトと相互作用でき、ユーザー体験を向上。リレイヤーがガス料金を支払い、ユーザーはオフチェーンでトランザクションデータに署名。EIP-712はセキュリティのためドメイン分離を持つ構造化データ署名を提供。このパターンは主流採用、ウォレットレスオンボーディング、ガス複雑性が抽象化されたユーザーフレンドリーDeFiアプリ作成に不可欠です。

pragma solidity ^0.8.0;

contract MetaTransaction {
mapping(address => uint256) public nonces;

// EIP712ドメインセパレーターハッシュ
bytes32 private constant = keccak256(
"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"
);

// メタトランザクション型ハッシュ
bytes32 private constant = keccak256(
"MetaTx(address from,address to,uint256 value,uint256 nonce)"
);

struct MetaTx {
address from;
address to;
uint256 value;
uint256 nonce;
}

function executeMetaTransaction(
MetaTx memory metaTx,
bytes memory signature
) public {
// 署名の真正性を検証
address signer = ();
require(signer == metaTx.from, "Invalid signature");

// nonceをチェックして増加
require(nonces[metaTx.from] == metaTx.nonce, "Invalid nonce");
[metaTx.from]++;

// トランザクションを実行
(bool success, ) = metaTx.to.call{value: metaTx.value}("");
require(success, "Transaction failed");
}

function verifySignature(
MetaTx memory metaTx,
bytes memory signature
) internal view returns (address) {
// EIP712ハッシュを作成
bytes32 digest = keccak256(abi.encodePacked(
"\x19\x01",
(),

));

// 署名者アドレスを復元
return );
}

function hashMetaTx(MetaTx memory metaTx) internal pure returns (bytes32) {
// メタトランザクションデータをエンコード
return keccak256(abi.encode(
,
metaTx.from,
metaTx.to,
metaTx.value,
metaTx.nonce
));
}

function domainSeparator() internal view returns (bytes32) {
// ドメインセパレーターを生成
return keccak256(abi.encode(
,
keccak256("MetaTransaction"),
keccak256("1"),
block.chainid,
address(this)
));
}
}