
スマートコントラクトマキシのみなさん、 Solidityコンパイラが、あなたのソースコードには存在しないにもかかわらず必要なストアを静かに削除していた可能性があります。 Solidity 0.8.38は先週木曜日にリリースされました。 このバージョンでは、0.8.19から0.8.37までのすべてのリリースに含まれていたYulオプティマイザのバグを修正しています。 オプティマイザは、メモリとストレージに何が格納されているかを記録し、その記録を使って、既に知っている値でロードを置き換えたり、すでに存在する値を書き込むストアをスキップしたりします。 2つのアドレスが重複するかどうかを判断するため、オプティマイザはそれぞれのアドレスを「ベース変数+オフセット」で表現します。ベースが同じでオフセットが異なる場合、異なるスロットであると判断されます。これらの表現はキャッシュされていました。 その後、誰かがベース変数を再割り当てします。オプティマイザは常にその変更に気づくとは限りません。 今や、古い値から構築されたアドレスと新しい値から構築されたアドレスを、同じベースを持つものとして比較してしまいます。オプティマイザはこれらが異なると判断しますが、実行時には同じ場所を指しています。 その結果、古くなった記録が残ります。 後続のロードが古い値を返す可能性があります。 必要なストアが削除される可能性があります。 その場所に対するkeccak256は、古くなったデータをハッシュしてしまう可能性があります。 オプティマイザを有効にしてコンパイルされたコードのみが影響を受けます。 via-IRを使用する場合、インラインアセンブリがなくてもすべてのコードが影響を受けます。 デフォルトのレガシーパイプラインでは、一部のインラインアセンブリとコンパイラが生成するヘルパー関数のみが影響を受けます。 最適化されていないビルドは安全です。 開発チームはこのバグの深刻度を低めと評価しており、私はすべてのコンパイラチームに望むような対応を行いました。 彼らはSourcifyデータベース内のすべての検証済みコントラクトを、修正前と修正後でそれぞれ再コンパイルし、すべてのバイトコードが同一であることを確認しました。 したがって、このバグは稀です。 稀であることは「決して発生しない」と同じではありません。特に、あなたのコードが新しく、まだデプロイされていない場合です。 このバグはEthereum Foundationのバグバウンティプログラムを通じて発見され、その後の別の報告では、アセンブリを使用しない通常のSolidityコードでもこのバグを引き起こせることを示しました。
