Merge pull request #2225 from poanetwork/ab-fix-metadata-decoding-for-smart-contracts

fix metadata decoding in smart contract verification
pull/2254/head
Victor Baranov 5 years ago committed by GitHub
commit b99c97841e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 3
      CHANGELOG.md
  2. 7
      apps/explorer/lib/explorer/smart_contract/verifier.ex
  3. 8
      apps/explorer/lib/explorer/smart_contract/verifier/constructor_arguments.ex
  4. 32
      apps/explorer/test/explorer/smart_contract/verifier_test.exs
  5. 76
      apps/explorer/test/support/fixture/smart_contract/solidity_0.5.9_smart_contract.sol

@ -45,8 +45,9 @@
- [#2173](https://github.com/poanetwork/blockscout/pull/2173) - handle correctly empty transactions
- [#2174](https://github.com/poanetwork/blockscout/pull/2174) - fix reward channel joining
- [#2186](https://github.com/poanetwork/blockscout/pull/2186) - fix net version test
- [#2167](https://github.com/poanetwork/blockscout/pull/2167) - feat: document eth rpc api mimicking endpoints
- [#2225](https://github.com/poanetwork/blockscout/pull/2225) - fix metadata decoding in Solidity 0.5.9 smart contract verification
- [#2204](https://github.com/poanetwork/blockscout/pull/2204) - fix large contract verification
- [#2167](https://github.com/poanetwork/blockscout/pull/2168) - feat: document eth rpc api mimicking endpoints
### Chore
- [#2127](https://github.com/poanetwork/blockscout/pull/2127) - use previouse chromedriver version

@ -107,6 +107,13 @@ defmodule Explorer.SmartContract.Verifier do
|> Enum.reverse()
|> :binary.list_to_bin()
# Solidity >= 0.5.9; https://github.com/ethereum/solidity/blob/aa4ee3a1559ebc0354926af962efb3fcc7dc15bd/docs/metadata.rst
"a265627a7a72305820" <>
<<_::binary-size(64)>> <> "64736f6c6343" <> <<_::binary-size(6)>> <> "0032" <> _constructor_arguments ->
extracted
|> Enum.reverse()
|> :binary.list_to_bin()
<<next::binary-size(2)>> <> rest ->
do_extract_bytecode([next | extracted], rest)
end

@ -21,6 +21,14 @@ defmodule Explorer.SmartContract.Verifier.ConstructorArguments do
constructor_arguments
end
# Solidity >= 0.5.9; https://github.com/ethereum/solidity/blob/aa4ee3a1559ebc0354926af962efb3fcc7dc15bd/docs/metadata.rst
defp extract_constructor_arguments(
"a265627a7a72305820" <>
<<_::binary-size(64)>> <> "64736f6c6343" <> <<_::binary-size(6)>> <> "0032" <> constructor_arguments
) do
constructor_arguments
end
defp extract_constructor_arguments(<<_::binary-size(2)>> <> rest) do
extract_constructor_arguments(rest)
end

File diff suppressed because one or more lines are too long

@ -0,0 +1,76 @@
pragma solidity ^0.5.9;
contract Token {
function totalSupply() public view returns (uint256 supply) {}
function balanceOf(address _owner) public view returns (uint256 balance) {}
function transfer(address _to, uint256 _value) public returns (bool success) {}
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) {}
function approve(address _spender, uint256 _value) public returns (bool success) {}
function allowance(address _owner, address _spender) public view returns (uint256 remaining) {}
event Transfer(address indexed _from, address indexed _to, uint256 _value);
event Approval(address indexed _owner, address indexed _spender, uint256 _value);
}
contract StandardToken is Token {
function transfer(address _to, uint256 _value) public returns (bool success) {
//if (balances[msg.sender] >= _value && balances[_to] + _value > balances[_to]) {
if (balances[msg.sender] >= _value && _value > 0) {
balances[msg.sender] -= _value;
balances[_to] += _value;
emit Transfer(msg.sender, _to, _value);
return true;
} else { return false; }
}
function transferFrom(address _from, address _to, uint256 _value) public returns (bool success) {
//if (balances[_from] >= _value && allowed[_from][msg.sender] >= _value && balances[_to] + _value > balances[_to]) {
if (balances[_from] >= _value && allowed[_from][msg.sender] >= _value && _value > 0) {
balances[_to] += _value;
balances[_from] -= _value;
allowed[_from][msg.sender] -= _value;
emit Transfer(_from, _to, _value);
return true;
} else { return false; }
}
function balanceOf(address _owner) public view returns (uint256 balance) {
return balances[_owner];
}
function approve(address _spender, uint256 _value) public returns (bool success) {
allowed[msg.sender][_spender] = _value;
emit Approval(msg.sender, _spender, _value);
return true;
}
function allowance(address _owner, address _spender) public view returns (uint256 remaining) {
return allowed[_owner][_spender];
}
mapping (address => uint256) balances;
mapping (address => mapping (address => uint256)) allowed;
uint256 totalTokenSupply;
}
contract TestToken is StandardToken {
/* Public variables */
string public name;
uint8 public decimals;
string public symbol;
string public version = '0.1';
constructor(
uint256 _initialAmount,
string memory _tokenName,
uint8 _decimalUnits,
string memory _tokenSymbol
) public {
balances[msg.sender] = _initialAmount;
totalTokenSupply = _initialAmount;
name = _tokenName;
decimals = _decimalUnits;
symbol = _tokenSymbol;
}
function approveAndCall(address _spender, uint256 _value) public returns (bool success) {
allowed[msg.sender][_spender] = _value;
emit Approval(msg.sender, _spender, _value);
return true;
}
}
Loading…
Cancel
Save