- Go back to TOP(インデックスページへ)
- References
- Account Storage
- Authorized account references
- Capabilities
- Transactions
- Types
- Access Control
これは、Cadence開発者がより安全なCadenceコードを記述するために従うべきベストプラクティスの意見リストです。
以下に列挙するプラクティスは、こちらもお読いただくことをお勧めしてますが、Cadence Anti-Patternsセクションのアドバイスと一部重複する可能性があります。
References
Referenceは一時的な値であり、保存することができません。永続性を求める場合は、Capabilityを保存し必要に応じてborrowすることで対応します。
機能をCapabilityとして公開する時は、必要最低限のアクセス権限のみを提供します。承認済み参照を作成する時は、必要とされる目的の機能を実現するための最小限の権限(Entitlement)をセットして作成します。
Account Storage
ユーザーのアカウントストレージを信用してはいけない。ユーザーは自分のデータに対して完全な制御権限を持つので必要に応じてデータを再編成することができます。ユーザーは任意のパスに値を保存できるため、パスには「予期しない」型の値が保存される可能性があります。これらの値は、ユーザーがデプロイしたスマートコントラクトに含まれている型のインスタンスである可能性があります。
常に、期待される特定の型でborrowすること。または、値が期待される型のインスタンスであるかどうかを確認すること。
Authorized account references
承認済みアカウント参照(auth(...) &Account
)へのアクセスは、アカウントのストレージ、キー、コントラクトなど、権限が必要なオペレーションに対するアクセスを許可します。
したがって、権限を持つアカウント参照を関数に渡すことは避け、関数を定義する時は必要な操作を行うだけの権限の粒度が細かいアカウント参照パラメータを指定します。
アカウントデータを公開する際は、アカウントストレージへの直接的なアクセスよりもCapabilityを使用することが推奨されます。Capabilityを使用することでアクセスを取り消したり、特定の機能セットの値に対するアクセスを制限することができるようになります。
Capabilities
本当に必要でない限り、発行および公開を行わないでください。公開されたCapabilityには誰でもアクセスできます。Public Accessが必要な場合は、principle of least privilege/authorityの原則に従ってください。公開されるべきフィールドやfunctionにのみCapability型がアクセスを許可していること、それ以外はアクセスを許可しないようにすることを守ってください。理想としては、未承認の参照型であるCapabilityを作成します。
フィールドや関数へのアクセスに権限を必要とする場合は、その権限が特定のフィールドや関数だけに使用されるようにし、他のフィールドや関数によって使用されることがないようにしてください。必要に応じて、新しく粒度の細かな権限(Entitlement)を導入するようにしてください。
Capabilityを公開する際、すでにCapabilityが存在している可能性があります。Capabilityを生成する前に、get
を使用して、すでにCapabilityが存在しているかどうかを確認することが望ましいです。この関数は、Capabilityが存在しない場合はnil
を返します。
Capabilityを借用(borrow)することに失敗する可能性に対処する必要がある場合は、account.check
関数を使用して、対象が存在することと有効な型であることを確認できます。
関係者以外がCapabilityにアクセスできないようにしてください。例えば、publicのディクショナリや配列などのpublicなフィールドからCapabilityにアクセスできないようにしてください。このような方法でCapabilityが公開されていると、誰でもそのCapabilityを使用して、そのCapabilityが許可するすべてのアクションを実行できるようになります。
Transactions
Cadenceのコードの監査にはトランザクションも含めるべきであり、スマートコントラクトの場合と同様、恣意的コードが含まれる可能性があるためです。加えて、トランザクションは署名者のアカウントに対するフルアクセスが許可されているからです。つまり、トランザクションは署名者のアカウントストレージ、コントラクト、およびキーを好きに操作することが許されているからです。
トランザクションに署名することによって、prepare
ブロックのパラメータ型で指定された権限によりアクセス可能なオペレーションが許されます。
例えば、アカウント参照(reference)型のauth(Storage) &Auth
は、アカウントのストレージを操作することが許されます。
トランザクションに署名する時には、権限(Entitlement)を監査することが求められます。
トランザクションを作成する際には、principle of least privilege/authorityの原則に従い、トランザクションの操作を実行するために必要な最小限かつ最も粒度が細かなアカウント権限のみをリクエストするべきです。
Types
Intersection Typesとインタフェースを使用してください。 常に可能な限り最も具体的な型を、最小権限の原則に従い使用してください。 型は常に可能な限り制限的であるべきであり、特にリソース型の場合はそうあるべきです。
より曖昧な型が関数の引数に定義されている場合、期待値より具体的な型にキャストするべきす。 例えば、fungible token standardを実装する場合、ユーザーは任意のfungible tokenを預けることができてしまうため、実装においては想定している具体的なfungible token型にキャストする必要があります。
Access Control
フィールドをaccess(all)
として宣言していると、そのフィールドの値の変更を防げますが、フィールドの値の性質は変わりませんのでそれ自体の値、つまり、ディクショナリや配列などコンテナ型の中の値は変更が可能であることを忘れないでください。
変更が可能なフィールドに対してはNon-Publicアクセスにする事が望ましいです。変更可能なフィールドはネストされている可能性もあります。例えば、親が変更不可アクセス権限でフィールドに公開している場合でも、子は変更される可能性があります。
必要がない限り、access(all)
修飾子をフィールドに使用しないでください。コントラクト内の他の型がアクセスする必要がある(補足: Cadenceではリソース宣言自体が型ですので、ここではリソース内関数内からのアクセス)場合や、アカウントがEntitlementベースでアクセスをする必要がある場合は、access(self)
、またはaccess(contract)
およびaccess(account)
修飾子を使用することが望ましいです。
翻訳元->https://cadence-lang.org/docs/security-best-practices