Skip to content

Latest commit

 

History

History
239 lines (169 loc) · 13.9 KB

README.md

File metadata and controls

239 lines (169 loc) · 13.9 KB

SolidityLearing

Solidityの細かい仕様まで学習するためのリポジトリ

Visibility

Functions can be declared as

  • public - any contract and account can call
  • private - only inside the contract that defines the function
  • internal- only inside contract that inherits an internal function
  • external - only other contracts and accounts can call

receive()とfallback()の違い

How to receive Ether? A contract receiving Ether must have at least one of the functions below

  • receive() external payable
  • fallback() external payable receive() is called if msg.data is empty, otherwise fallback() is called.

receive()はトランザクションのインプットデータが空の時のもの、つまり純粋な送金処理時に呼ばれる。それ以外の 場合にはfallback()が呼び出される。

DelegateCallとは

delegatecall is a low level function similar to call.

When contract A executes delegatecall to contract B, B's code is executed

with contract A's storage, msg.sender and msg.value.

Slotとは

solidiyでは32byteを1つの区切りとして認識する。

mload()とは

引数にした変数の長さを求めるメソッド

inline assemblyを使う意味

solidityでinline assemblyを使うメリットとして以下が挙げられると思います。

  1. コンパイラの制約を無視した実装ができる
  2. ガス代が浮く
  3. inline assemblyでしかできない操作を実現できる

Self Destruct

Contracts can be deleted from the blockchain by calling selfdestruct.
selfdestruct sends all remaining Ether stored in the contract to a designated address.

SolidityのSlot

solidityでは、32バイトのデータを1スロットとして考える。

delegateCallについて

Delegatecallとは、外部コントラクトへの呼び出しに対して呼び出し元のコントラクトの文脈で処理する関数です。ここで言う「コントラクトの文脈」とは、msg.senderやmsg.value、コントラクトのストレージのことなどを指しています。

delegatecallの場合は外部コントラクトの関数を自身のコントラクトのストレージ文脈で処理することが可能になります。

delegateCallを実行する場合の注意事項

  1. delegatecall preserves context (storage, caller, etc...)
  2. s2torage layout must be the same for the contract calling delegatecall and the contract getting called

blockhashとblock.timestampのランダム性

blockhashとblock.timestampはランダム性を確保するための信頼できるソースではありません。

tx.originとmsg.senderの違い

msg.senderには、EOAとコントラクトアドレスの2種類が入り得る。tx.originにはEOAしか入らない。

例えば、アカウントAからコントラクトBを呼び出し、コントラクトBから別のコントラクトCを呼び出したとき、 コントラクトC内でmsg.senderはコントラクトBを指し、tx.originはアカウントAを指す。

tx.originを使用すると想定とは異なるアドレスが入ってくる可能性(本当はコントラクトのアドレスである必要がある場合)があり、セキュリティ的にリスクがあるため、tx.originの使用は控えた方が良いことになっている。

コミットメント方式について

コミットメント方式を使うことでトランザクションの中身を秘密にしたまた送信することができる。

block.timestampについて

block.timestampについては、任意に操作できてしまう可能性があるので乱数などの用途には使わないこと。
強力なマイナーであれば、未来のblock.timestampからスマコンのロジックを読み解いて逆算される可能性があるため。(The Mergeでも発生する??)

スマートコントラクトで署名データを利用する場合

署名ロジックをうまく活用すればメタトランザクションなどの応用に利用できるが、注意しないと脆弱性を突かれる可能性があるのでよく考えて設計する必要がある。
同じ署名を複数回使用して関数を実行することができるので、署名者の意図が一度の取引を承認することであった場合、有害である可能性が出てくる。
なので一回きりの署名であることを証明するためにナンスを含める必要がある。ナンスは、通常のトランザクションをsubmitする際に取得できるのでその値を埋め込むこと!

// コントラクトのアドレス、送信先、総金額、ナンスを含めて署名データを生成するようにする。
keccak256(abi.encodePacked(address(this), _to, _amount, _nonce));

Vaultとは

DeFiプロトコルで使用される資金用の保管庫のこと。
ユーザーが入金すると、ある程度の量のシェアがミントされる。DeFiプロトコルは、ユーザーの預金を利用して(何らかの形で)利回りを発生させる。ユーザーは、自分のトークン+利回りを引き出す。

Constant product AMM

Constant product AMM XY = K

Proxyコントラクトとは

ユーザーのトランザクション送信をUpgradableコントラクトへ届ける役割のコントラクトのこと。つまりdelegatecall関数を実行するコントラクトとなる。Proxyコントラクトにはfallback関数にdelegate関数を実装している。この仕組みを上手く利用することでProxyコントラクトに記述されていない関数はfallback関数に定義されている処理を実行する形となる。

実装例は下記の通り。
delegatecallの引数の内容は下記の通り

  • gas:この呼び出しのために与えるgas量です。gas opcodeは処理のために利用可能なgas量を返します。
  • _impl:delegatecall先のコントラクトアドレス
  • ptr:上で定義したメモリポインタ。calldataを適用するため。
  • calldatasize:msg.data.lengthと同じのデータサイズ
  • 0:delegatecall先コントラクトの関数から返される出力データ。現時点ではこのデータは分からないので使わない。
  • 0:出力データのサイズ。これ以降、returndetasize opcodeで使用することができる。
function () payable public {
    address _impl = implementation();
    require(_impl != address(0));
 
    assembly {
      let ptr := mload(0x40)  // フリーメモリポインタ
      calldatacopy(ptr, 0, calldatasize) // calldataをコピーする処理 (msg.data.lengthと同じです)
      let result := delegatecall(gas, _impl, ptr, calldatasize, 0, 0)  // delegatecall opcodeの操作
      let size := returndatasize
      returndatacopy(ptr, 0, size)
 
      switch result //  成功したら1 失敗したら0が格納される
      case 0 { revert(ptr, size) }
      default { return(ptr, size) }
    }
}

MasterChef Contractとは

Dexにおける流動性提供をしたときに取得できる LP-Token を Stake することで得られる収益を計算するためのスマートコントラクトのこと。

unchecked

ガス代を安くする上で使えるのがuncheckedである。

selfdestructとは

コントラクトを壊すメソッド。コントラクトを破棄した呼び出し元にコントラクトが所持していたEtherを全て送金することができる。

calldataついて

EVM(Ethereum Virtual Machine)でコードを実行する際にstack、memory、storage、calldata、returndataの5つのデータ領域がある。 calldataはcallまたはdelegatecallで別のコントラクトを呼び出す時に使用するデータ領域で、calldataはbytes型で表される。

calldataは2つのサブパートに分けることができる。

  • メソッドID(4バイト)
  • 引数(32バイト)※引数が複数ある場合もある

最終的なcalldataはこの2つを連結させたもの。

メソッドIDについて

メソッドIDは、メソッドシグネチャのkecccak256ハッシュの先頭8文字で表される。 メソッドシグネチャは、メソッドの名前とその引数の型のこと。

例 
メソッドの名前  -->  transferFrom
引数の型  -->  (address, address, uint256)
メソッドシグネチャ  -->  transferFrom(address, address, uint256)
kecccak256ハッシュの先頭8文字  -->  web3.abi.encodeFunctionSignature('transferFrom(address,address,uint256)')  -->  0x4a6e9f4e
0x4a6e9f4eがメソッドIDとなる
引数の場合について

calldataの引数部分の求め方

例
transferFrom(0x0123456789abcdef01223456789abcdef0123456, 0xabcdef0123456789abcdef0123456789abcdef01, 30)

0x0123456789abcdef01223456789abcdef0123456を32バイトにする  -->  0x0000000000000000000000000123456789abcdef01223456789abcdef0123456
0xabcdef0123456789abcdef0123456789abcdef01を32バイトにする  -->  0x000000000000000000000000abcdef0123456789abcdef0123456789abcdef01
30を32バイトにする  -->  0x000000000000000000000000000000000000000000000000000000000000001d
連結する  -->  0x0000000000000000000000000123456789abcdef01223456789abcdef0123456000000000000000000000000abcdef0123456789abcdef0123456789abcdef01000000000000000000000000000000000000000000000000000000000000001d

スリッページとは

スリッページとは、お客様の注文レートと実際に約定したレートの差のこと。

参考文献

  1. Solidity by Example
  2. Smart Contract Engineer
  3. Solidity Inline Assembly で気になったことをまとめる
  4. Solidityのストレージスロットとパッキングについて
  5. Gitpod
  6. ChainIDE
  7. How do I make my DAPP "Serenity-Proof?"
  8. 【Solidity】tx.originとmsg.senderの違い
  9. forge-std
  10. foundry-rs/foundry
  11. UniswapV3
  12. Weird ERC20
  13. アップグレード可能なスマートコントラクトを実現する具体的なアプローチ
  14. pancake-farm
  15. 【UNCHAIN-dev】openzeppelin-deepdive
  16. Foundry book
  17. BBB 資料
  18. How to become a smart contract auditor
  19. 【sherlock】GMX contest
  20. 【Secureum】Audit Findings 101
  21. イーサの送金とリエントランシー攻撃
  22. Reentrancy | Hack Solidity #1
  23. 日本円ハッカソン入門ラボ
  24. [図解] delegatecall callcode call の違い
  25. solidityのcalldataの求め方
  26. スマートコントラクトを使った入金システムについて全力で理解してみた
  27. ERC-20と ERC-721の主な違い
  28. 第二回コントラクト輪読会レポート〜ERC721のコントラクトを皆で読みながら理解を深めよう〜
  29. Writing Upgradeable Contracts
  30. Dex(分散型取引所)の一つであるPancakeSwapを開発面から理解する
  31. Caviar contest
  32. Uniswap v2-core
  33. DefiLlama
  34. backed protocol
  35. PuttyV2 protocol
  36. 【GitHub】Caviar contest
  37. Caviar contest
  38. 【Solidity】mapping key が存在しない場合を判定する
  39. Solidity Assembly入門 ~ 配列について storage/memory ~
  40. Caviar Demo
  41. Solidity開発ツール、Foundryの紹介
  42. AMM型NFTマーケットプレイスの仕組みとは