 I've been in Ethereum since 2014, worked in C++ Client in the Solidity compiler, did DAO stuff, White Hat and the ATC and DAO wars, but then I worked on L2 payments for many years and found it road key. Today I will be talking about user transactions and how we can start to understand them, like what are they and how can we decode them in a human readable format. Everybody has used Ethereum in here and we have all faced these two big problems, like you do not know when you have a transaction, you do not know how to get it, like there is no built-in way to get transactions for an address, you need to utilize some kind of third party service and that will never be decentralized. Also once you have these transactions you really don't know what I mean, there is a complete lack of a universal tool that will decode a transaction to human readable format, there is some third party services but again they are centralized and they tend to be protocol specific. What does a transaction look like, everybody has opened Etherscan and sees this, you know, hex block, there is no metadata, there is no human readable info, that's what every new user to Ethereum is greeted with, there is no way to understand what your transaction like three, four years ago has done. There are ways, we are no longer in 2014, there are ways to gain insight so you can see stuff in Etherscan with the graph and other centralized APIs such as covalent, moralis, et cetera. So we have all used Etherscan, what are the ways to decode the transaction with Etherscan is that it looks like this, it's a complicated transaction that swaps over multiple protocols, it's easy to use, you just type in Etherscan, you know, transaction slash the has and it gives you useful insight and it's totally free. Of course there are cons with Etherscan that's centralized, it's proprietary and close so that means that there is no way for me as a developer to see how they do what they do or extend it in any way. They know everything about you. I know the guys from Etherscan, they are good guys but you never know who in there could be malicious, they can match IPs to your addresses and know who owns what address and where they are located. And actually it does not decode everything. We have all seen that there are transactions that Etherscan doesn't have insights for and there are other tools that actually can do this. The graph is a way, it's kind of an index per protocol. They have subgraphs and they index the chain for a particular protocol and they query this index and get any insight you want. The pros is that it's very good for single protocol data. So for example here we have the other Ethereum by Messari, this is a subgraph that say the other guys can run in their interface and query any information they want for their protocol. But it has many, many disadvantages. It needs payment per query. This is their vision that everybody should be paying for every query. It's built for single protocol data, so the subgraphs, so there is no generic solution. If you have a portfolio tracker or a wallet or something that wants to decode every single transaction no matter what protocol it is in, subgraphs will not work. You will have to basically query every single subgraph and create a subgraph for everything that doesn't, is unsupported yet. And it does not work with local apps, what I like to call true dubs. So basically when the company that makes the application hosts the code they can have an API key and pay for the queries. But when it's a local application there is no way for this to happen. And there are decentralized APIs like Covalent, Morales and Alchemy. They're easy to use. They have pretty cool APIs which can decode transactions, give you all the transactions, but the same concepts can apply. Like it's centralized, it knows everything about you, it's proprietary so you cannot extend it. It's not modular at all. So having seen the ways that we can get insights about data, let's see how we can actually get accurate historical data. And let's go to the original scene of Ethereum, like this is absolutely bonkers. If any of you has tried to get the history of transactions for your address you will find out very easily that there is absolutely no built-in way to do this for Ethereum. There is no RPC method. This is all due to the way that EVM works and how the clients are built. But it is really like it's absolutely crazy that there is no way for you as a user to get all of the transactions for your address. Someone that comes as a developer outside from Web3 and comes to Ethereum and sees this, they think that we are just crazy, that this is broken. It's not all gloom and doom though. There are ways to do this. Etherscan again comes to the rescue. They have many APIs and if you combine three I think. So this one for transactions, then there is one for ERC-20 transfer and one for NFTs, if you combine all of them you get a pretty accurate picture of what transactions your address has done. Of course it has Dropbox, right? It doesn't detect all other appearances, it's rate limited but you can pay for bigger limits. But rate limiting means that it takes time for your query to actually work. It is centralized. So it can go down, they can cut access to the API or they can do what I said before that they can monitor you and map IP to your address. The truly decentralized way to go around this is something by my friend Thomas Deras, it's called Trueblocks. It is really the best and most complete way to get transaction data. Trueblocks detects all appearances of an address. Really I have seen demos where TJ basically shows Etherscan and then compares it with Trueblocks and you can see that for some addresses, Trueblocks does indeed detect more appearances than Etherscan. It is decentralized. So it runs on top of your local node so you do not need to do any other network queries. It's super fast. Like it's really like milliseconds or seconds depending on the amount of addresses that you query for. And it's built to share this index with others. Of course, like with everything in software there is Dropbox. It is hard to set up. So TJ was a long wolf since I met him in Shanghai in 2016. Now he has a bit bigger team but it takes time to build something that's easy to use by others. It does require a local node so you need to be running an Ergon node, I think. I'm not sure if it works with others. And of course you require Trueblocks itself to create the index. So building on this, I would like to present what I try to call the stack of truly decentralization which is something that we should be striving for in crypto. So everybody should try to run their own node. So something like a DAB node or Raspberry Pi with whatever setup you guys want to have. You should run your own client, right? For whatever chain you have, run a client for that chain that you want to use. And Trueblocks actually works for all chains, all EVM chains. So you can have an indexer like Trueblocks on top that will index the chain and provide you an answer to the question, how the heck... So on top of it all, to come and bind it all, you have the aggregating and decoding level that something like ROTC, so ROTC right now is an application but imagine a platform where you can have a genetic way to go from transactions to a common readable format for what they do. And it's actually consumable by humans. Going from how we get data to what actually would go into this decoding platform that my talk is about. So once you have all the data, like either from Etherscan or from Trueblocks, what kind of data is this? If you have tried to play with understanding transaction history of Ethereum, you know that there is two ways to get data. It's either a trace, a transaction trace, or transaction receipts. There are two kinds of traces, one is the gith style trace and the other is the parity trace. I'm going to go through them a bit fast for those of you who do not know what they are. So gith style trace is the tracing that comes with the gith client. When a transaction happens, it touches multiple contracts, right? So you make a transaction to a contract and this one may make a call to another contract and so on and so forth. And as they do this, they touch the state of these contracts and they make some changes. So this is what the trace of a transaction is and the gith style trace is the most complete. It's like super detailed. It has every single step of execution with the opcode, the program counter, the storage diff, et cetera. It's super detailed. It's very hard to use because for complicated transactions you have like a huge thing that you don't really know what it does and it can grow extremely huge, like in the gigabytes for really complicated transactions. And then we have the parity style trace, which comes from the now defunct parity client. But it is used, I think, Ergon for sure and NetherMind and maybe Beshu, I'm not sure. They have three commands. One is a trace that's pretty cool and useful. It gives you a call stack like this of what did your transaction do, the call trace of the transaction. And this actually does not require an archive node. The screenshot is from a very nice article by Bantech on traces that came out like two months ago, I think. So Google like Bantech and transaction traces and you can read about it in more detail. And the other thing that you can use to understand how a transaction, what has it done is the parity style trace diff. It gives you a state diff. So for each account that you touch, it gives you a difference in balance, code, nones and storage. The cool thing is here, if you have the ABI, you can play with it a bit and you can have readable names for the storage slots and how did they change. So this is a very useful insight on what did the transaction do. And of course, then transaction receipts. We've all seen like how a source code of a contract looks like. They have events. These events are actually contained in something that's called the transaction receipt. So let's say for a token transfer, it's like transfer, source, estimation and value or something. Almost everything generates them. It looks like this. It's all hex, but if you have the ABI of the contract, you can decode this into a human readable format. This is how you gather the data, but gathering this data is actually expensive. It takes time. And exactly because this is expensive in resources, persistence is key. So any kind of platform that you create and the thing that we have created, the draw key, needs to have data persistence. You can choose various ways. We've gone with a simple SQL database for now. But this way, when you have gathered all of the data and you know that they are true and will not change, then you can just take it out of the database and reuse it instead of having to re-query again true blocks or ether scan or make a trace again. We talked about where you can get data, how to get it, and then I'm going to go to the meat of the presentation, which is the decoders themselves. So we want to get human readable format of the transaction data. So we have gotten either receipts or traces, and with this amazing Inkscape graphic that I made, guys, I'm really proud of myself for this, we can see that you can check for each log the address and then send it depending on the address to either the generic ERC20 transfer decoder, if it's a Uniswap to the Uniswap decoder and so on and so forth, like AVE, et cetera. And all of this will at the end emit a common event format. What's more, some decoders feed data to other decoders. So the ERC20 transfers create the ERC20 transfer event and this gets fed to Uniswap, which translates it into swaps. Such a decoder platform is made on modularity. This is a ROTKIS repo, and this is where we have all the decoders, and it's like a huge list, it doesn't have all of them because they don't fit on the screenshot. But the idea is that it's easy to write, easy to use, and drag and drop. That you just drag, so you drop it in there and it's caught by the system. And then a new decoder is taking into account whenever we decode a transaction. That's the idea. We're not there yet. We build binaries and this is not as modular as it should be, but the idea is that it should just big drag and drop. This is how the source code looks like. This is, I think, a hop protocol to bridge to another chain. So it's hard to read probably, but the idea is that you get from the ERC20 transfer decoder you get the ERC20 transfer, and then you see, oh, it's a spend. The counterparty is the F-bridge of a hop and the asset of F matches and the amount matches. So then we transform it into the common event format for a hop and give it a nice readable explanation which like bridge the amount of ETH to either your own address or to some other address in the chain. So the name of the chain via hop protocol. I talk a lot about the common event format. It's kind of a POC because we are only consumer right now. It's changing. So this is how it looks in the code. It has like a sequence index inside the transaction. So where did it happen in the transaction? Time stamp, location. Location is mostly something that we use in Rotki because we subtract everything into this format. Not only Ethereum transactions, but your Kraken trades, your Ethereum staking, everything gets subtracted into this list common denominator format. We have the history type, history event type and history event subtype. So this is what defines the meat of how you define an event, the asset and the balance chains. And then some extra stuff like the location label is along with the counterparty is if I sent it from me to someone or if I got from others. And some extra data like if it's a CDP for maker, we have the CDP ID here, et cetera. As I said, everything is broken down into this thing. Like a swap is three of this event. So it's amount out, amount in and fee out. Or it can be two if there is no fee. We are working on this. It's not final, but this is like the idea. This is how a front-end can consume and show this code. This should be read, unfortunately, because I didn't take a nice case from the bottom to the top. So I claim my buzzer airdrop, so it has two events. The gas fee that's burned and the airdrop claiming, then approval to one inch V2 and the gas fee for this. And then the swap for in one inch for basically immediately dumping the tokens. This is the same thing that you saw in the previous screenshot, basically, these events. Each one of them is one line here. So this is how they are consumed in Rotkey itself, which is a portfolio tracking application. I would like to actually also talk a little bit about the abstraction layer of the vision of Rotkey, which is if you take this a step further and not just focus on just EVM code, but anything, like any event you can get into like an open source middleware that offers an abstraction layer for everything, accounts, balances, PNL, over multiple protocols and jurisdictions. So this is kind of the vision that we would like at some point to go with Rotkey. So we went from a portfolio tracking app to a common EVM decoder and now more towards a middleware that would offer an abstraction for everything in accounting for crypto. Why? Like people would ask, what the heck, why would you need this? Because everybody is reinventing the wheel. Again, as I said, different protocols, different exchanges, chains, jurisdictions, it's impossible to keep up. I have spoken with people in both small startups and big names in the field for portfolio tracking and crypto accounting. Everybody is saying that this is just too much to keep up. Maintaining just one module is a full-time job. So I believe that there is a solution to this problem. So the problem of everybody reinventing the wheel has a solution that we can have an open source platform, middleware, if you want, maintained by a core team but with contributors from the entire industry and used by multiple projects. And for the problem of different protocols and jurisdictions and being it impossible for a single organization to keep up, I would like to propose a solution that we can have people incentivized from each chain and protocol with appropriate know-how to come and implement modules in this platform. Again, my amazing inkscape skills, imagine a middleware where you have someone who wants to do portfolio tracking and accounting, the core uses Bitcoin and Ethereum, plugs in the Yen module, the AVE module. He also wants to do accounting, plugs in the accounting module, and because he's in Germany, he plugs in the German accounting with FIFO, multiple DPO, and LIFO accounting methods. And imagine this middleware basically being used by many people in the field and Indian, just everything plugging into this. Because it's better to use a common open source middleware rather than every single application reinventing the wheel. Any such platform would have some super basic requirements. It needs to be open source. Everybody tries to reinvent the wheel in a proprietary, close source way. This is absolutely idiotic. It needs to have a modular architecture so that, as we saw before, be pluggable, have pluggable modules. You are in a different country than Germany, you can just plug the Netherlands accounting module. You don't use Ethereum, you use Kusama. You do the substrate module, and you can do all the polka.kusama, et cetera. It needs to have, this is a hard requirement to achieve, but it needs to be multilingual. It needs to have multilingual bindings. Because we at TrotQ are a Python house. We know how to use other languages, but most of our code is in Python. Such a middleware should not limit the user. We cannot ask the entire industry to switch to Python if they are to use such a thing. The platform should be built in a multilingual way. And as for incentivization, the creators and maintenance of modules should be incentivized to actually contribute to this platform. If it becomes an open source standard, then everybody should be like, oh, wait. We made this new platform. We need to write a TrotQ module for it also because otherwise it just, like, nobody will use it. And the core team that builds and maintains it also needs to be incentivized in some way in order to be able to keep building. The ways that this can be is through support to the various teams or through SLAs for software level agreements for companies that may not want to have open source code. So you can have dual licensing. So it's a bit funny. I wanted to show this. So the timeline thing, and I was in the template that they gave us and I thought, hey, why not put the timeline? So how the heck did we get here? 2017, I just need to do my taxes in crypto. And I was like, okay, I'm not going to, what is the way to do this? There was Bitcoin.tax. There was nothing else back then. I'm not going to use the centralized service. I just don't trust them. So I just made some Python CLI scripts. It worked. I've not been sued by the German government yet, so it worked. I don't know. In 2020, we made it into a company. We were a team of two people and maybe we had 200 users, 300 and maybe 10 paid. So last year, the app had grown. We hired one more developer and we were 2,000 users and 200 paying users. In the beginning of this year, there is many people who use ROTK right now. Some like it. Some complain. They always want more and more. But it is at a level that many people can use it. We are a team of 7 now. Around 6,000 users. It's hard to know because it's an open source app and we don't have analytics. And 550 paying users. We came all this way without anything. Like it was completely bootstrapped and from basically your donations through Gitcoin and from integrations with other companies like Optimism gave us a grant lately before the Kusama and so on and so forth. So for getting this POC that I described here to the full ROTK vision, we would need to go further from here and try to grow and potentially get some funding because with the current team that we have, it's impossible to actually build this vision. The POC cannot grow to a level of something that can be used by the entire industry with just 6 developers. It's just impossible. So with this, I'm coming to the closing notes. So if you like the stuff that you had like open source, local first, the modular thing that can be used by everybody in the industry, then please talk to me or check out ROTK.com jobs. We have some open positions. We came here thanks to you. Like seriously, it's a bootstrap project and we would not be here without Gitcoin donations and without our premium users. So keep supporting us. You can donate in Gitcoin grants or buy premium subscription and unlock all of the features of ROTK and you can join our community in Twitter or Discord, like that's where all the support is. It would be pretty cool for you if you can join the chat and join our community. If you're interested in helping us grow in realizing this vision that I tried to present here, then talk to me either like any day in the conference or write an email to lefteris at ROTK.com. Yes, with that, that's all. Thank you very much. Okay. Like you mentioned the graph and true blogs. One thing that I don't understand about these two tools is to query historical data is that they use a client node and this node is basically in charge of storing these data in an SQL database. Isn't this central as way of saving data? Is this when IPFS comes into play and if that's the case, can you explain how IPFS and SQL database work together to solve this? IPFS doesn't come anywhere in there. The graph is and true books complete different things. So the graph is it creates an index on top of your already existing node data and true books does the same. But true books does it in a generic way for all of your transactions. While the graph has specialized subgraphs written by developers of particular protocol that basically write an index just for this protocol and this leaves on top of your node data. It is decentralized. Like the graph by design is also decentralized true books is itself also decentralized. It creates this index and this index is shared. I think it's pinned in IPFS and shared with others who use true books. I'm not totally sure on the details of sharing of true books because I'm not a developer. But I think that this is how they do it. As for the graph, they have a decentralized network. If I'm understanding this right, the idea is if we build this out and get it out there, then like we could get around using services like tenderly and just basically run tenderly at home for transaction tracing and simulations and all that. Yeah. I view it more from a historical perspective and tenderly is a current emulator. But yeah, I suppose that you could also do the same. Correct me if I'm wrong, tenderly is proprietary, right? Yeah. Yes. Yeah. I think that they work with traces. They're pretty good, but yeah, proprietary. With such a design, yes, I believe that we could use this as an alternative. Hola. Awesome presentation. Great work. From the developer perspective on a solid developer, I think it will be very useful for, for example, I write a smart contract and I write the decoder. Let's say I write the decoder and I host it on IPFS. Have you thought about that, like how we can have like a standardized, I know, let's say parable where we define the URI or hash where we set our decoder and you guys can use it because you have a list of decoders on GitHub, right? Yeah. Yeah. I mean, this is just a different medium of delivering the decoder. But yes, the idea is exactly what you described. So I'm not going to write every decoder. My team is not going to write every decoder. That's impossible. But the idea is exactly that you, when you write your smart contract for a protocol, then you say, okay, I'm also going to write a decoder for this. And then somehow it should be delivered to this mid-ware. Yes, it can be through a link. This is just a POC of what we have right now, the drag and drop in the folder in GitHub. I think it does a lot of value if you can also validate the decoder. Because if I do it, I can write a malicious decoder, but we want it like a validation system and this is a place where I think you can add a lot of value. Okay. That's good feedback. Thank you, guys.