{"id":15931070,"url":"https://github.com/arthurgousset/dune","last_synced_at":"2025-04-03T14:21:25.658Z","repository":{"id":197798477,"uuid":"699365823","full_name":"arthurgousset/dune","owner":"arthurgousset","description":"✨ DuneSQL cheat sheet","archived":false,"fork":false,"pushed_at":"2024-05-03T10:30:01.000Z","size":197,"stargazers_count":3,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-02-09T03:15:36.845Z","etag":null,"topics":["dune","sql"],"latest_commit_sha":null,"homepage":"https://dune.com","language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/arthurgousset.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2023-10-02T13:47:42.000Z","updated_at":"2024-10-22T10:29:38.000Z","dependencies_parsed_at":"2023-12-22T14:55:56.421Z","dependency_job_id":"c54879e7-df73-4ecd-a05d-71037276b793","html_url":"https://github.com/arthurgousset/dune","commit_stats":{"total_commits":10,"total_committers":2,"mean_commits":5.0,"dds":"0.30000000000000004","last_synced_commit":"4b4bde7f9416fe4fc6f027fcb3260ebce3febc11"},"previous_names":["0xarthurxyz/dune","arthurgousset/dune"],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arthurgousset%2Fdune","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arthurgousset%2Fdune/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arthurgousset%2Fdune/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/arthurgousset%2Fdune/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/arthurgousset","download_url":"https://codeload.github.com/arthurgousset/dune/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247014513,"owners_count":20869376,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["dune","sql"],"created_at":"2024-10-07T01:03:37.316Z","updated_at":"2025-04-03T14:21:25.634Z","avatar_url":"https://github.com/arthurgousset.png","language":null,"readme":"# Dune.com (Cheat Sheet)\n\nThis is a cheatsheet for dune.com commands and patterns (mostly notes-to-self). They are incomplete\nby default.\n\n## Background\n\n### Ethereum logs\n\nSource: [medium.com][1]\n\nThe EVM currently has **5 opcodes** for emitting event logs: `LOG0`, `LOG1`, `LOG2`, `LOG3`,\nand `LOG4`.\n\nEach log record consists of both **topics** and **data**.\n\n**Topics** are 32-byte (256 bit) \"words\" that are used to describe what's going on in an event.\n\nDifferent opcodes (`LOG0` ... `LOG4`) are needed to describe the number of topics that need to be\nincluded in the log record. For instance, **LOG1** includes **one topic**,\nwhile **LOG4** includes **four topics**. Therefore, the maximum number of topics that can be\nincluded in a single log record is **four**.\n\n#### Topics\n\nThe first part of a log record consists of an array of topics. These topics are used to describe the\nevent.\n\nThe first topic (`topic0`) usually consists of the **_signature_**  (a [keccak256][2] hash) of the\nname of the event that occurred, including the types  *(`uint256`, `string`, etc.)* of its\nparameters.\n\n\u003cimg width=\"650\" src=\"assets/image/event-signature-hash.png\"\u003e\n\nOne exception where this signature is not included as the first topic is when emitting  **anonymous\nevents**.\n\nSince topics can only hold a maximum of 32 bytes of data, things like arrays or strings cannot be\nused as topics reliably. Instead, they should be included as **data** in the log record, not as a\n**topic**.\n\nIf you try to include a topic larger than 32 bytes, the topic will be hashed instead. As a result,\nthis hash can only be reversed if you know the original input. Thus, topics should **only** reliably\nbe used for data that strongly narrows down search queries (like addresses). Topics can be seen as\nindexed *keys* of the event that all map to the same value.\n\n#### Data\n\nWhile topics are searchable, data is not. But, including data is **a lot cheaper** than including\ntopics. Similarly, topics are limited to **32 bytes**, event data is not, which means it can\ninclude **large or complicated data** like arrays or strings.\n\nBy analogy, if **topics** are _keys_, then **data** is the *value*.\n\n[1]: https://medium.com/mycrypto/understanding-event-logs-on-the-ethereum-blockchain-f4ae7ba50378\n[2]: https://en.wikipedia.org/wiki/SHA-3\n\n### Bytes, hex characters, solidity data types\n\nIn Ethereum, 1 byte = 2 hexadecimal characters. Therefore, a 32-byte word is represented by 64\nhexadecimal characters.\n\n\u003e **FOOTNOTE** Remember, 8 bits = 1 byte = [256 possible patterns][6] = 2 hexadecimal characters = 1\n\u003e ASCII character\n\n| Solidity data type    | Size (Bytes) | Size (Hex Characters) | Notes                                                    |\n| --------------------- | ------------ | --------------------- | -------------------------------------------------------- |\n| `address`             | 20           | 40                    | Ethereum addresses are 20 bytes long.                    |\n| `uint256`             | 32           | 64                    | Unsigned integer of 256 bits.                            |\n| `bool`                | 1            | 2                     | Boolean values are typically padded to 32 bytes.         |\n| `bytes1` to `bytes32` | 1 to 32      | 2 to 64               | Fixed-size byte arrays.                                  |\n| `int256`              | 32           | 64                    | Signed integer of 256 bits.                              |\n| `string`              | Variable     | Variable              | Dynamic size. Encoded with length prefix in `data`.      |\n| `bytes`               | Variable     | Variable              | Similar to `string`, dynamic size.                       |\n| `enum`                | Variable     | Variable              | Depends on the number of elements (often 1 to 32 bytes). |\n\n[6]: https://web.stanford.edu/class/cs101/bits-bytes.html\n\n## `bytearray_\u003cfunction\u003e` (old) == `varbinary_\u003cfunction\u003e` (new)\n\n\u003e Varbinary functions were previously called byte array functions. You might find\n\u003e e.g. `bytearray_to_uint256` in some of our older queries. These functions are identical to the\n\u003e varbinary functions and work as aliases.\n\nSource:\n[dune.com/docs](https://dune.com/docs/query/DuneSQL-reference/Functions-and-operators/varbinary/#varbinary-functions)\n\n## Parse `uint256` from `data`\n\nFor example, suppose `data` is:\n\n```txt\n0x0000000000000000000000000000000000000000000000a2a15d09519be00000000000000000000000000000000002e93c1c6586656bb97761036c475599e3d0\n```\n\nwhere `data` is the concatenation of `uint256 value` and `uint256 units`, in the following event:\n\n```solidity\nevent ValidatorGroupVoteActivated(\n    address indexed account,\n    address indexed group,\n    uint256 value,\n    uint256 units\n);\n```\n\nWe know that 1 byte is 2 hex characters, and the data type `uint256` requires 32 bytes or 64 hex\ncharacters. On that basis, we can use the\n[`varbinary_substring(varbinary, integer, integer) → varbinary`][3] function to parse `value` and\n`units` from `data`:\n\n```sql\nSELECT\n    -- ...\n    varbinary_substring(data, 1, 32) as value, -- uint256 = 32 bytes = 64 hex characters\n    varbinary_substring(data, 33, 64) as units -- uint256 = 32 bytes = 64 hex characters\n    -- ...\nFROM celo.logs\nWHERE contract_address = 0x8d6677192144292870907e3fa8a5527fe55a7ff6 -- ElectionProxy\n    AND topic0 = 0x45aac85f38083b18efe2d441a65b9c1ae177c78307cb5a5d4aec8f7dbcaeabfe -- ValidatorGroupVoteActivated\n```\n\nThis returns:\n\n```txt\nvalue = 0x0000000000000000000000000000000000000000000000a2a15d09519be00000\nunits = 0x000000000000000000000000000002e93c1c6586656bb97761036c475599e3d0\n```\n\n\u003e **FOOTNOTE** Unfortunately, in dune you need to ignore `0x` in `data`, which is the first byte, so\n\u003e the indices are shifted by 1. See dune docs for\n\u003e [`varbinary_substring(varbinary, integer, integer) → varbinary`][3].\n\u003e\n\u003e ```sql\n\u003e SELECT 0xabcdefabcdef AS varbinary_data,\n\u003e        varbinary_substring(0xabcdefabcdef, 1, 3) AS varbinary_substring\n\u003e -- returns  0xabcd\n\u003e ```\n\nNow convert `value` and `unit` (which are `varbinary` words) to `uint256` using\n[`varbinary_to_uint256(varbinary) → uint256`][4]:\n\n```sql\nSELECT\n    -- ...\n    varbinary_to_uint256(varbinary_substring(data, 1, 32)) as value, -- uint256 = 32 bytes = 64 hex characters\n    varbinary_to_uint256(varbinary_substring(data, 33, 64)) as units -- uint256 = 32 bytes = 64 hex characters\n    -- ...\nFROM celo.logs\nWHERE contract_address = 0x8d6677192144292870907e3fa8a5527fe55a7ff6 -- ElectionProxy\n    AND topic0 = 0x45aac85f38083b18efe2d441a65b9c1ae177c78307cb5a5d4aec8f7dbcaeabfe -- ValidatorGroupVoteActivated\n```\n\nThis returns:\n\n```txt\nvalue = 3000000000000000000000\nunits = 253590264479329621170386650913407566996432\n```\n\n[3]:\n  https://dune.com/docs/query/DuneSQL-reference/Functions-and-operators/varbinary/#byte-array-manipulation-functions\n[4]:\n  https://dune.com/docs/query/DuneSQL-reference/Functions-and-operators/varbinary/#bytearray_to_uint256\n\n### Remove leading zeros from `address`\n\nFor example, suppose `topic1` is:\n\n```txt\n0x000000000000000000000000da5fc5db514ffe24f30229711fc4545624e52320\n```\n\nwhere `topic1` is `address account`, in the following event:\n\n```solidity\nevent ValidatorGroupVoteActivated(\n    address indexed account,\n    address indexed group,\n    uint256 value,\n    uint256 units\n);\n```\n\nWe can use [`varbinary_ltrim(varbinary) → varbinary`][5] to remove leading zeros from `topic1`:\n\n```sql\nSELECT\n    -- ...\n    varbinary_ltrim(topic1) as account,\n    -- ...\nFROM celo.logs\nWHERE contract_address = 0x8d6677192144292870907e3fa8a5527fe55a7ff6 -- ElectionProxy\n    AND topic0 = 0x45aac85f38083b18efe2d441a65b9c1ae177c78307cb5a5d4aec8f7dbcaeabfe -- ValidatorGroupVoteActivated\n```\n\nThis returns:\n\n```txt\naccount = 0xda5fc5db514ffe24f30229711fc4545624e52320\n```\n\n[5]:\n  https://dune.com/docs/query/DuneSQL-reference/Functions-and-operators/varbinary/#bytearray_ltrim\n\n### Convert wei to ethers\n\n```sql\nSELECT\n    (value * 1e-18) as amountInDollar -- converts to decimal (10^18 wei = 1 ether)\nFROM erc20_celo.evt_Transfer\nWHERE contract_address = 0x765de816845861e75a25fca122bb6898b8b1282a -- cUSD ERC-20 token\n```\n\n## Date and Time\n\n### Getting year, month, day from timestamp\n\n`year()`: Returns the year from x. `month()`: Returns the month of the year from x.\n\nSource:\n[dune.com](https://dune.com/docs/query/DuneSQL-reference/Functions-and-operators/datetime/?h=year#year)\n\nExample of hacky way I needed to get `2023_09` type `varchar`:\n\n```sql\nCONCAT(CAST(year(time) as varchar), '-', cast(month(time) as varchar)) as year_month,\n```\n\n## Format labels\n\nI like to use `0[.]00a`, but other label formats are available:\n\n| Starting Value | Tick/Label format | Output          | Description                                                                                                                                                     |\n| -------------- | ----------------- | --------------- | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |\n| 1256784.3745   | [blank]           | 1256784.3745000 | Displays the number with 7 decimal precision.                                                                                                                   |\n| 1256784.3745   | 0                 | 1256784         | Displays only the integer.                                                                                                                                      |\n| 1256784.3745   | 0,0               | 1,256,784       | Only displays the integer with comma separation.                                                                                                                |\n| 1256784.3745   | 0,0.00            | 1,256,784.38    | Displays the number with [x] decimal precision, where [x] is the number of 0 you add after the decimal point.                                                   |\n| 1256784.3745   | 0.0a              | 1.2M            | Displays the number with [x] precision and a letter based on the number’s 1e[y] power (eg “m” for million, “b” for billion)                                     |\n| 1256784.3745   | $0.0a             | $1.2M           | Adds a ”$” to the number. Works with all formats above though use of the a suffix is recommended. Currently the only ”$” is the only supported currency symbol. |\n\nSource:\n[docs.dune.com \u003e visualisations](https://docs.dune.com/web-app/visualizations/charts-graphs#x-y-axis-tick-and-label-formats)\n\n## Manually append rows to a SQl query\n\nSometimes I need to manually add a row to a SQL query. This is not ideal and not a long-term\nsolution, but sometimes it helps as a hacky solution. For example, this query\n[ERC20 | Token names](https://dune.com/queries/3340302):\n\n```sql\nSELECT\n    DISTINCT symbol as name,\n    contract_address as address\nFROM tokens.erc20\nWHERE blockchain = 'celo'\n\nUNION\n\n/*\nI'm manually adding names for adapted tokens like USDT and USDC,\nwhich are used as fee currencies on Celo.\n\nUnfortunately, the fee currency field will show the adapted token address,\nwhich has 18 decimals, and not the ERC20 token address, which has 6 decimals.\n\nSince the `tokens.erc20` table only includes ERC20 tokens, it doesn't\ninclude adapted tokens.\n\nThis is a hacky fix, and probably not a good solution.\nBut it's good enough for now.\n\nSource for name and addresses of adapted token:\nhttps://docs.celo.org/protocol/transaction/erc20-transaction-fees#adapters-by-network\n*/\nSELECT 'USDC' AS name, 0x2F25deB3848C207fc8E0c34035B3Ba7fC157602B AS address\nUNION\nSELECT 'USDT' AS name, 0x0e2a3e05bc9a16f5292a6170456a710cb89c6f72 AS address\n\n-- Order all results\nORDER BY name\n```\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Farthurgousset%2Fdune","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Farthurgousset%2Fdune","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Farthurgousset%2Fdune/lists"}