EtherscanのDecompile機能の使い方

## EtherscanのDecompile機能

過去に開発したイーサリアムのプロジェクトを復元する際に、ソースコードが残っておらす、Etherscanで検証・公開するのも忘れていて、となって困っていた時に、EtherscanのDecompile機能がとても便利だったので備忘録として残します。

EtherscanのDecompileは公開されてないコントラクトロジックを、完全ではないですが少しわかりやすいように分析してくれるツールです。それでは早速やってみましょう！

## 手順
今回は僕が初めてメインネットにデプロイした[コントラクト](https://etherscan.io/address/0xb8fa8adc4f1a62613461183871382909a5ab5433#code
)の復元をおこなっていきます。

こちらはコードの検証・公開を忘れていたため、Etherscanからソースコードにアクセスすることができません。そんな時はDecompile Bytecodeをクリックして

![Screen Shot 2022-02-03 at 14.09.58.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/258956/6ae40cf8-0737-0b17-8972-595f3155428d.png)

こちらのEVM bytecode decompilerというページにアクセスして、Decompileをクリックします。30秒後にリフレッシュして結果を見てね、という指示に従って、リフレッシュ後にもう一度Decompile Bytecodeをクリックします。

![Screen Shot 2022-02-03 at 14.10.13.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/258956/19368d46-e760-b948-a007-ed53d475d0d3.png)

すると、下記のようにDecompileされたコードにアクセスすることができます。

![Screen Shot 2022-02-03 at 14.10.48.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/258956/b7e81a19-e1a1-5972-faae-2d251230b00b.png)

こちら復元したコードをコピーして記載しておきます。


```
#  Decompiled source of 0xB8fA8Adc4f1a62613461183871382909a5Ab5433
# 
#  Let's make the world open source 
# 

def storage:
  unknownd84f55ee is array of struct at storage 0
  stor99 is mapping of addr at storage 99

def unknownd84f55ee(addr _param1): # not payable
  return uint256(unknownd84f55ee[addr(_param1)][0 len unknownd84f55ee[addr(_param1)].length].field_0)

#
#  Regular functions
#

def _fallback() payable: # default function
  revert

def unknowned3db67c(addr _param1): # not payable
  mem[96] = uint256(unknownd84f55ee[addr(_param1)].field_0)
  idx = 96
  s = 0
  while unknownd84f55ee[addr(_param1)].length + 96 > idx + 32:
      mem[idx + 32] = uint256(unknownd84f55ee[addr(_param1)][s].field_256)
      idx = idx + 32
      s = s + 1
      continue 
  if sha3(mem[96 len unknownd84f55ee[addr(_param1)].length]) != sha3(None):
      return 0
  return 1

def unknown1d34866f(array _param1): # not payable
  mem[128 len _param1.length] = _param1[all]
  mem[ceil32(_param1.length) + 128 len floor32(_param1.length)] = call.data[_param1 + 36 len floor32(_param1.length)]
  mem[ceil32(_param1.length) + floor32(_param1.length) + -(_param1.length % 32) + 160 len _param1.length % 32] = mem[floor32(_param1.length) + -(_param1.length % 32) + 160 len _param1.length % 32]
  mem[_param1.length + ceil32(_param1.length) + 128] = 1
  if stor[mem[ceil32(_param1.length) + floor32(_param1.length) + 128 len (_param1.length % 32) + 32]][call.data[_param1 + 36 len floor32(_param1.length)]]:
      return 0
  return 1

def getAddress(string _key): # not payable
  mem[128 len _key.length] = _key[all]
  mem[ceil32(_key.length) + 128 len floor32(_key.length)] = call.data[_key + 36 len floor32(_key.length)]
  mem[ceil32(_key.length) + floor32(_key.length) + -(_key.length % 32) + 160 len _key.length % 32] = mem[floor32(_key.length) + -(_key.length % 32) + 160 len _key.length % 32]
  mem[_key.length + ceil32(_key.length) + 128] = 1
  mem[ceil32(_key.length) + 128] = stor[mem[ceil32(_key.length) + floor32(_key.length) + 128 len (_key.length % 32) + 32]][call.data[_key + 36 len floor32(_key.length)]]
  return memory
    from ceil32(_key.length) + 128
     len 32

def registerUser(string _name): # not payable
  mem[128 len _name.length] = _name[all]
  mem[ceil32(_name.length) + 128] = uint256(unknownd84f55ee[caller].field_0)
  idx = ceil32(_name.length) + 128
  s = 0
  while ceil32(_name.length) + unknownd84f55ee[caller].length + 128 > idx + 32:
      mem[idx + 32] = uint256(unknownd84f55ee[caller][s].field_256)
      idx = idx + 32
      s = s + 1
      continue 
  require sha3(mem[ceil32(_name.length) + 128 len unknownd84f55ee[caller].length]) == sha3(None)
  mem[ceil32(_name.length) + 128 len floor32(_name.length)] = call.data[_name + 36 len floor32(_name.length)]
  mem[ceil32(_name.length) + floor32(_name.length) + -(_name.length % 32) + 160 len _name.length % 32] = mem[floor32(_name.length) + -(_name.length % 32) + 160 len _name.length % 32]
  mem[_name.length + ceil32(_name.length) + 128] = 1
  require not stor[mem[ceil32(_name.length) + floor32(_name.length) + 128 len (_name.length % 32) + 32]][call.data[_name + 36 len floor32(_name.length)]]
  uint256(unknownd84f55ee[caller][].field_0) = Array(len=_name.length, data=_name[all])
  mem[ceil32(_name.length) + 128 len floor32(_name.length)] = call.data[_name + 36 len floor32(_name.length)]
  mem[ceil32(_name.length) + floor32(_name.length) + -(_name.length % 32) + 160 len _name.length % 32] = mem[floor32(_name.length) + -(_name.length % 32) + 160 len _name.length % 32]
  mem[_name.length + ceil32(_name.length) + 128] = 1
  stor[mem[ceil32(_name.length) + floor32(_name.length) + 128 len (_name.length % 32) + 32]][call.data[_name + 36 len floor32(_name.length)]] = caller

```

公開されていないNFTや、マーケットのロジックを分析する際にも使えるのでぜひ試してみてください！

また、こちらで紹介しているツールは、より詳細に分析できるようなのでこちらも併せてどうぞ！

https://qiita.com/taijusanagi/items/b586837e37a1fce213cd

https://qiita.com/taijusanagi/items/2c9f742bd091bdba1912