---
title: eth_call Investigation Notes
---
# Input Parameters
### Block Number
- latest block number
```json=
// Returns output of NUMBER opcode
// Code: 0x684360005260206000f360005260096017f3
// request
{
"jsonrpc": "2.0",
"method": "eth_call",
"params": [
{
"from": null,
"to": "{{contractAddress}}",
"data":""
},
"pending"
],
"id": 8
}
// response
{
"jsonrpc": "2.0",
"id": 8,
"result": "0x00000000000000000000000000000000000000000000000000000000000000df"
}
// current block is 224 (pending) so this is the last which is 223
```
- pending
```json=
// Returns output of NUMBER opcode
// Code: 0x684360005260206000f360005260096017f3
// request
{
"jsonrpc": "2.0",
"method": "eth_call",
"params": [
{
"from": null,
"to": "{{contractAddress}}",
"data":""
},
"pending"
],
"id": 8
}
// response
{
"jsonrpc": "2.0",
"id": 8,
"result": "0x00000000000000000000000000000000000000000000000000000000000000c1"
}
// current block is 225 so this is the one in progress
```
- earliest
```json=
// Returns output of NUMBER opcode
// Code: 0x684360005260206000f360005260096017f3
// request
{
"jsonrpc": "2.0",
"method": "eth_call",
"params": [
{
"from": null,
"to": "{{contractAddress}}",
"data":""
},
"earliest"
],
"id": 8
}
// response
{
"jsonrpc": "2.0",
"id": 8,
"result": "0x"
}
// earliest retrieves the genesis block
```
- mispelled
```json
// Returns output of NUMBER opcode
// Code: 0x684360005260206000f360005260096017f3
// request
{
"jsonrpc": "2.0",
"method": "eth_call",
"params": [
{
"from": null,
"to": "{{contractAddress}}",
"data":""
},
"latst"
],
"id": 8
}
// response
{
"jsonrpc": "2.0",
"id": 8,
"error": {
"code": -32602,
"message": "invalid argument 1: hex string without 0x prefix"
}
}
```
- null or undefined
```json
// Returns output of NUMBER opcode
// Code: 0x684360005260206000f360005260096017f3
// request
{
"jsonrpc": "2.0",
"method": "eth_call",
"params": [
{
"from": null,
"to": "{{contractAddress}}",
"data":""
},
null
],
"id": 8
}
// response
{
"jsonrpc": "2.0",
"id": 8,
"error": {
"code": -32000,
"message": "invalid arguments; neither block nor hash specified"
}
}
```
- block height (hex encoded height)
- valid height
```json
// Returns output of NUMBER opcode
// Code: 0x684360005260206000f360005260096017f3
// request
{
"jsonrpc": "2.0",
"method": "eth_call",
"params": [
{
"from": null,
"to": "{{contractAddress}}",
"data":""
},
"0x1"
],
"id": 8
}
// response
{
"jsonrpc": "2.0",
"id": 8,
"result": "0x0000000000000000000000000000000000000000000000000000000000000001"
}
```
- height greater than current block
```json
// Returns output of NUMBER opcode
// Code: 0x684360005260206000f360005260096017f3
// request
{
"jsonrpc": "2.0",
"method": "eth_call",
"params": [
{
"from": null,
"to": "{{contractAddress}}",
"data":""
},
"0x8"
],
"id": 8
}
// response
{
"jsonrpc": "2.0",
"id": 8,
"error": {
"code": -32000,
"message": "header not found"
}
}
```
### <i>from</i>
- null account
```json
// Code: 0x683360005260206000f360005260096017f3
// request
{
"jsonrpc": "2.0",
"method": "eth_call",
"params": [
{
"from": null,
"to": "{{contractAddress}}",
"data":""
},
"latest"
],
"id": 8
}
// response
{
"jsonrpc": "2.0",
"id": 8,
"result": "0x0000000000000000000000000000000000000000000000000000000000000000"
}
```
- non-null account
```json
// Code: 0x683360005260206000f360005260096017f3
// request
{
"jsonrpc": "2.0",
"method": "eth_call",
"params": [
{
"from": "{{Account1}}",
"to": "{{contractAddress}}",
"data":""
},
"latest"
],
"id": 8
}
// response
{
"jsonrpc": "2.0",
"id": 8,
"result": "0x000000000000000000000000c228a058717372e08f58a113df1bdff35babd05a"
}
```
- non-existent account
```json
// Code: 0x683360005260206000f360005260096017f3
// request
{
"jsonrpc": "2.0",
"method": "eth_call",
"params": [
{
"from": "0xc228a058718372e08f58f113df1bdff35babd05a",
"to": "{{contractAddress}}",
"data":""
},
"latest"
],
"id": 8
}
// response
{
"jsonrpc": "2.0",
"id": 8,
"result": "0x000000000000000000000000c228a058718372e08f58f113df1bdff35babd05a"
}
```
- improperly formatted account
- length
```json
// Code: 0x683360005260206000f360005260096017f3
// request
{
"jsonrpc": "2.0",
"method": "eth_call",
"params": [
{
"from": "0xc228a058718372e08f58f113dff35babd05a",
"to": "{{contractAddress}}",
"data":""
},
"latest"
],
"id": 8
}
// response
{
"jsonrpc": "2.0",
"id": 8,
"error": {
"code": -32602,
"message": "invalid argument 0: hex string has length 36, want 40 for common.Address"
}
}
```
- invalid characters
```json
// Code: 0x683360005260206000f360005260096017f3
// request
{
"jsonrpc": "2.0",
"method": "eth_call",
"params": [
{
"from": "0xc228a05871837#e08f58f113df1bdff35babd05a",
"to": "{{contractAddress}}",
"data":""
},
"latest"
],
"id": 8
}
// response
{
"jsonrpc": "2.0",
"id": 8,
"error": {
"code": -32602,
"message": "invalid argument 0: json: cannot unmarshal invalid hex string into Go struct field CallArgs.from of type common.Address"
}
}
```
### <i>to</i>
- null
```json
// request
{
"jsonrpc": "2.0",
"method": "eth_call",
"params": [
{
"from": "{{Account1}}",
"to": null,
"data":null
},
"latest"
],
"id": 8
}
// response
{
"jsonrpc": "2.0",
"id": 8,
"result": "0x"
}
```
- improper formatting
- length
```json
// request
{
"jsonrpc": "2.0",
"method": "eth_call",
"params": [
{
"from": "{{Account1}}",
"to": "0x91a2ac564fac17965ee2db773500fde39f0cfb",
"data":null
},
"latest"
],
"id": 8
}
// response
{
"jsonrpc": "2.0",
"id": 8,
"error": {
"code": -32602,
"message": "invalid argument 0: hex string has length 38, want 40 for common.Address"
}
}
```
- invalid characters
```json
// request
{
"jsonrpc": "2.0",
"method": "eth_call",
"params": [
{
"from": "{{Account1}}",
"to": "0x91a2#c564fac17965ee2db77359800fde39f0cfb",
"data":null
},
"latest"
],
"id": 8
}
// response
{
"jsonrpc": "2.0",
"id": 8,
"error": {
"code": -32602,
"message": "invalid argument 0: json: cannot unmarshal invalid hex string into Go struct field CallArgs.to of type common.Address"
}
}
```
- Account doesn't exist
```json
// request
{
"jsonrpc": "2.0",
"method": "eth_call",
"params": [
{
"from": "{{Account1}}",
"to": "0x91a2ac564fac17964ee2db77359800fde39f0cfb",
"data":""
},
"latest"
],
"id": 8
}
// response
{
"jsonrpc": "2.0",
"id": 8,
"result": "0x"
}
```
### <i>gas</i>
- output of GAS opcode
- if gas is not defined
```json
// code returns output of GAS opcode
// code 0x685a60005260206000f360005260096017f3
// request
{
"jsonrpc": "2.0",
"method": "eth_call",
"params": [
{
"from": "{{Account1}}",
"to": "{{contractAddress}}",
"data":null
},
"latest"
],
"id": 8
}
// response
{
"jsonrpc": "2.0",
"id": 8,
"result": "0x00000000000000000000000000000000000000000000000000000000017d2636"
}
```
- gas is defined (above limit)
```json
// code returns output of GAS opcode
// code 0x685a60005260206000f360005260096017f3
// request
{
"jsonrpc": "2.0",
"method": "eth_call",
"params": [
{
"from": "{{Account1}}",
"to": "{{contractAddress}}",
"data":null,
"gas": "0x33333"
},
"latest"
],
"id": 8
}
// response
{
"jsonrpc": "2.0",
"id": 8,
"result": "0x000000000000000000000000000000000000000000000000000000000002e129"
}
```
- gas is defined (below limit)
```json
// code returns output of GAS opcode
// code 0x685a60005260206000f360005260096017f3
// request
{
"jsonrpc": "2.0",
"method": "eth_call",
"params": [
{
"from": "{{Account1}}",
"to": "{{contractAddress}}",
"data":null,
"gas": "0x3333"
},
"latest"
],
"id": 8
}
// response
{
"jsonrpc": "2.0",
"id": 8,
"error": {
"code": -32000,
"message": "err: intrinsic gas too low: have 13107, want 21000 (supplied gas 13107)"
}
}
```
- gas is higher implicit but below actual
```json
// code returns output of GAS opcode after storing and then loading from
// storage (very expensive)
// 0x6e5a60005560005460005260206000f3600052600f6011f3
// request
{
"jsonrpc": "2.0",
"method": "eth_call",
"params": [
{
"from": "{{Account1}}",
"to": "{{contractAddress}}",
"data":null,
"gas": "0x5208" // exactly implicit
},
"latest"
],
"id": 8
}
// response
{
"jsonrpc": "2.0",
"id": 8,
"error": {
"code": -32000,
"message": "out of gas"
}
}
```
- if gas is not hex encoded it will return
```jsx
"error": {
"code": -32602,
"message": "invalid argument 0: json: cannot unmarshal hex number with leading zero digits into Go struct field CallArgs.gas of type hexutil.Uint64"
}
```
- if gas is too low it will return
```jsx
"error": {
"code": -32000,
"message": "err: intrinsic gas too low: have 1, want 21204 (supplied gas 1)"
}
```
- if sufficient gas it returns
```jsx
"result": "0x0000000000000000000000000000000000000000000000000000000000000002"
```
- with gas equal to anything greater than `"0xffffffffffffffff"` which is equivalent to saying that gas must be less than or equal to `2^64 - 1`
```jsx
"error": {
"code": -32602,
"message": "invalid argument 0: json: cannot unmarshal hex number > 64 bits into Go struct field CallArgs.gas of type hexutil.Uint64"
}
```
- effects on GASLIMIT
- no gas set
```json
// code returns output of GASLIMIT opcode
// 0x684560005260206000f360005260096017f3
// request
{
"jsonrpc": "2.0",
"method": "eth_call",
"params": [
{
"from": "{{Account1}}",
"to": "{{contractAddress}}",
"data":null
},
"latest"
],
"id": 8
}
// response
{
"jsonrpc": "2.0",
"id": 8,
"result": "0x0000000000000000000000000000000000000000000000000000000000997eb0" // 10059440
}
// the above response does not change unless a transaction is processed on-chain
// (e.g. deploying another contract)
```
- gas sent (above implicit)
```json
// code returns output of GASLIMIT opcode
// 0x684560005260206000f360005260096017f3
// request
{
"jsonrpc": "2.0",
"method": "eth_call",
"params": [
{
"from": "{{Account1}}",
"to": "{{contractAddress}}",
"data":null,
"gas": "0x5500"
},
"latest"
],
"id": 8
}
// response
{
"jsonrpc": "2.0",
"id": 8,
"result": "0x0000000000000000000000000000000000000000000000000000000000995852" // 10049618
}
```
### <i>gasPrice</i>
- gasPrice as null
```json
// returns the output of GASPRICE opcode
// 0x683a60005260206000f360005260096017f3
// request
{
"jsonrpc": "2.0",
"method": "eth_call",
"params": [
{
"from": "{{Account1}}",
"to": "{{contractAddress}}",
"data":null,
"gas": "0x5500"
},
"latest"
],
"id": 8
}
// response
{
"jsonrpc": "2.0",
"id": 8,
"result": "0x0000000000000000000000000000000000000000000000000000000000000000"
}
```
- gasPrice set
- low
```json
// returns the output of GASPRICE opcode
// 0x683a60005260206000f360005260096017f3
// request
{
"jsonrpc": "2.0",
"method": "eth_call",
"params": [
{
"from": "{{Account1}}",
"to": "{{contractAddress}}",
"data":null,
"gas": "0x5500",
"gasPrice": "0x1"
},
"latest"
],
"id": 8
}
// response
{
"jsonrpc": "2.0",
"id": 8,
"result": "0x0000000000000000000000000000000000000000000000000000000000000001"
}
```
- very high
```json
// returns the output of GASPRICE opcode
// 0x683a60005260206000f360005260096017f3
// request
{
"jsonrpc": "2.0",
"method": "eth_call",
"params": [
{
"from": "{{Account1}}",
"to": "{{contractAddress}}",
"data":null,
"gas": "0x5500",
"gasPrice": "0x1000000000000000000000000000000000000000000000000000000000000"
},
"latest"
],
"id": 8
}
// response
{
"jsonrpc": "2.0",
"id": 8,
"result": "0x0001000000000000000000000000000000000000000000000000000000000000"
}
```
- too high
```json
// returns the output of GASPRICE opcode
// 0x683a60005260206000f360005260096017f3
// request
{
"jsonrpc": "2.0",
"method": "eth_call",
"params": [
{
"from": "{{Account1}}",
"to": "{{contractAddress}}",
"data":null,
"gas": "0x5500",
"gasPrice": "0x10000000000000000000000000000000000000000000000000000000000000"
},
"latest"
],
"id": 8
}
// response
{
"jsonrpc": "2.0",
"id": 8,
"error": {
"code": -32000,
"message": "err: insufficient funds for gas * price + value: address 0xC228a058717372E08F58a113dF1BDfF35bABD05a have 115792089237316195423570985008687907853269984665640564039357534007913129639927 want 615145474073242288187720857858654510470496793536215496459618415042038501212160 (supplied gas 21760)"
}
}
```
### <i>value</i>
- effect on contract BALANCE
- undefined (no effect)
- defined and greater than 0
```json
// code returns BALANCE of contract ACCOUNT opcode
// 0x69303160005260206000f3600052600a6016f3
// request
{
"jsonrpc": "2.0",
"method": "eth_call",
"params": [
{
"from": "{{Account1}}",
"to": "{{contractAddress}}",
"data":null,
"value": "0x1"
},
"latest"
],
"id": 8
}
// response
{
"jsonrpc": "2.0",
"id": 8,
"result": "0x0000000000000000000000000000000000000000000000000000000000000001"
}
```
- very large (below value is greater than from account value)
```json
// code returns BALANCE of contract ACCOUNT opcode
// 0x69303160005260206000f3600052600a6016f3
// request
{
"jsonrpc": "2.0",
"method": "eth_call",
"params": [
{
"from": "{{Account1}}",
"to": "{{contractAddress}}",
"data":null,
"value": "0x1000000000000000000000000000000000000000000000000000000000000000"
},
"latest"
],
"id": 8
}
// response
{
"jsonrpc": "2.0",
"id": 8,
"result": "0x1000000000000000000000000000000000000000000000000000000000000000"
}
```
- too large
```json
// code returns BALANCE of contract ACCOUNT opcode
// 0x69303160005260206000f3600052600a6016f3
// request
{
"jsonrpc": "2.0",
"method": "eth_call",
"params": [
{
"from": "{{Account1}}",
"to": "{{contractAddress}}",
"data":null,
"value": "0x10000000000000000000000000000000000000000000000000000000000000000"
},
"latest"
],
"id": 8
}
// response (if amount transfered is too large but account had enough)
{
"jsonrpc": "2.0",
"id": 8,
"error": {
"code": -32602,
"message": "invalid argument 0: json: cannot unmarshal hex number > 256 bits into Go struct field CallArgs.value of type *hexutil.Big"
}
}
// reponse (if from account didn't have enough value)
{
"jsonrpc": "2.0",
"id": 8,
"error": {
"code": -32000,
"message": "err: insufficient funds for transfer: address 0x9fc48f3BD757d35a7c286af4735B7250b4A4929b (supplied gas 25000000)"
}
}
```
- from account undefined (any amount greater than 0)
```json
// code returns BALANCE of contract ACCOUNT opcode
// 0x69303160005260206000f3600052600a6016f3
// request
{
"jsonrpc": "2.0",
"method": "eth_call",
"params": [
{
"from": null,
"to": "{{contractAddress}}",
"data":null,
"value": "0x1000000000000000000000000000000000000000000000000000000000000000"
},
"latest"
],
"id": 8
}
// response
{
"jsonrpc": "2.0",
"id": 8,
"error": {
"code": -32000,
"message": "err: insufficient funds for transfer: address 0x0000000000000000000000000000000000000000 (supplied gas 25000000)"
}
}
```
### `eth_call` from accounts with too little ETH or Zero?
`eth_call` succeeds despite not having enough balance
### What is TIMESTAMP?
seconds since 1/1/1970 (UNIX Epoch time) of the specified block
# Request format
```bash=
### Request
curl
-H "Content-Type: application/json"
http://localhost:8545/
-X POST
--data
'{
"method": "eth_call",
"params": [
{
"from": "0x85f7c2480b66ca340e9f2a534dbf8b660137889f",
"to": "0x52e596894ea366943da485eaca43f1813aac551d",
"data": "0x6ffa1caa0000000000000000000000000000000000000000000000000000000000000005"
},
"latest"
],
"id": 1,
"jsonrpc": "2.0"
}'
### Response
{
"jsonrpc": "2.0",
"id": 1,
"result": "0x000000000000000000000000000000000000000000000000000000000000000a"
}
```
# Call data types
## Unsigned Integers
uses [08bb1114](#08bb1114)
For a given call to this contract we need to first format the data request; to establish a baseline of how things work right now, here're the results from the built-in methods
```javascript=
const data = await contract.methods.addAssembly(1,2).encodeABI() // the data to be sent to the contract
// '0x08bb111400000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002'
const res = await ethers.call({to:"<Contract Address>", data})
// '0x0000000000000000000000000000000000000000000000000000000000000003'
// Can also make call with web3.js
const res = await contract.methods.addAssembly(1,2).call()
// '3'
```
But it's important that we understand what exactly goes into the request / is required for the `Call Data` type.
```javascript=
// 1) calculate the hash of the method call
const hash = web3Utils.sha3("addAssembly(uint256,uint256)") // uint256 comes from solidity types; but can be within uint8,uint16,...uint256
// hash -> '0x08bb1114a1f38d5f27cbb87d6d30555f5e86ce4cb3202bb7cef8b919a4a52301'
// 2) extract the first 4 bytes of that hash and append it to 0x...
const dataHeader = `0x${hash.slice(2,10)}`
// dataHeader -> '0x08bb1114'
// 3) hex encode each parameter and give 32 bytes of padding
const hexEncoded1 = web3Utils.toHex(1).slice(2)
// hexEncoded1 -> '1'
const hexEncoded2 = web3Utils.toHex(2).slice(2)
// hexEncoded2 -> '2'
const input1 = "0".repeat(64).concat(hexEncoded1).slice(-64)
// bytes1 -> '0000000000000000000000000000000000000000000000000000000000000001'
const input2 = "0".repeat(64).concat(hexEncoded2).slice(-64)
// bytes2 -> '0000000000000000000000000000000000000000000000000000000000000002'
// 4) concat dataHeader and inputs in order to receive data
const data = dataHeader.concat(input1, input2)
// data -> '0x08bb111400000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002'
```
## String
uses [d8e928c](#d8e928c)
The call data is encoded with the following format:
```javascript=
const calldata1 = contract.methods.strAssemblyCalldata("a").encodeABI()
// calldata1 -> '0xd8e928c7000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000016100000000000000000000000000000000000000000000000000000000000000'
const memory1 = contract.methods.strAssemblyMemory("a").encodeABI()
// memory1 -> '0xf62b2952000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000016100000000000000000000000000000000000000000000000000000000000000'
const calldata2 = contract.methods.strAssemblyCalldata("aa").encodeABI()
// calldata2 -> '0xd8e928c7000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000026161000000000000000000000000000000000000000000000000000000000000'
// string call data can be broken into 4 parts
`0x${web3Utils.sha3("strAssemblyMemory(string)").slice(2,10)}`
// header -> 0xf62b2952
?
// {unknown} -> 000000000000000000000000000000000000000000000000000000000000002
"0".repeat(64).concat(web3Utils.toHex("aa".length).slice(2)).slice(-64)
// string length -> 00000000000000000000000000000000000000000000000000000000000000002
web3Utils.toHex("aa").slice(2).concat("0".repeat(64)).slice(0,64)
// hex encoded string -> 6161000000000000000000000000000000000000000000000000000000000000
```
if the string is too long it will extend in increments of 64 bytes and each character is 2 bytes
```javascript=
contract.methods.strAssemblyCalldata("aadddddddddddddddddddddddddddddd").encodeABI()
// '0xd8e928c7000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000206161646464646464646464646464646464646464646464646464646464646464'
contract.methods.strAssemblyCalldata("aaddddddddddddddddddddddddddddddd").encodeABI()
// '0xd8e928c70000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000002161616464646464646464646464646464646464646464646464646464646464646400000000000000000000000000000000000000000000000000000000000000'
// diff -> 6400000000000000000000000000000000000000000000000000000000000000
// each character is 2 bytes
contract.methods.strAssemblyMemory("a".repeat(32)).encodeABI()
// '0xf62b2952000000000000000000000000000000000000000000000000000000000000002000000000000000000000000000000000000000000000000000000000000000206161616161616161616161616161616161616161616161616161616161616161'
contract.methods.strAssemblyMemory("a".repeat(64)).encodeABI()
// '0xf62b29520000000000000000000000000000000000000000000000000000000000000020000000000000000000000000000000000000000000000000000000000000004061616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161616161'
```
## Boolean
uses [89a47ad8](#89a47ad8)
The request encoding follows expected types
```javascript=
await contract.methods.boolean(true).encodeABI()
// '0x89a47ad80000000000000000000000000000000000000000000000000000000000000001'
// breakdown...
`0x${web3Utils.sha3("boolean(bool)").slice(2,10)}`
// '0x89a47ad8'
"0".repeat(64).concat(web3Utils.toHex(true).slice(2)).slice(-64)
// '0000000000000000000000000000000000000000000000000000000000000001'
```
This is similarly followed in the case of 2 inputs / outputs
```javascript=
await contract.methods.boolean2(true,false).encodeABI()
'0xc89a4b3400000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000'
// breakdown...
`0x${web3Utils.sha3("boolean2(bool,bool)").slice(2,10)}`
// '0xc89a4b34'
"0".repeat(64).concat(web3Utils.toHex(true).slice(2)).slice(-64)
// '0000000000000000000000000000000000000000000000000000000000000001'
"0".repeat(64).concat(web3Utils.toHex(false).slice(2)).slice(-64)
// '0000000000000000000000000000000000000000000000000000000000000000'
```
## Signed Integers
uses [291c4b98](#291c4b98)
```javascript=
await contract.methods.signedInt(-1).encodeABI()
// '0x291c4b98ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff'
`0x${web3Utils.sha3("signedInt(int256)").slice(2,10)}`
// '0x291c4b98'
// "ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff"
// above is just the inverted hex of its positive counterpart
await contract.methods.addSignedInt(-2, -3).encodeABI()
// '0xc37ccbd3fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffefffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffd'
`0x${web3Utils.sha3("addSignedInt(int256,int256)").slice(2,10)}`
// '0xc37ccbd3'
```
# Return data types
## Unsigned Integers
Consider a simple contract
```solidity
library Assembly {
function addAssembly(uint x, uint y) public pure returns (uint) {
assembly {
// Add some code here
let result := add(x, y)
mstore(0x0, result)
return(0x0, 32)
}
}
}
```
Then the response from a simple request will be ABI encoded
```javascript=
const data = contract.methods.addAssembly(1,2).encodeABI();
// data -> '0x08bb111400000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002'
const res = await ethers.call({to: "<Contract Address", data});
// res -> '0x0000000000000000000000000000000000000000000000000000000000000003'
const hexEncoded3 = web3Utils.toHex(3).slice(2);
// hexEncoded3 -> '3'
const abiEncoded3 = "0x" + "0".repeat(64).concat(hexEncoded3).slice(-64);
// abiEncoded3 -> '0x0000000000000000000000000000000000000000000000000000000000000003'
// i.e. returns(uint256)
```
# Revert
Uses [8d558b8](#8d558b8)
Note that `signedInt(1) -> '0x291c4b980000000000000000000000000000000000000000000000000000000000000001'
`
when called, the method reverts with the following RPC output:
```bash
curl -H "Content-Type: application/json" http://localhost:8545/ -X POST --data '{"method":"eth_call","params":[{"from":"0x85f7c2480b66ca340e9f2a534dbf8b660137889f","to":"0x5d3320aaa0adf4a7665a10a4404a87b0c8805b01","data":"0x291c4b980000000000000000000000000000000000000000000000000000000000000001"},"latest"],"id":1,"jsonrpc":"2.0"}'
> {"jsonrpc":"2.0","id":1,"error":{"code":-32000,"message":"execution reverted"}}
```
# Gas
### Low Gas Limit
Uses [291c4b98](#291c4b98)
```javascript=
await contract.methods.addSignedInt(1,1).call({
from: "<Any Non-Zero Balance Account>",
gas: "200"
})
```
```bash=
```
### Low Account Balance
Uses [291c4b98](#291c4b98)
For accounts with a low or zero balance the call allows for the synthetic transactions to occur
```javascript=
await contract.methods.addSignedInt(1,1).call({from: "0x72c90e03256099e1DC27DE3711F80bbdd5bE1925"})
// '2'
await contract.methods.addSignedInt(1,1).call({from: "0x72c90e03256099e1DC27DE3711F80bbdd5bE1925", gas: "100000"})
// '2'
await contract.methods.addSignedInt(1,1).call({from: "0x72c90e03256099e1DC27DE3711F80bbdd5bE1925", gasPrice: "200000000000000", gas: "100000"})
// '2'
```
This is also true when interfacing directly with geth RPC
```bash=
curl -H "Content-Type: application/json" http://localhost:8545/ -X POST --data '{"method":"eth_call","params":[{"from":"0x09b1b5f60ae2648bb1b329354361f6bc243c3b7e","to":"0x52e596894ea366943da485eaca43f1813aac551d","data":"0x6ffa1caa0000000000000000000000000000000000000000000000000000000000000005"},"latest"],"id":1,"jsonrpc":"2.0"}'
> {"jsonrpc":"2.0","id":1,"result":"0x000000000000000000000000000000000000000000000000000000000000000a"}
```
In contrast when actually executing the action it will error if the account doesn't have enough balance
```javascript=
await contract.methods.addSignedInt(1,1).send({from: "0x72c90e03256099e1DC27DE3711F80bbdd5bE1925", gasPrice: "200000000000000", gas: "100000"}) // errors
```
# No Response Data
```bash
{"jsonrpc":"2.0","id":1,"result":"0x"}
```
It appears that the above occurs for, if any reason, a contract returns no data; so it allows for things to fail silently
Consider for instance the following bytecode `0x41` which is just the CODEBASE opcode
Appendix
---
# Errors
```bash=
# ganache
curl localhost:9545 -X POST {"method":"eth_call","params":[{"from":"0xe965c8ad2607884034e941e7f3f150c2ee9c9720","data":"0xc37ccbd300000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002"}],"id":46,"jsonrpc":"2.0"}
> zsh: no matches found: params:[from:0xe965c8ad2607884034e941e7f3f150c2ee9c9720]
```
```bash=
# the 'from' address has double quotes typo
# geth
curl -H "Content-Type: application/json" http://localhost:8545/ -X POST --data '{"method":"eth_call","params":[{"from":""0x85f7c2480b66ca340e9f2a534dbf8b660137889f"","to":"0x7cde2049b4445a73b1573e344f78c0202d63ebe7b51e64497e1ab3cfdbc32862","data":"0xc37ccbd300000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002"},"latest"],"id":1,"jsonrpc":"2.0"}'
> {"jsonrpc":"2.0","id":null,"error":{"code":-32700,"message":"parse error"}}
```
```bash=
# geth
curl -H "Content-Type: application/json" http://localhost:8545/ -X POST --data '{"method":"eth_call","params":[{"from":"accounts[0]","to":"0x7cde2049b4445a73b1573e344f78c0202d63ebe7b51e64497e1ab3cfdbc32862","data":"0xc37ccbd300000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000002"},"latest"],"id":46,"jsonrpc":"2.0"}'
> {"jsonrpc":"2.0","id":46,"error":{"code":-32602,"message":"invalid argument 0: json: cannot unmarshal hex string without 0x prefix into Go struct field CallArgs.from of type common.Address"}}
```
the return size must be 32, otherwise there is an overflow error (wrt to defining assembly returns in solidity)
```bash
Error: data out-of-bounds (length=16, offset=32, code=BUFFER_OVERRUN, version=abi/5.0.7)
at Logger.makeError (/Users/alitamoore/ethereum/node_modules/@ethersproject/logger/lib/index.js:180:21)
at Logger.throwError (/Users/alitamoore/ethereum/node_modules/@ethersproject/logger/lib/index.js:189:20)
at Reader._peekBytes (/Users/alitamoore/ethereum/node_modules/web3-eth-abi/node_modules/@ethersproject/abi/lib/coders/abstract-coder.js:149:24)
at Reader.readBytes (/Users/alitamoore/ethereum/node_modules/web3-eth-abi/node_modules/@ethersproject/abi/lib/coders/abstract-coder.js:161:26)
at Reader.readValue (/Users/alitamoore/ethereum/node_modules/web3-eth-abi/node_modules/@ethersproject/abi/lib/coders/abstract-coder.js:167:48)
at NumberCoder.decode (/Users/alitamoore/ethereum/node_modules/web3-eth-abi/node_modules/@ethersproject/abi/lib/coders/number.js:49:28) {
reason: 'data out-of-bounds',
code: 'BUFFER_OVERRUN',
length: 16,
offset: 32
}
```
#### Block Enum
The block enum is the second variable in the call and can only be "latest", "earliest", or "pending"; the following errors occur if this is violated
- if you submit a request without a second parameter defined it'll throw an error
```bash
{
"jsonrpc":"2.0",
"method":"eth_call",
"params": [{
"from": "{{Account1}}",
"to": "0xee408b2d602d94e06a9d0241cc9dc0092eed1d53"
}],
"id": 1
}
>>>>
{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -32602,
"message": "missing value for required argument 1"
}
}
```
- if you submit with something that is empty
```bash
{
"jsonrpc":"2.0",
"method":"eth_call",
"params": [{
"from": "{{Account1}}",
"to": "0xee408b2d602d94e06a9d0241cc9dc0092eed1d53"
}, ""],
"id": 1
}
>>>>
{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -32602,
"message": "invalid argument 1: empty hex string"
}
}
```
- if you submit with something that's not an accepted value
```bash
{
"jsonrpc":"2.0",
"method":"eth_call",
"params": [{
"from": "{{Account1}}",
"to": "0xee408b2d602d94e06a9d0241cc9dc0092eed1d53"
}, "fake"],
"id": 1
}
>>>>>
{
"jsonrpc": "2.0",
"id": 1,
"error": {
"code": -32602,
"message": "invalid argument 1: hex string without 0x prefix"
}
}
```
# Contracts
##### 291c4b98
```solidity=
library Assembly {
function signedInt(int _int) public pure returns (int) {
return _int;
}
function addSignedInt(int _int1, int _int2) public pure returns (int) {
return _int1 + _int2;
}
}
```
```
```
##### d8e928c
```solidity=
library Assembly {
function strAssemblyCalldata(string calldata _str) public pure returns (string calldata) {
return _str;
}
function strAssemblyMemory(string memory _str) public pure returns (string memory) {
return _str;
}
}
```
```
```
##### 08bb1114
```solidity
library Assembly {
function addAssembly(uint x, uint y) public pure returns (uint) {
assembly {
// Add some code here
let result := add(x, y)
mstore(0x0, result)
return(0x0, 32)
}
}
}
```
```
```
##### 89a47ad8
```solidity=
library Assembly {
function boolean(bool _bool) public pure returns (bool) {
return _bool;
}
function boolean2(bool _bool1, bool _bool2) public pure returns (bool, bool) {
return (_bool1, _bool2);
}
}
```
```
```
##### 8d558b8
```solidity=
library Assembly {
function signedInt(int _int) public pure returns (int) {
int apple = _int;
revert();
// return _int;
}
function addSignedInt(int _int1, int _int2) public pure returns (int) {
return _int1 + _int2;
}
}
```
```
0x6102a1610053600b82828239805160001a607314610046577f4e487b7100000000000000000000000000000000000000000000000000000000600052600060045260246000fd5b30600052607381538281f3fe730000000000000000000000000000000000000000301460806040526004361061005d576000357c010000000000000000000000000000000000000000000000000000000090048063291c4b9814610062578063c37ccbd314610092575b600080fd5b61007c600480360381019061007791906100f8565b6100c2565b604051610089919061016c565b60405180910390f35b6100ac60048036038101906100a79190610121565b6100cd565b6040516100b9919061016c565b60405180910390f35b600080829050600080fd5b600081836100db9190610187565b905092915050565b6000813590506100f281610254565b92915050565b60006020828403121561010a57600080fd5b6000610118848285016100e3565b91505092915050565b6000806040838503121561013457600080fd5b6000610142858286016100e3565b9250506020610153858286016100e3565b9150509250929050565b6101668161021b565b82525050565b6000602082019050610181600083018461015d565b92915050565b60006101928261021b565b915061019d8361021b565b9250817f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff038313600083121516156101d8576101d7610225565b5b817f80000000000000000000000000000000000000000000000000000000000000000383126000831216156102105761020f610225565b5b828201905092915050565b6000819050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b61025d8161021b565b811461026857600080fd5b5056fea2646970667358221220cef7a31d885883915a67926f53e4c6595dad92a6124c33b00a1fc55df8ff3a5a64736f6c63430008030033
```
#### Custom1
This was primarily used to investigate the behavior of specific edge-case opcodes
bytecode:
```
4160005260206000a04360005260206000a03360005260206000a04460005260206000a04260005260206000a0
```
Outputs (in logs):
```bash=
4160005260206000a0 # logs COINBASE output
4360005260206000a0 # logs NUMBER output
3360005260206000a0 # logs CALLER output
4460005260206000a0 # logs DIFFICULTY output
4260005260206000a0 # logs TIMESTAMP output
0x00000000000000000000000085f7c2480b66ca340e9f2a534dbf8b660137889f # COINBASE
0x000000000000000000000000000000000000000000000000000000000000006c # NUMBER -> 108
0x00000000000000000000000085f7c2480b66ca340e9f2a534dbf8b660137889f # CALLER
0x0000000000000000000000000000000000000000000000000000000000000002 # DIFFICULTY
0x00000000000000000000000000000000000000000000000000000000607d03db # TIMESTAMP -> 1618805723s since 1970
# once more a little bit later
0x00000000000000000000000085f7c2480b66ca340e9f2a534dbf8b660137889f # COINBASE
0x000000000000000000000000000000000000000000000000000000000000006f # NUMBER -> 111
0x00000000000000000000000085f7c2480b66ca340e9f2a534dbf8b660137889f # CALLER
0x0000000000000000000000000000000000000000000000000000000000000002 # DIFFICULTY
0x00000000000000000000000000000000000000000000000000000000607d0682 # TIMESTAMP -> 1618806402s since 1970 Unix epoch
```