
{"id":239288,"date":"2026-10-14T06:46:29","date_gmt":"2026-10-14T06:46:29","guid":{"rendered":"https:\/\/mycryptomania.com\/?p=239288"},"modified":"2026-10-14T06:46:29","modified_gmt":"2026-10-14T06:46:29","slug":"tangems-eip-7702-executor-never-reads-tx-origin-my-census-found-one-in-the-word-uint256","status":"publish","type":"post","link":"https:\/\/mycryptomania.com\/?p=239288","title":{"rendered":"Tangem\u2019s EIP-7702 executor never reads tx.origin. My census found one in the word uint256"},"content":{"rendered":"<h4>Three of my stories counted it as a tx.origin-only contract. The byte was the 2 in an EIP-712 type string, after the last instruction<\/h4>\n<p><em>Fee(address feeToken,uint256 maxTokenFee,uint256 coinPriceInToken,uint256 feeTransferGasLimit,uint256 baseGas,address feeReceiver)<\/em><\/p>\n<p>That line of text sits in the runtime bytecode of 0xe3014e9a\u20260178, one of the EIP-7702 delegate contracts I counted in September. Since 9 September, three of my stories have said this contract reads tx.origin and never msg.sender. The tx.origin they counted is the 2 in \u201cuint256\u201d, just before \u201cbaseGas\u201d.<\/p>\n<h3>How a sentence turns into\u00a0opcodes<\/h3>\n<p>My census walks a contract\u2019s bytecode from byte 0, skips PUSH data and counts seven opcodes. It doesn\u2019t follow jumps. Solidity can leave data after the last instruction, and the walk carries straight on into it. Here that data is three EIP-712 type strings, 243 bytes starting at byte 6,996, after a REVERT at 6,994 and an INVALID at\u00a06,995.<\/p>\n<p>Text read as bytecode is mostly PUSH instructions. Every lowercase letter is one, 0x61 to 0x7a, so a letter swallows the next 2 to 27 bytes and the walk lands wherever that arithmetic puts it. The \u201cr\u201d in \u201cfeeTransferGasLimit\u201d is 0x72, PUSH19. It skips \u201cansferGasLimit,uint\u201d, and the next byte the walk reads as an instruction is the character 2, which is 0x32. That\u2019s ORIGIN. The capital T at the start of \u201cTransaction\u201d came out as SLOAD, and the space after that \u201cuint256\u201d as KECCAK256.<\/p>\n<p>There are six 2s in the text. Five land inside PUSH data and never get counted. One\u00a0doesn\u2019t.<\/p>\n<p>The 243 bytes after Tangem\u2019s last instruction, as my census walked them. Orange is the byte it counted as tx.origin.<\/p>\n<h3>I had this on 11 September<\/h3>\n<p><a href=\"https:\/\/medium.com\/@azhar.great\/most-solidity-contracts-end-in-the-byte-for-caller-my-opcode-census-counted-it-as-code-aa2926274767\">Yesterday\u2019s story<\/a> fixed a different way the census reads bytes that aren\u2019t code: it stopped the walk where Solidity\u2019s CBOR metadata begins. That fix doesn\u2019t reach this. The type strings sit before the metadata, so trimming the tail left the 2 exactly where it was, and that story said the 333\u00a0held.<\/p>\n<p>The worse part is that I\u2019d already found it. On 11 September a reachability pass over the same bytecode put this ORIGIN inside a band of type strings, and the chart from that day is still in my repo. The draft it was drawn for was deleted the same day along with six others, and the finding went with it. Nothing carried it into the next story, or the one after\u00a0that.<\/p>\n<h3>Checking it from the source\u00a0side<\/h3>\n<p>The bytes already said the ORIGIN couldn\u2019t run: there\u2019s no JUMPDEST anywhere in the text, and the code before it ends in REVERT. I wanted the source to say the same. The contract is verified on Blockscout as Tangem7702GaslessExecutorL1, verified on 2 February 2026 and compiled with solc 0.8.33. Across its 27 source files tx.origin appears zero times. msg.sender appears twice, both in OpenZeppelin doc comments.<\/p>\n<p>What it checks is a signature. The account signs an EIP-712 message, and the contract recovers the signer and requires signer == address(this). Under EIP-7702 the delegated code runs as the account itself, so address(this) is that account, and only its key can authorise what the executor runs. The strings are in the bytecode because the source builds one of its typehashes with abi.encodePacked over three string constants.<\/p>\n<p>From Tangem\u2019s verified source: the executor checks who signed, never who\u00a0called.<\/p>\n<p>So my census filed a signature-checking executor from a hardware wallet maker under \u201cguards itself with tx.origin\u201d, which is close to the opposite of what it\u00a0does.<\/p>\n<h3>The number, corrected<\/h3>\n<p>The September claim was that two contracts reading ORIGIN and never CALLER held 333 of the 1,178 authorizations in a 200-block window, 28.3%, and 198 of 948 signing accounts by the count I made on 11 September. Tangem\u2019s executor had 25 of those authorizations, from 16 accounts. Without it there\u2019s one contract left: 308 authorizations, 26.15%, from 182 accounts, 19.20%.<\/p>\n<p>That one is the Poisoner, 0xe6b97aa1, the contract <a href=\"https:\/\/medium.com\/@azhar.great\/the-most-delegated-eip-7702-contract-on-ethereum-guards-itself-with-tx-origin-f199f82c74bb\">the 9 September story<\/a> was about. The same dead-byte pass leaves its ORIGIN where it was, in the dispatcher at byte\u00a065.<\/p>\n<p>The share I published three times, and what it is without Tangem\u2019s executor.<\/p>\n<p>Across all 59 contracts the pass finds 1,018 bytes that can never execute, and counted opcodes in them in five contracts. Tangem\u2019s is the only one where that changes the answer. The rule is small: stop counting after a terminating instruction until the next JUMPDEST. It treats every JUMPDEST as reachable, so anything it drops is certainly not code. It still can\u2019t tell me what a contract checks. The source did\u00a0that.<\/p>\n<p>The census has now been wrong about the same window twice, once in the metadata and once in the text just before it. The first time, the number I cared about survived the fix, and that\u2019s the reason I stopped\u00a0looking.<\/p>\n<p><a href=\"https:\/\/medium.com\/coinmonks\/tangems-eip-7702-executor-never-reads-tx-origin-my-census-found-one-in-the-word-uint256-f1ca08b6a05e\">Tangem\u2019s EIP-7702 executor never reads tx.origin. My census found one in the word uint256<\/a> was originally published in <a href=\"https:\/\/medium.com\/coinmonks\">Coinmonks<\/a> on Medium, where people are continuing the conversation by highlighting and responding to this story.<\/p>","protected":false},"excerpt":{"rendered":"<p>Three of my stories counted it as a tx.origin-only contract. The byte was the 2 in an EIP-712 type string, after the last instruction Fee(address feeToken,uint256 maxTokenFee,uint256 coinPriceInToken,uint256 feeTransferGasLimit,uint256 baseGas,address feeReceiver) That line of text sits in the runtime bytecode of 0xe3014e9a\u20260178, one of the EIP-7702 delegate contracts I counted in September. Since 9 September, [&hellip;]<\/p>\n","protected":false},"author":0,"featured_media":239289,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[2],"tags":[],"class_list":["post-239288","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-interesting"],"_links":{"self":[{"href":"https:\/\/mycryptomania.com\/index.php?rest_route=\/wp\/v2\/posts\/239288"}],"collection":[{"href":"https:\/\/mycryptomania.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/mycryptomania.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"replies":[{"embeddable":true,"href":"https:\/\/mycryptomania.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=239288"}],"version-history":[{"count":0,"href":"https:\/\/mycryptomania.com\/index.php?rest_route=\/wp\/v2\/posts\/239288\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/mycryptomania.com\/index.php?rest_route=\/wp\/v2\/media\/239289"}],"wp:attachment":[{"href":"https:\/\/mycryptomania.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=239288"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/mycryptomania.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=239288"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/mycryptomania.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=239288"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}