2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

EtherscanのDecompile機能の使い方

Last updated at Posted at 2022-02-03

EtherscanのDecompile機能

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

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

手順

今回は僕が初めてメインネットにデプロイしたコントラクトの復元をおこなっていきます。

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

Screen Shot 2022-02-03 at 14.09.58.png

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

Screen Shot 2022-02-03 at 14.10.13.png

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

Screen Shot 2022-02-03 at 14.10.48.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や、マーケットのロジックを分析する際にも使えるのでぜひ試してみてください!

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

2
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
2
1

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?