1

I'm trying to build a wallet capable of managing ERC20 tokens added by the users, using Web3 1.0.0-beta.34. After adding a certain token to the wallet using its address, I was able to fetch the amount of coins in a certain wallet.
Since I want the users to add any ERC20 token, I don't know the ABI of the token contract. Web3 requires the ABI to instantiate a contract, and I solved this issue getting the ABI of the single balanceOf function and then instantiating the contract using:

var contract = new web3.eth.Contract(balanceOfABI, contractAddress);

Now I need to get the decimals of the token, so I basically need a getter on the decimals variable but this is not possible since this is not a function and I can't use the trick above.
Is there a way to create the ABI for a common getter method? JavaScript code should be something like this at the end:

var contract = new web3.eth.Contract(getterABI, contractAddress);
contract.methods.decimals().call(function (error, result) {
    if(!error) 
        console.log(result);
});

I hope I made my point, thanks a lot.

4
  • 1
    the ABI encoding does not disntiguish between a variable and a function, they are all functions. So you can get decimals as if would be a function.
    – Nulik
    Commented Jul 23, 2018 at 14:24
  • 3
    Also , all ERC20 tokens have a standard interface (a set of methods) , you don't need to get the ABI for every contract, just use the standard ABI.
    – Nulik
    Commented Jul 23, 2018 at 14:26
  • @Nulik Thanks, I was able to get the ABI for the variable as you said. Anyway I noted on etherscan that several tokens don't have the same code (e.g. Tronix and OmiseGO), maybe there's something I didn't understand
    – DamiToma
    Commented Jul 23, 2018 at 14:53
  • well, they never gonna be equal, but they will comply to the standard (ERC20). Only early Ethereum tokens aren't fully standard.
    – Nulik
    Commented Jul 23, 2018 at 15:23

2 Answers 2

1

The ABI (Application Binary Interface) of a contract defines the actions that can be taken by that contract. Though the logic/code of the contract may vary between ERC20 tokens, the ERC20 standard itself is the list of function names alone. So taking just the basic actions that ERC20 defines, you'd be able to apply them to any ERC20 contract, though any special/additional functions that contract employs your wallet would be unaware of.

[
  {
    "constant": true,
    "inputs": [],
    "name": "name",
    "outputs": [
      {
        "name": "",
        "type": "string"
      }
    ],
    "payable": false,
    "type": "function"
  },
  {
    "constant": false,
    "inputs": [
      {
        "name": "_spender",
        "type": "address"
      },
      {
        "name": "_value",
        "type": "uint256"
      }
    ],
    "name": "approve",
    "outputs": [],
    "payable": false,
    "type": "function"
  },
  {
    "constant": true,
    "inputs": [],
    "name": "totalSupply",
    "outputs": [
      {
        "name": "",
        "type": "uint256"
      }
    ],
    "payable": false,
    "type": "function"
  },
  {
    "constant": false,
    "inputs": [
      {
        "name": "_from",
        "type": "address"
      },
      {
        "name": "_to",
        "type": "address"
      },
      {
        "name": "_value",
        "type": "uint256"
      }
    ],
    "name": "transferFrom",
    "outputs": [],
    "payable": false,
    "type": "function"
  },
  {
    "constant": true,
    "inputs": [],
    "name": "decimals",
    "outputs": [
      {
        "name": "",
        "type": "uint256"
      }
    ],
    "payable": false,
    "type": "function"
  },
  {
    "constant": true,
    "inputs": [
      {
        "name": "_who",
        "type": "address"
      }
    ],
    "name": "balanceOf",
    "outputs": [
      {
        "name": "balance",
        "type": "uint256"
      }
    ],
    "payable": false,
    "type": "function"
  },
  {
    "constant": true,
    "inputs": [],
    "name": "symbol",
    "outputs": [
      {
        "name": "",
        "type": "string"
      }
    ],
    "payable": false,
    "type": "function"
  },
  {
    "constant": false,
    "inputs": [
      {
        "name": "_to",
        "type": "address"
      },
      {
        "name": "_value",
        "type": "uint256"
      }
    ],
    "name": "transfer",
    "outputs": [],
    "payable": false,
    "type": "function"
  },
  {
    "constant": true,
    "inputs": [
      {
        "name": "_owner",
        "type": "address"
      },
      {
        "name": "_spender",
        "type": "address"
      }
    ],
    "name": "allowance",
    "outputs": [
      {
        "name": "remaining",
        "type": "uint256"
      }
    ],
    "payable": false,
    "type": "function"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "name": "from",
        "type": "address"
      },
      {
        "indexed": true,
        "name": "to",
        "type": "address"
      },
      {
        "indexed": false,
        "name": "value",
        "type": "uint256"
      }
    ],
    "name": "Transfer",
    "type": "event"
  },
  {
    "anonymous": false,
    "inputs": [
      {
        "indexed": true,
        "name": "owner",
        "type": "address"
      },
      {
        "indexed": true,
        "name": "spender",
        "type": "address"
      },
      {
        "indexed": false,
        "name": "value",
        "type": "uint256"
      }
    ],
    "name": "Approval",
    "type": "event"
  }
]
0
1

you should create fake abi include some common func of erc21


[
    {
    "constant": false,
    "inputs": [
    {
    "name": "to",
    "type": "address"
    },
    {
    "name": "tokenId",
    "type": "uint256"
    }
    ],
    "name": "approve",
    "outputs": [],
    "payable": false,
    "stateMutability": "nonpayable",
    "type": "function"
    },
    {
    "constant": false,
    "inputs": [
    {
    "name": "tokenId",
    "type": "uint256"
    }
    ],
    "name": "depositToGateway",
    "outputs": [],
    "payable": false,
    "stateMutability": "nonpayable",
    "type": "function"
    },
    {
    "constant": false,
    "inputs": [
    {
    "name": "user",
    "type": "address"
    }
    ],
    "name": "register",
    "outputs": [],
    "payable": false,
    "stateMutability": "nonpayable",
    "type": "function"
    },
    {
    "constant": false,
    "inputs": [],
    "name": "renounceOwnership",
    "outputs": [],
    "payable": false,
    "stateMutability": "nonpayable",
    "type": "function"
    },
    {
    "constant": false,
    "inputs": [
    {
    "name": "from",
    "type": "address"
    },
    {
    "name": "to",
    "type": "address"
    },
    {
    "name": "tokenId",
    "type": "uint256"
    }
    ],
    "name": "safeTransferFrom",
    "outputs": [],
    "payable": false,
    "stateMutability": "nonpayable",
    "type": "function"
    },
    {
    "constant": false,
    "inputs": [
    {
    "name": "from",
    "type": "address"
    },
    {
    "name": "to",
    "type": "address"
    },
    {
    "name": "tokenId",
    "type": "uint256"
    },
    {
    "name": "_data",
    "type": "bytes"
    }
    ],
    "name": "safeTransferFrom",
    "outputs": [],
    "payable": false,
    "stateMutability": "nonpayable",
    "type": "function"
    },
    {
    "constant": false,
    "inputs": [
    {
    "name": "to",
    "type": "address"
    },
    {
    "name": "approved",
    "type": "bool"
    }
    ],
    "name": "setApprovalForAll",
    "outputs": [],
    "payable": false,
    "stateMutability": "nonpayable",
    "type": "function"
    },
    {
    "constant": false,
    "inputs": [
    {
    "name": "from",
    "type": "address"
    },
    {
    "name": "to",
    "type": "address"
    },
    {
    "name": "tokenId",
    "type": "uint256"
    }
    ],
    "name": "transferFrom",
    "outputs": [],
    "payable": false,
    "stateMutability": "nonpayable",
    "type": "function"
    },
    {
    "constant": false,
    "inputs": [
    {
    "name": "newOwner",
    "type": "address"
    }
    ],
    "name": "transferOwnership",
    "outputs": [],
    "payable": false,
    "stateMutability": "nonpayable",
    "type": "function"
    },
    {
    "inputs": [],
    "payable": false,
    "stateMutability": "nonpayable",
    "type": "constructor"
    },
    {
    "anonymous": false,
    "inputs": [
    {
    "indexed": true,
    "name": "previousOwner",
    "type": "address"
    },
    {
    "indexed": true,
    "name": "newOwner",
    "type": "address"
    }
    ],
    "name": "OwnershipTransferred",
    "type": "event"
    },
    {
    "anonymous": false,
    "inputs": [
    {
    "indexed": true,
    "name": "from",
    "type": "address"
    },
    {
    "indexed": true,
    "name": "to",
    "type": "address"
    },
    {
    "indexed": true,
    "name": "tokenId",
    "type": "uint256"
    }
    ],
    "name": "Transfer",
    "type": "event"
    },
    {
    "anonymous": false,
    "inputs": [
    {
    "indexed": true,
    "name": "owner",
    "type": "address"
    },
    {
    "indexed": true,
    "name": "approved",
    "type": "address"
    },
    {
    "indexed": true,
    "name": "tokenId",
    "type": "uint256"
    }
    ],
    "name": "Approval",
    "type": "event"
    },
    {
    "anonymous": false,
    "inputs": [
    {
    "indexed": true,
    "name": "owner",
    "type": "address"
    },
    {
    "indexed": true,
    "name": "operator",
    "type": "address"
    },
    {
    "indexed": false,
    "name": "approved",
    "type": "bool"
    }
    ],
    "name": "ApprovalForAll",
    "type": "event"
    },
    {
    "constant": true,
    "inputs": [
    {
    "name": "owner",
    "type": "address"
    }
    ],
    "name": "balanceOf",
    "outputs": [
    {
    "name": "",
    "type": "uint256"
    }
    ],
    "payable": false,
    "stateMutability": "view",
    "type": "function"
    },
    {
    "constant": true,
    "inputs": [],
    "name": "gateway",
    "outputs": [
    {
    "name": "",
    "type": "address"
    }
    ],
    "payable": false,
    "stateMutability": "view",
    "type": "function"
    },
    {
    "constant": true,
    "inputs": [
    {
    "name": "tokenId",
    "type": "uint256"
    }
    ],
    "name": "getApproved",
    "outputs": [
    {
    "name": "",
    "type": "address"
    }
    ],
    "payable": false,
    "stateMutability": "view",
    "type": "function"
    },
    {
    "constant": true,
    "inputs": [
    {
    "name": "owner",
    "type": "address"
    },
    {
    "name": "operator",
    "type": "address"
    }
    ],
    "name": "isApprovedForAll",
    "outputs": [
    {
    "name": "",
    "type": "bool"
    }
    ],
    "payable": false,
    "stateMutability": "view",
    "type": "function"
    },
    {
    "constant": true,
    "inputs": [],
    "name": "isOwner",
    "outputs": [
    {
    "name": "",
    "type": "bool"
    }
    ],
    "payable": false,
    "stateMutability": "view",
    "type": "function"
    },
    {
    "constant": true,
    "inputs": [],
    "name": "name",
    "outputs": [
    {
    "name": "",
    "type": "string"
    }
    ],
    "payable": false,
    "stateMutability": "view",
    "type": "function"
    },
    {
    "constant": true,
    "inputs": [],
    "name": "owner",
    "outputs": [
    {
    "name": "",
    "type": "address"
    }
    ],
    "payable": false,
    "stateMutability": "view",
    "type": "function"
    },
    {
    "constant": true,
    "inputs": [
    {
    "name": "tokenId",
    "type": "uint256"
    }
    ],
    "name": "ownerOf",
    "outputs": [
    {
    "name": "",
    "type": "address"
    }
    ],
    "payable": false,
    "stateMutability": "view",
    "type": "function"
    },
    {
    "constant": true,
    "inputs": [
    {
    "name": "interfaceId",
    "type": "bytes4"
    }
    ],
    "name": "supportsInterface",
    "outputs": [
    {
    "name": "",
    "type": "bool"
    }
    ],
    "payable": false,
    "stateMutability": "view",
    "type": "function"
    },
    {
    "constant": true,
    "inputs": [],
    "name": "symbol",
    "outputs": [
    {
    "name": "",
    "type": "string"
    }
    ],
    "payable": false,
    "stateMutability": "view",
    "type": "function"
    },
    {
    "constant": true,
    "inputs": [
    {
    "name": "index",
    "type": "uint256"
    }
    ],
    "name": "tokenByIndex",
    "outputs": [
    {
    "name": "",
    "type": "uint256"
    }
    ],
    "payable": false,
    "stateMutability": "view",
    "type": "function"
    },
    {
    "constant": true,
    "inputs": [
    {
    "name": "owner",
    "type": "address"
    },
    {
    "name": "index",
    "type": "uint256"
    }
    ],
    "name": "tokenOfOwnerByIndex",
    "outputs": [
    {
    "name": "",
    "type": "uint256"
    }
    ],
    "payable": false,
    "stateMutability": "view",
    "type": "function"
    },
    {
    "constant": true,
    "inputs": [
    {
    "name": "tokenId",
    "type": "uint256"
    }
    ],
    "name": "tokenURI",
    "outputs": [
    {
    "name": "",
    "type": "string"
    }
    ],
    "payable": false,
    "stateMutability": "view",
    "type": "function"
    },
    {
    "constant": true,
    "inputs": [],
    "name": "totalSupply",
    "outputs": [
    {
    "name": "",
    "type": "uint256"
    }
    ],
    "payable": false,
    "stateMutability": "view",
    "type": "function"
    },
    {
        "constant": true,
        "inputs": [{
            "name": "",
            "type": "uint256"
        }],
        "name": "kittyIndexToApproved",
        "outputs": [{
            "name": "",
            "type": "address"
        }],
        "payable": false,
        "stateMutability": "view",
        "type": "function"
        },
        {
            "constant": true,
            "inputs": [{
                "name": "_tokenId",
                "type": "uint256"
            }],
            "name": "approvedFor",
            "outputs": [{
                "name": "",
                "type": "address"
            }],
            "payable": false,
            "stateMutability": "view",
            "type": "function"
        }
    ]

1
  • How does this answer the question? Commented Aug 23, 2019 at 8:32

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.