コントラクトごとに複製する必要はないが、コントラクト インスタンスの状態を変更する多くの機能コードを含む外部データ用の Chainlink オラクルに依存する Solidity スマート コントラクトがあります。これが、プロキシを決定した理由です。デリゲート呼び出しを使用するパターンが最も理にかなっています。プロキシ パターンでは、コントラクト関数のバイトコードを 1 回デプロイするだけで済みます。その後、コントラクトの他のすべてのインスタンスは呼び出しを実装コントラクトに委任するだけで、ブロック チェーンに追加される新しい情報はインスタンス フィールドだけになります。その特定の契約の。
実装コントラクトを展開し、展開したプロキシをその関数に向けることができますが、プロキシでロック関数を呼び出すと、デリゲート呼び出しが渡されるはずであり、所有者フィールドを設定するrequire(owner == msg.sender,"Owner only")
ため、意味をなさないチェックに失敗しますプロキシのコンストラクターでmsg.sender
。msg.sender
必要なものを削除すると、元に戻さずに関数を呼び出すことができますが、locked
anddebugAddr
ロック関数がフィールドを変更する必要がありますが、フィールドは変更されません (呼び出し元のコンテキストでデリゲート呼び出しが実行されたと思いましたか?)。私のプロキシと実装の契約の何が問題なのか誰か知っていますか? デリゲート呼び出しを行うために使用しているメモリ レイアウトまたはアセンブリに関係していると推測できますが、グーグル スキルを使用して何が問題なのかを特定できるレベルにはまだ達していません。契約書が間違っている/形式が正しくない場合はお知らせください。
ありがとう、ベン
ロック機能のコード スニペット
//Locks in the contract, buyer should have already provided data scientist an upload only API key and their model ID
function lock() public returns (bool success)
{
debugAddr = msg.sender;
uint tempStamp = now;
//THIS IS THE REQUIRE THAT FAILS WHEN IT SHOULDNT WHEN I UNCOMMENT THIS AND DEPLOY/RUN
require(msg.sender == owner, "Only owner can lock contract.");
//require(!locked, "Cannot lock contract that is already locked.");
//require(buyer != address(0),"No buyer to lock.");
//require(bytes(buyerModelName).length != 0,"No buyerModelName to lock.");
//require((tempStamp - startTimestamp) < 158400,"Cannot lock contract that was entered by buyer over 44 hours ago.");
//require((getWeekday(tempStamp) == 0) || (getWeekday(tempStamp) == 1 && getHour(tempStamp) < 14),"Contract can only be locked in between Sunday 00:00 UTC and Monday 14:00 UTC");
LinkTokenInterface link = LinkTokenInterface(chainlinkTokenAddress());
//require(link.balanceOf(address(this)) >= totalFee, "Contract requires 0.5 LINK total to operate once locked, current LINK balance is under 0.5.");
locked = true;
return true;
}
コメントが必要なプロキシ コントラクト(コントラクトの tx も参照してください。ロックを呼び出すことができます): https://kovan.etherscan.io/address/0x1f805d559f6eb7d7b19bf0340db288503f448ae8 プロキシが指す実装コントラクト: https://kovan.etherscan.io/アドレス/0xfb41ea6452da396279cbd9d9d8c136121e38fab6
コメント解除が必要なプロキシ コントラクト(コントラクトの tx も参照してください。私がロックを呼び出し、元に戻すのを見ることができます) : https://kovan.etherscan.io/address/0x2d59aa0c1dd9a77d592167c43f2e65adcb275bfe
プロキシ コードと実装コード
参照コード: https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/proxy/Proxy.sol
プロキシ: https://github.com/benschreyer/Steak/blob/main/SteakQuarterly/ProxyPattern/SteakQuarterlyProxy.sol
重要な注意: 私のプロキシでは、コントラクトを ChainlinkClient として宣言したくありません。なぜなら、ChainlinkClient の関数がプロキシに含まれるからです。これは、実装に既にこれらのメソッドが必要なため不要です。代わりに、フィールドと ChainlinkClient を自分で宣言するだけです。これは私の実装が間違っている主要な場所のように感じますが、何を変更する必要があるか/これが実現可能かどうかはわかりません
編集: それでも失敗する最小限のコード例 このコントラクトには、ChainlinkClient のプロキシになるための最小限の要件が必要であり、ロック機能とコンストラクターのみが必要です。要求を削除すると、プロキシ コントラクトのロックの呼び出しは確認済みと表示されますが、プロキシの状態変数は変更されません (debugAddr は 0、ロックは false のままです)。
最小限のコード例を次に示します (0.6.12 をコンパイルしたリミックス IDE にデプロイしました。プロキシのロック機能は、デリゲートの abi が使用されるようにコンパイルされたデリゲート コードで at アドレス取得を使用して呼び出されました): https://github. com/benchreyer/Steak/tree/main/MinimalCodeExample
編集 2: 上記のリンクのように、プロキシと実装の最小例の ChainlinkClient 部分/フィールドを削除すると、機能するプロキシ コントラクトが取得され、実装コントラクトで定義された外部関数呼び出しを受け入れることができます。
私の質問は、Chainlink GET リクエスト機能をサポートするプロキシと実装コントラクトをどのように作成するかです。私のプロキシはどのフィールド/定数/イベント/インターフェースを定義またはインポートする必要がありますか? また、Chainlink が機能するようにするには、それらをどこで定義/インポートする必要がありますか? たとえば、コントラクトに Chainlink を介して API からパリの気温を取得させたいとしますが、すべての関数を再デプロイしてガス代を節約する必要がないように、プロキシにもなりたいとします。
プロキシのストレージとアクセス/書き込みができるようにプロキシ コントラクト クラスを構造化する方法がわからないため、Chainlink をミックスに追加すると、これまでに試したことはすべて機能しません (最小限の破壊的な例を参照)。呼び出しを実装ラインアップに委譲します。Chainlink 機能を削除した後に機能する最小限のコードは次のとおりです 。https://github.com/benschreyer/Steak/tree/main/MinimalCodeExample/WorkingButNoChainlinkオラクルを呼び出すためにプロキシ契約が必要とするフィールド/イベント/定数については、大歓迎です。