Merge pull request #1245 from poanetwork/wsa-jason-decode-error

Fix Jason decode error validating contracts
pull/1252/head
William Sanches 6 years ago committed by GitHub
commit 5a3787da8b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 5
      apps/block_scout_web/test/block_scout_web/features/pages/contract_verify_page.ex
  2. 9
      apps/explorer/lib/explorer/chain/smart_contract.ex
  3. 9
      apps/explorer/lib/explorer/smart_contract/publisher.ex
  4. 26
      apps/explorer/lib/explorer/smart_contract/solidity/code_compiler.ex
  5. 492
      apps/explorer/package-lock.json
  6. 2
      apps/explorer/package.json
  7. 28
      apps/explorer/priv/compile_solc.js
  8. 22
      apps/explorer/test/explorer/smart_contract/solidity/code_compiler_test.exs

@ -39,10 +39,7 @@ defmodule BlockScoutWeb.ContractVerifyPage do
end end
def validation_error do def validation_error do
css( css("[data-test='contract-source-code-error']")
"[data-test='contract-source-code-error']",
text: "there was an error validating your contract, please try again."
)
end end
def verify_and_publish(session) do def verify_and_publish(session) do

@ -45,10 +45,15 @@ defmodule Explorer.Chain.SmartContract do
|> unique_constraint(:address_hash) |> unique_constraint(:address_hash)
end end
def invalid_contract_changeset(%__MODULE__{} = smart_contract, attrs) do def invalid_contract_changeset(%__MODULE__{} = smart_contract, attrs, error) do
smart_contract smart_contract
|> cast(attrs, [:name, :compiler_version, :optimization, :contract_source_code, :address_hash]) |> cast(attrs, [:name, :compiler_version, :optimization, :contract_source_code, :address_hash])
|> validate_required([:name, :compiler_version, :optimization, :address_hash]) |> validate_required([:name, :compiler_version, :optimization, :address_hash])
|> add_error(:contract_source_code, "there was an error validating your contract, please try again.") |> add_error(:contract_source_code, error_message(error))
end end
defp error_message(:compilation), do: "There was an error compiling your contract."
defp error_message(:generated_bytecode), do: "Bytecode does not match, please try again."
defp error_message(:name), do: "Wrong contract name, please try again."
defp error_message(_), do: "There was an error validating your contract, please try again."
end end

@ -28,8 +28,8 @@ defmodule Explorer.SmartContract.Publisher do
{:ok, %{abi: abi}} -> {:ok, %{abi: abi}} ->
publish_smart_contract(address_hash, params, abi) publish_smart_contract(address_hash, params, abi)
{:error, _} -> {:error, error} ->
{:error, unverified_smart_contract(address_hash, params)} {:error, unverified_smart_contract(address_hash, params, error)}
end end
end end
@ -39,13 +39,14 @@ defmodule Explorer.SmartContract.Publisher do
|> Chain.create_smart_contract() |> Chain.create_smart_contract()
end end
defp unverified_smart_contract(address_hash, params) do defp unverified_smart_contract(address_hash, params, error) do
attrs = attributes(address_hash, params) attrs = attributes(address_hash, params)
changeset = changeset =
SmartContract.invalid_contract_changeset( SmartContract.invalid_contract_changeset(
%SmartContract{address_hash: address_hash}, %SmartContract{address_hash: address_hash},
attrs attrs,
error
) )
%{changeset | action: :insert} %{changeset | action: :insert}

@ -53,9 +53,8 @@ defmodule Explorer.SmartContract.Solidity.CodeCompiler do
"type" => "function" "type" => "function"
} }
], ],
"bytecode" => "6080604052600436106049576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806360fe47b114604e5780636d4ce63c146078575b600080fd5b348015605957600080fd5b5060766004803603810190808035906020019092919050505060a0565b005b348015608357600080fd5b50608a60aa565b6040518082815260200191505060405180910390f35b8060008190555050565b600080549050905600a165627a7a72305820235fceab083d33bf112b473c85551306a29f32dcdc7e95b4dfdd697c1db188ec0029", "bytecode" => "6080604052600436106049576000357c0100000000000000000000000000000000000000000000000000000000900463ffffffff16806360fe47b114604e5780636d4ce63c146078575b600080fd5b348015605957600080fd5b5060766004803603810190808035906020019092919050505060a0565b005b348015608357600080fd5b50608a60aa565b6040518082815260200191505060405180910390f35b8060008190555050565b600080549050905600a165627a7a72305820834bdab406d80509618957aa1a5ad1a4b77f4f1149078675940494ebe5b4147b0029",
"name" => "SimpleStorage", "name" => "SimpleStorage"
"opcodes" => "PUSH1 0x80 PUSH1 0x40 MSTORE CALLVALUE DUP1 ISZERO PUSH2 0x10 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0xDF DUP1 PUSH2 0x1F PUSH1 0x0 CODECOPY PUSH1 0x0 RETURN STOP PUSH1 0x80 PUSH1 0x40 MSTORE PUSH1 0x4 CALLDATASIZE LT PUSH1 0x49 JUMPI PUSH1 0x0 CALLDATALOAD PUSH29 0x100000000000000000000000000000000000000000000000000000000 SWAP1 DIV PUSH4 0xFFFFFFFF AND DUP1 PUSH4 0x60FE47B1 EQ PUSH1 0x4E JUMPI DUP1 PUSH4 0x6D4CE63C EQ PUSH1 0x78 JUMPI JUMPDEST PUSH1 0x0 DUP1 REVERT JUMPDEST CALLVALUE DUP1 ISZERO PUSH1 0x59 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x76 PUSH1 0x4 DUP1 CALLDATASIZE SUB DUP2 ADD SWAP1 DUP1 DUP1 CALLDATALOAD SWAP1 PUSH1 0x20 ADD SWAP1 SWAP3 SWAP2 SWAP1 POP POP POP PUSH1 0xA0 JUMP JUMPDEST STOP JUMPDEST CALLVALUE DUP1 ISZERO PUSH1 0x83 JUMPI PUSH1 0x0 DUP1 REVERT JUMPDEST POP PUSH1 0x8A PUSH1 0xAA JUMP JUMPDEST PUSH1 0x40 MLOAD DUP1 DUP3 DUP2 MSTORE PUSH1 0x20 ADD SWAP2 POP POP PUSH1 0x40 MLOAD DUP1 SWAP2 SUB SWAP1 RETURN JUMPDEST DUP1 PUSH1 0x0 DUP2 SWAP1 SSTORE POP POP JUMP JUMPDEST PUSH1 0x0 DUP1 SLOAD SWAP1 POP SWAP1 JUMP STOP LOG1 PUSH6 0x627A7A723058 KECCAK256 0x23 0x5f 0xce 0xab ADDMOD RETURNDATASIZE CALLER 0xbf GT 0x2b 0x47 EXTCODECOPY DUP6 SSTORE SGT MOD LOG2 SWAP16 ORIGIN 0xdc 0xdc PUSH31 0x95B4DFDD697C1DB188EC002900000000000000000000000000000000000000 "
} }
} }
""" """
@ -71,25 +70,20 @@ defmodule Explorer.SmartContract.Solidity.CodeCompiler do
] ]
) )
with %{"contracts" => contracts} <- Jason.decode!(response), with {:ok, contracts} <- Jason.decode(response),
%{"interface" => abi, "runtimeBytecode" => bytecode, "opcodes" => opcodes} <- %{"abi" => abi, "evm" => %{"deployedBytecode" => %{"object" => bytecode}}} <-
get_contract_info(contracts, name) do get_contract_info(contracts, name) do
{ {:ok, %{"abi" => abi, "bytecode" => bytecode, "name" => name}}
:ok,
%{
"abi" => Jason.decode!(abi),
"bytecode" => bytecode,
"name" => name,
"opcodes" => opcodes
}
}
else else
{:error, %Jason.DecodeError{}} ->
{:error, :compilation}
error -> error ->
parse_error(error) parse_error(error)
end end
end end
def get_contract_info(contracts, _) when contracts == %{}, do: %{"errors" => []} def get_contract_info(contracts, _) when contracts == %{}, do: {:error, :compilation}
def get_contract_info(contracts, name) do def get_contract_info(contracts, name) do
new_versions_name = ":" <> name new_versions_name = ":" <> name
@ -106,9 +100,9 @@ defmodule Explorer.SmartContract.Solidity.CodeCompiler do
end end
end end
def parse_error({:error, :name} = error), do: error
def parse_error(%{"error" => error}), do: {:error, [error]} def parse_error(%{"error" => error}), do: {:error, [error]}
def parse_error(%{"errors" => errors}), do: {:error, errors} def parse_error(%{"errors" => errors}), do: {:error, errors}
def parse_error({:error, _} = error), do: error
defp optimize_value(false), do: "0" defp optimize_value(false), do: "0"
defp optimize_value("false"), do: "0" defp optimize_value("false"), do: "0"

@ -13,6 +13,11 @@
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz",
"integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c="
}, },
"bindings": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/bindings/-/bindings-1.3.1.tgz",
"integrity": "sha512-i47mqjF9UbjxJhxGf+pZ6kSxrnI3wBLlnGI2ArWJ4r0VrvDS7ZYXkprq/pLaBWYq4GM0r4zdHY+NNRqEMU7uew=="
},
"brace-expansion": { "brace-expansion": {
"version": "1.1.11", "version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
@ -22,56 +27,48 @@
"concat-map": "0.0.1" "concat-map": "0.0.1"
} }
}, },
"builtin-modules": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz",
"integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8="
},
"camelcase": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-3.0.0.tgz",
"integrity": "sha1-MvxLn82vhF/N9+c7uXysImHwqwo="
},
"cliui": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz",
"integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=",
"requires": {
"string-width": "^1.0.1",
"strip-ansi": "^3.0.1",
"wrap-ansi": "^2.0.0"
}
},
"code-point-at": { "code-point-at": {
"version": "1.1.0", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz",
"integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c="
}, },
"command-exists": {
"version": "1.2.8",
"resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.8.tgz",
"integrity": "sha512-PM54PkseWbiiD/mMsbvW351/u+dafwTJ0ye2qB60G1aGQP9j3xK2gmMDc+R34L3nDtx4qMCitXT75mkbkGJDLw=="
},
"concat-map": { "concat-map": {
"version": "0.0.1", "version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
"integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s="
}, },
"cross-spawn": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz",
"integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=",
"requires": {
"lru-cache": "^4.0.1",
"shebang-command": "^1.2.0",
"which": "^1.2.9"
}
},
"decamelize": { "decamelize": {
"version": "1.2.0", "version": "1.2.0",
"resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
"integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA="
}, },
"error-ex": { "execa": {
"version": "1.3.2", "version": "0.7.0",
"resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz",
"integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=",
"requires": { "requires": {
"is-arrayish": "^0.2.1" "cross-spawn": "^5.0.1",
} "get-stream": "^3.0.0",
}, "is-stream": "^1.1.0",
"find-up": { "npm-run-path": "^2.0.0",
"version": "1.1.2", "p-finally": "^1.0.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz", "signal-exit": "^3.0.0",
"integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8=", "strip-eof": "^1.0.0"
"requires": {
"path-exists": "^2.0.0",
"pinkie-promise": "^2.0.0"
} }
}, },
"fs-extra": { "fs-extra": {
@ -96,6 +93,11 @@
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz", "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.2.tgz",
"integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U=" "integrity": "sha1-9wLmMSfn4jHBYKgMFVSstw1QR+U="
}, },
"get-stream": {
"version": "3.0.0",
"resolved": "http://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
"integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ="
},
"glob": { "glob": {
"version": "7.1.2", "version": "7.1.2",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.2.tgz",
@ -114,11 +116,6 @@
"resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz",
"integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg="
}, },
"hosted-git-info": {
"version": "2.6.1",
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.6.1.tgz",
"integrity": "sha512-Ba4+0M4YvIDUUsprMjhVTU1yN9F2/LJSAl69ZpzaLT4l4j5mwTS6jqqW9Ojvj6lKz/veqPzpJBqGbXspOb533A=="
},
"inflight": { "inflight": {
"version": "1.0.6", "version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
@ -138,19 +135,6 @@
"resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz",
"integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=" "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY="
}, },
"is-arrayish": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
"integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0="
},
"is-builtin-module": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz",
"integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=",
"requires": {
"builtin-modules": "^1.0.0"
}
},
"is-fullwidth-code-point": { "is-fullwidth-code-point": {
"version": "1.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz",
@ -159,10 +143,15 @@
"number-is-nan": "^1.0.0" "number-is-nan": "^1.0.0"
} }
}, },
"is-utf8": { "is-stream": {
"version": "0.2.1", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/is-utf8/-/is-utf8-0.2.1.tgz", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
"integrity": "sha1-Sw2hRCEE0bM2NA6AeX6GXPOffXI=" "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ="
},
"isexe": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
"integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA="
}, },
"jsonfile": { "jsonfile": {
"version": "2.4.0", "version": "2.4.0",
@ -172,6 +161,17 @@
"graceful-fs": "^4.1.6" "graceful-fs": "^4.1.6"
} }
}, },
"keccak": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/keccak/-/keccak-1.4.0.tgz",
"integrity": "sha512-eZVaCpblK5formjPjeTBik7TAg+pqnDrMHIffSvi9Lh7PQgM1+hSzakUeZFCk9DVVG0dacZJuaz2ntwlzZUIBw==",
"requires": {
"bindings": "^1.2.1",
"inherits": "^2.0.3",
"nan": "^2.2.1",
"safe-buffer": "^5.1.0"
}
},
"klaw": { "klaw": {
"version": "1.3.1", "version": "1.3.1",
"resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz", "resolved": "https://registry.npmjs.org/klaw/-/klaw-1.3.1.tgz",
@ -188,28 +188,49 @@
"invert-kv": "^1.0.0" "invert-kv": "^1.0.0"
} }
}, },
"load-json-file": { "locate-path": {
"version": "1.1.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/load-json-file/-/load-json-file-1.1.0.tgz", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz",
"integrity": "sha1-lWkFcI1YtLq0wiYbBPWfMcmTdMA=", "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=",
"requires": { "requires": {
"graceful-fs": "^4.1.2", "p-locate": "^2.0.0",
"parse-json": "^2.2.0", "path-exists": "^3.0.0"
"pify": "^2.0.0", },
"pinkie-promise": "^2.0.0", "dependencies": {
"strip-bom": "^2.0.0" "path-exists": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
"integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU="
}
}
},
"lru-cache": {
"version": "4.1.5",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
"integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==",
"requires": {
"pseudomap": "^1.0.2",
"yallist": "^2.1.2"
} }
}, },
"lodash.assign": { "mem": {
"version": "4.2.0", "version": "1.1.0",
"resolved": "https://registry.npmjs.org/lodash.assign/-/lodash.assign-4.2.0.tgz", "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz",
"integrity": "sha1-DZnzzNem0mHRm9rrkkUAXShYCOc=" "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=",
"requires": {
"mimic-fn": "^1.0.0"
}
}, },
"memorystream": { "memorystream": {
"version": "0.3.1", "version": "0.3.1",
"resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz", "resolved": "https://registry.npmjs.org/memorystream/-/memorystream-0.3.1.tgz",
"integrity": "sha1-htcJCzDORV1j+64S3aUaR93K+bI=" "integrity": "sha1-htcJCzDORV1j+64S3aUaR93K+bI="
}, },
"mimic-fn": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz",
"integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ=="
},
"minimatch": { "minimatch": {
"version": "3.0.4", "version": "3.0.4",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz",
@ -218,15 +239,17 @@
"brace-expansion": "^1.1.7" "brace-expansion": "^1.1.7"
} }
}, },
"normalize-package-data": { "nan": {
"version": "2.4.0", "version": "2.12.0",
"resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", "resolved": "https://registry.npmjs.org/nan/-/nan-2.12.0.tgz",
"integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", "integrity": "sha512-zT5nC0JhbljmyEf+Z456nvm7iO7XgRV2hYxoBtPpnyp+0Q4aCoP6uWNn76v/I6k2kCYNLWqWbwBWQcjsNI/bjw=="
},
"npm-run-path": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",
"integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=",
"requires": { "requires": {
"hosted-git-info": "^2.1.4", "path-key": "^2.0.0"
"is-builtin-module": "^1.0.0",
"semver": "2 || 3 || 4 || 5",
"validate-npm-package-license": "^3.0.1"
} }
}, },
"number-is-nan": { "number-is-nan": {
@ -242,92 +265,57 @@
"wrappy": "1" "wrappy": "1"
} }
}, },
"os-locale": { "os-tmpdir": {
"version": "1.4.0", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", "resolved": "http://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
"integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ="
"requires": {
"lcid": "^1.0.0"
}
}, },
"parse-json": { "p-finally": {
"version": "2.2.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
"integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4="
},
"p-limit": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz",
"integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==",
"requires": { "requires": {
"error-ex": "^1.2.0" "p-try": "^1.0.0"
} }
}, },
"path-exists": { "p-locate": {
"version": "2.1.0", "version": "2.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz",
"integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s=", "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=",
"requires": { "requires": {
"pinkie-promise": "^2.0.0" "p-limit": "^1.1.0"
} }
}, },
"p-try": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz",
"integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M="
},
"path-is-absolute": { "path-is-absolute": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18="
}, },
"path-type": { "path-key": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/path-type/-/path-type-1.1.0.tgz",
"integrity": "sha1-WcRPfuSR2nBNpBXaWkBwuk+P5EE=",
"requires": {
"graceful-fs": "^4.1.2",
"pify": "^2.0.0",
"pinkie-promise": "^2.0.0"
}
},
"pify": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
"integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw="
},
"pinkie": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
"integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA="
},
"pinkie-promise": {
"version": "2.0.1", "version": "2.0.1",
"resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
"integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A="
"requires": {
"pinkie": "^2.0.0"
}
},
"read-pkg": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-1.1.0.tgz",
"integrity": "sha1-9f+qXs0pyzHAR0vKfXVra7KePyg=",
"requires": {
"load-json-file": "^1.0.0",
"normalize-package-data": "^2.3.2",
"path-type": "^1.0.0"
}
}, },
"read-pkg-up": { "pseudomap": {
"version": "1.0.1", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-1.0.1.tgz", "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
"integrity": "sha1-nWPBMnbAZZGNV/ACpX9AobZD+wI=", "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM="
"requires": {
"find-up": "^1.0.0",
"read-pkg": "^1.0.0"
}
}, },
"require-directory": { "require-directory": {
"version": "2.1.1", "version": "2.1.1",
"resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
"integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I="
}, },
"require-from-string": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-1.2.1.tgz",
"integrity": "sha1-UpyczvJzgK3+yaL5ZbZJu+5jZBg="
},
"require-main-filename": { "require-main-filename": {
"version": "1.0.1", "version": "1.0.1",
"resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz",
@ -341,6 +329,11 @@
"glob": "^7.0.5" "glob": "^7.0.5"
} }
}, },
"safe-buffer": {
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
"integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
},
"semver": { "semver": {
"version": "5.5.0", "version": "5.5.0",
"resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz", "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.0.tgz",
@ -351,45 +344,137 @@
"resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
"integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc="
}, },
"solc-js": { "shebang-command": {
"version": "0.4.20", "version": "1.2.0",
"resolved": "https://registry.npmjs.org/solc-js/-/solc-js-0.4.20.tgz", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
"integrity": "sha1-tjCVsPcatkx6fi+C7YUtCzUxTlg=", "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=",
"requires": {
"shebang-regex": "^1.0.0"
}
},
"shebang-regex": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
"integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM="
},
"signal-exit": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz",
"integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0="
},
"solc": {
"version": "0.5.1",
"resolved": "https://registry.npmjs.org/solc/-/solc-0.5.1.tgz",
"integrity": "sha512-+RJfa5zRpWBm8DhEiEScIzEzPHWppwHSp/2yV9qvM/lNr0Y8cCv2mcNiXy+R6SSV0OoskhPEfe6Fwa4QQEgxlg==",
"requires": { "requires": {
"command-exists": "^1.2.8",
"fs-extra": "^0.30.0", "fs-extra": "^0.30.0",
"keccak": "^1.0.2",
"memorystream": "^0.3.1", "memorystream": "^0.3.1",
"require-from-string": "^1.1.0", "require-from-string": "^2.0.0",
"semver": "^5.3.0", "semver": "^5.5.0",
"yargs": "^4.7.1" "tmp": "0.0.33",
} "yargs": "^11.0.0"
}, },
"spdx-correct": { "dependencies": {
"ansi-regex": {
"version": "3.0.0", "version": "3.0.0",
"resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.0.tgz", "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz",
"integrity": "sha512-N19o9z5cEyc8yQQPukRCZ9EUmb4HUpnrmaL/fxS2pBo2jbfcFRVuFZ/oFC+vZz0MNNk0h80iMn5/S6qGZOL5+g==", "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg="
},
"camelcase": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz",
"integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0="
},
"cliui": {
"version": "4.1.0",
"resolved": "https://registry.npmjs.org/cliui/-/cliui-4.1.0.tgz",
"integrity": "sha512-4FG+RSG9DL7uEwRUZXZn3SS34DiDPfzP0VOiEwtUWlE+AR2EIg+hSyvrIgUUfhdgR/UkAeW2QHgeP+hWrXs7jQ==",
"requires": {
"string-width": "^2.1.1",
"strip-ansi": "^4.0.0",
"wrap-ansi": "^2.0.0"
}
},
"find-up": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz",
"integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=",
"requires": { "requires": {
"spdx-expression-parse": "^3.0.0", "locate-path": "^2.0.0"
"spdx-license-ids": "^3.0.0"
} }
}, },
"spdx-exceptions": { "is-fullwidth-code-point": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
"integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8="
},
"os-locale": {
"version": "2.1.0", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.1.0.tgz", "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz",
"integrity": "sha512-4K1NsmrlCU1JJgUrtgEeTVyfx8VaYea9J9LvARxhbHtVtohPs/gFGG5yy49beySjlIMhhXZ4QqujIZEfS4l6Cg==" "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==",
"requires": {
"execa": "^0.7.0",
"lcid": "^1.0.0",
"mem": "^1.1.0"
}
}, },
"spdx-expression-parse": { "require-from-string": {
"version": "3.0.0", "version": "2.0.2",
"resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
"integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw=="
},
"string-width": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
"integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
"requires": { "requires": {
"spdx-exceptions": "^2.1.0", "is-fullwidth-code-point": "^2.0.0",
"spdx-license-ids": "^3.0.0" "strip-ansi": "^4.0.0"
} }
}, },
"spdx-license-ids": { "strip-ansi": {
"version": "3.0.0", "version": "4.0.0",
"resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.0.tgz", "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
"integrity": "sha512-2+EPwgbnmOIl8HjGBXXMd9NAu02vLjOO1nWw4kmeRDFyHn+M/ETfHxQUK0oXg8ctgVnl9t3rosNVsZ1jG61nDA==" "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=",
"requires": {
"ansi-regex": "^3.0.0"
}
},
"which-module": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
"integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho="
},
"yargs": {
"version": "11.1.0",
"resolved": "http://registry.npmjs.org/yargs/-/yargs-11.1.0.tgz",
"integrity": "sha512-NwW69J42EsCSanF8kyn5upxvjp5ds+t3+udGBeTbFnERA+lF541DDpMawzo4z6W/QrzNM18D+BPMiOBibnFV5A==",
"requires": {
"cliui": "^4.0.0",
"decamelize": "^1.1.1",
"find-up": "^2.1.0",
"get-caller-file": "^1.0.1",
"os-locale": "^2.0.0",
"require-directory": "^2.1.1",
"require-main-filename": "^1.0.1",
"set-blocking": "^2.0.0",
"string-width": "^2.0.0",
"which-module": "^2.0.0",
"y18n": "^3.2.1",
"yargs-parser": "^9.0.2"
}
},
"yargs-parser": {
"version": "9.0.2",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-9.0.2.tgz",
"integrity": "sha1-nM9qQ0YP5O1Aqbto9I1DuKaMwHc=",
"requires": {
"camelcase": "^4.1.0"
}
}
}
}, },
"string-width": { "string-width": {
"version": "1.0.2", "version": "1.0.2",
@ -409,33 +494,27 @@
"ansi-regex": "^2.0.0" "ansi-regex": "^2.0.0"
} }
}, },
"strip-bom": { "strip-eof": {
"version": "2.0.0", "version": "1.0.0",
"resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-2.0.0.tgz", "resolved": "http://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
"integrity": "sha1-YhmoVhZSBJHzV4i9vxRHqZx+aw4=", "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8="
},
"tmp": {
"version": "0.0.33",
"resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
"integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
"requires": { "requires": {
"is-utf8": "^0.2.0" "os-tmpdir": "~1.0.2"
} }
}, },
"validate-npm-package-license": { "which": {
"version": "3.0.3", "version": "1.3.1",
"resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.3.tgz", "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
"integrity": "sha512-63ZOUnL4SIXj4L0NixR3L1lcjO38crAbgrTpl28t8jjrfuiOBL5Iygm+60qPs/KsZGzPNg6Smnc/oY16QTjF0g==", "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
"requires": { "requires": {
"spdx-correct": "^3.0.0", "isexe": "^2.0.0"
"spdx-expression-parse": "^3.0.0"
} }
}, },
"which-module": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/which-module/-/which-module-1.0.0.tgz",
"integrity": "sha1-u6Y8qGGUiZT/MHc2CJ47lgJsKk8="
},
"window-size": {
"version": "0.2.0",
"resolved": "https://registry.npmjs.org/window-size/-/window-size-0.2.0.tgz",
"integrity": "sha1-tDFbtCFKPXBY6+7okuE/ok2YsHU="
},
"wrap-ansi": { "wrap-ansi": {
"version": "2.1.0", "version": "2.1.0",
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz",
@ -455,35 +534,10 @@
"resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz",
"integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=" "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE="
}, },
"yargs": { "yallist": {
"version": "4.8.1", "version": "2.1.2",
"resolved": "https://registry.npmjs.org/yargs/-/yargs-4.8.1.tgz", "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
"integrity": "sha1-wMQpJMpKqmsObaFznfshZDn53cA=", "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI="
"requires": {
"cliui": "^3.2.0",
"decamelize": "^1.1.1",
"get-caller-file": "^1.0.1",
"lodash.assign": "^4.0.3",
"os-locale": "^1.4.0",
"read-pkg-up": "^1.0.1",
"require-directory": "^2.1.1",
"require-main-filename": "^1.0.1",
"set-blocking": "^2.0.0",
"string-width": "^1.0.1",
"which-module": "^1.0.0",
"window-size": "^0.2.0",
"y18n": "^3.2.1",
"yargs-parser": "^2.4.1"
}
},
"yargs-parser": {
"version": "2.4.1",
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-2.4.1.tgz",
"integrity": "sha1-hVaN488VD/SfpRgl8DqMiA3cxcQ=",
"requires": {
"camelcase": "^3.0.0",
"lodash.assign": "^4.0.6"
}
} }
} }
} }

@ -13,6 +13,6 @@
}, },
"scripts": {}, "scripts": {},
"dependencies": { "dependencies": {
"solc-js": "^0.4.20-browser.1" "solc": "^0.5"
} }
} }

@ -1,6 +1,6 @@
#!/usr/bin/env node #!/usr/bin/env node
const solc = require('solc-js'); const solc = require('solc');
var sourceCode = process.argv[2]; var sourceCode = process.argv[2];
var version = process.argv[3]; var version = process.argv[3];
@ -10,6 +10,30 @@ var compiled_code = solc.loadRemoteVersion(version, function (err, solcSnapshot)
if (err) { if (err) {
console.log(JSON.stringify(err)); console.log(JSON.stringify(err));
} else { } else {
console.log(JSON.stringify(solcSnapshot.compile(sourceCode, optimize))); const input = {
language: 'Solidity',
sources: {
'New.sol': {
content: sourceCode
}
},
settings: {
evmVersion: 'byzantium',
optimizer: {
enabled: optimize == '1',
runs: 200
},
outputSelection: {
'*': {
'*': ['*']
}
}
}
}
const output = JSON.parse(solcSnapshot.compile(JSON.stringify(input)))
/** Older solc-bin versions don't use filename as contract key */
const response = output.contracts['New.sol'] || output.contracts['']
console.log(JSON.stringify(response));
} }
}); });

@ -24,8 +24,7 @@ defmodule Explorer.SmartContract.Solidity.CodeCompilerTest do
%{ %{
"abi" => _, "abi" => _,
"bytecode" => _, "bytecode" => _,
"name" => _, "name" => _
"opcodes" => _
}} = response }} = response
end end
@ -44,8 +43,7 @@ defmodule Explorer.SmartContract.Solidity.CodeCompilerTest do
%{ %{
"abi" => _, "abi" => _,
"bytecode" => _, "bytecode" => _,
"name" => _, "name" => _
"opcodes" => _
}} = response }} = response
end end
@ -75,12 +73,11 @@ defmodule Explorer.SmartContract.Solidity.CodeCompilerTest do
%{ %{
"abi" => _, "abi" => _,
"bytecode" => _, "bytecode" => _,
"name" => _, "name" => _
"opcodes" => _
}} = response }} = response
end end
test "returns a list of errors the compilation isn't possible", %{ test "returns compilation error when compilation isn't possible", %{
contract_code_info: contract_code_info contract_code_info: contract_code_info
} do } do
wrong_code = "pragma solidity ^0.4.24; cont SimpleStorage { " wrong_code = "pragma solidity ^0.4.24; cont SimpleStorage { "
@ -93,8 +90,7 @@ defmodule Explorer.SmartContract.Solidity.CodeCompilerTest do
contract_code_info.optimized contract_code_info.optimized
) )
assert {:error, errors} = response assert {:error, :compilation} = response
assert is_list(errors)
end end
end end
@ -108,16 +104,16 @@ defmodule Explorer.SmartContract.Solidity.CodeCompilerTest do
assert {:error, :name} == response assert {:error, :name} == response
end end
test "returns an empty list of errors for empty info" do test "returns compilation error for empty info" do
name = "Name" name = "Name"
response = CodeCompiler.get_contract_info(%{}, name) response = CodeCompiler.get_contract_info(%{}, name)
assert %{"errors" => []} == response assert {:error, :compilation} == response
end end
test "the contract info is returned when the name matches" do test "the contract info is returned when the name matches" do
contract_inner_info = %{"abi" => %{}, "bytecode" => "", "opcodes" => ""} contract_inner_info = %{"abi" => %{}, "bytecode" => ""}
name = "Name" name = "Name"
contract_info = %{name => contract_inner_info} contract_info = %{name => contract_inner_info}
@ -129,7 +125,7 @@ defmodule Explorer.SmartContract.Solidity.CodeCompilerTest do
test "the contract info is returned when the name matches with a `:` suffix" do test "the contract info is returned when the name matches with a `:` suffix" do
name = "Name" name = "Name"
name_with_suffix = ":Name" name_with_suffix = ":Name"
contract_inner_info = %{"abi" => %{}, "bytecode" => "", "opcodes" => ""} contract_inner_info = %{"abi" => %{}, "bytecode" => ""}
contract_info = %{name_with_suffix => contract_inner_info} contract_info = %{name_with_suffix => contract_inner_info}
response = CodeCompiler.get_contract_info(contract_info, name) response = CodeCompiler.get_contract_info(contract_info, name)

Loading…
Cancel
Save