web-dev-qa-db-ja.com

イーサリアムのアドレスが契約であるかどうかを調べる方法は?

Solidityのアドレスは、アカウントまたは契約(またはトランザクションなどのその他のもの)にすることができます。アドレスを保持している変数xがある場合、それが契約であるかどうかをテストするにはどうすればよいですか?

(はい、ドキュメントの 型の章 を読みました)

20
bortzmeyer

編集:この答えが最初に書かれて以来、堅実性が変化しました。@manuel-aráozが正しい答えを持っています。

住所が契約であるかどうかを確認する方法はありません。イーサリアムの目標の1つは、人間とスマート契約の両方を同等に扱うことです。これは、スマートコントラクトが人間や他のコントラクトとシームレスに対話する未来につながります。将来変更される可能性がありますが、現時点では任意のアドレスはあいまいです。

4
nchinda2

はい。アドレスのコードサイズを取得するために、いくつかのEVMアセンブリコードを使用することで可能です。

function isContract(address addr) returns (bool) {
  uint size;
  Assembly { size := extcodesize(addr) }
  return size > 0;
}
49
Manuel Aráoz

これは、Solidityを使用して契約内からクエリできるものではありませんが、住所に契約コードがあるかどうかだけを知りたい場合は、gethコンソールなどを使用して確認できます。例:

  > eth.getCode("0xbfb2e296d9cf3e593e79981235aed29ab9984c0f")

16進文字列(ここでは0xbfb2e296d9cf3e593e79981235aed29ab9984c0f)クエリするアドレスとして。これにより、そのアドレスに保存されているバイトコードが返されます。

ブロックチェーンスキャナーを使用して、そのアドレスで契約のソースコードを見つけることもできます。たとえば、 etherscan.io に示すように ecsolライブラリー です。

7
bekah

EXTCODESIZEを使用するisContract関数を使用したトップ投票の回答は、ハッキング可能であることが発見されました。

関数は、コントラクトのコンストラクターから呼び出された場合にfalseを返します(コントラクトがまだデプロイされていないため)。

コードは、次のようなセキュリティハッキングを回避するために、非常に慎重に使用する必要があります。

https://www.reddit.com/r/ethereum/comments/916xni/how_to_pwn_fomo3d_a_beginners_guidearchive

宛先 繰り返し

スマートコントラクトが関数を呼び出さないようにするために、EXTCODESIZEチェックを使用しないでください。これは絶対確実ではありません。コンストラクターの実行中に、そのアドレスのEXTCODESIZEが0を返すため、コンストラクター呼び出しによって破壊される可能性があります。

EXTCODESIZEをtrickして0を返すコントラクトについては、 サンプルコード を参照してください。


EOAが契約を呼び出していることを確認したい場合、簡単な方法はrequire(msg.sender == tx.Origin)です。ただし、契約の防止は anti-pattern with security および interoperability の考慮事項です。

これは、アカウントの抽象化が実装されたときに再検討する必要があります。

1
eth

あなたができること、手元に情報があることを認めた。トランザクションの送信者アドレスがnullまたは空いている場合、アドレスが契約アカウントかEOA(外部所有アカウント)かを確認できます。すなわち、ネットワーク上で契約作成トランザクションを送信する場合、トランザクションの受信アドレスはnull /使用されません。

Githubからの参照: https://github.com/ethereum/go-ethereum/wiki/Contracts-and-Transactions

お役に立てれば。

0
Malone

短い答え:

require(tx.Origin == msg.sender);

tx.Originは、このシリアル関数呼び出しを開始する元のアドレスの参照です。一方、msg.senderは、ターゲット関数を直接呼び出すアドレスです。つまり、tx.Originは人間でなければならず、msg.senderは契約または人間にすることができます。したがって、誰かが契約からあなたを呼び出した場合、msg.senderはtx.Originとは異なる契約アドレスです。

ほとんどの契約で@ManuelAráozのコードを使用できることは知っていますが、これはほとんどの場合に機能します。ただし、コントラクトのコンストラクター内で関数を呼び出すと、extcodesizeは0を返し、isContractチェックに失敗します。

注:他の状況でtx.Originを使用しないでください。

0
user7839155