{"id":1233,"date":"2025-12-10T12:45:34","date_gmt":"2025-12-10T10:45:34","guid":{"rendered":"https:\/\/ackee.xyz\/blog\/?p=1233"},"modified":"2026-01-05T14:26:27","modified_gmt":"2026-01-05T12:26:27","slug":"signing-data-in-wake-raw-structured-and-hash-flows","status":"publish","type":"post","link":"https:\/\/ackee.xyz\/blog\/signing-data-in-wake-raw-structured-and-hash-flows\/","title":{"rendered":"Signing Data in Wake: Raw, Structured, and Hash Flows"},"content":{"rendered":"<h2 dir=\"auto\" data-line=\"3\">Why Signing Matters in Tests<\/h2>\n<p class=\"code-line\" dir=\"auto\" data-line=\"4\">Typed signatures drive permit flows, meta-transactions, and off-chain approvals. Being able to generate them inside tests lets you confirm your verification logic without wiring external wallets. Wake exposes a focused API on <code class=\"codehl\">Account<\/code> that covers the three common cases: raw message signing (<code class=\"codehl\">sign<\/code>), EIP-712 structured signing (<code class=\"codehl\">sign_structured<\/code>), and low-level hash signing (<code class=\"codehl\">sign_hash<\/code>). This guide distills the official <a href=\"https:\/\/ackee.xyz\/wake\/docs\/latest\/testing-framework\/accounts-and-addresses\/\">Accounts and addresses<\/a> documentation into practical examples you can drop directly into your tests.<\/p>\n<h2 dir=\"auto\" data-line=\"8\">Preparing an Account With a Private Key<\/h2>\n<p class=\"code-line\" dir=\"auto\" data-line=\"9\">Wake signs only when an account holds a private key. You can import or generate one in a single line:<\/p>\n<pre><code class=\"language-python\">\nfrom wake.testing import Account\n\naccount = Account.from_mnemonic(&quot; &quot;.join([&quot;test&quot;] * 11 + [&quot;junk&quot;]))\n# Other options:\n# Account.from_key(&quot;0x&quot; + &quot;a&quot; * 64)\n# Account.from_alias(&quot;alice&quot;)  # uses the alias from config\n# Account.new()                # fresh random key\n\n<\/code><\/pre>\n<p class=\"code-line\" dir=\"auto\" data-line=\"19\">The account is now ready for transactions and all three signing modes.<\/p>\n<h2 dir=\"auto\" data-line=\"21\">Signing Raw Messages (EIP-191)<\/h2>\n<p class=\"code-line\" dir=\"auto\" data-line=\"22\">Use <code class=\"codehl\">Account.sign<\/code> for human-readable bytes, such as when you need a <code class=\"codehl\">personal_sign<\/code> style flow in a test:<\/p>\n<pre><code class=\"language-python\">from wake.testing import Account\n\naccount = Account.from_mnemonic(&quot; &quot;.join([&quot;test&quot;] * 11 + [&quot;junk&quot;]))\nsignature = account.sign(b&quot;Hello, world!&quot;)\n<\/code><\/pre>\n<p class=\"code-line\" dir=\"auto\" data-line=\"31\">Wake applies the EIP-191 prefix (version <code class=\"codehl\">0x45<\/code>) automatically so the signature matches standard wallet behavior. Use this mode for UX prompts or legacy flows that intentionally avoid typed data.<\/p>\n<h2 dir=\"auto\" data-line=\"33\">Signing Structured Messages (EIP-712)<\/h2>\n<p class=\"code-line\" dir=\"auto\" data-line=\"34\">Typed data keeps approvals unambiguous. Wake mirrors the EIP-712 pipeline using dataclasses and an explicit domain:<\/p>\n<pre><code class=\"language-python\">from dataclasses import dataclass\nfrom wake.testing import *\n\n\n@dataclass\nclass Transfer:\n    sender: Address\n    recipient: Address\n    amount: uint256\n\n\naccount = Account.from_mnemonic(&quot; &quot;.join([&quot;test&quot;] * 11 + [&quot;junk&quot;]))\nsignature = account.sign_structured(\n    Transfer(\n        sender=account.address,\n        recipient=Address(1),\n        amount=10,\n    ),\n    domain=Eip712Domain(\n        name=&quot;Test&quot;,\n        chainId=chain.chain_id,\n        verifyingContract=Address(0),  # set to your contract if needed\n    ),\n)\n<\/code><\/pre>\n<p class=\"code-line\" dir=\"auto\" data-line=\"63\">Wake builds the type string, hashes each field, and signs the EIP-712 digest. In protocol tests, pair this with a Solidity function such as <code class=\"codehl\">hashTypedData<\/code> to confirm the contract computes the same digest before verifying the signature.<\/p>\n<h2 dir=\"auto\" data-line=\"65\">Signing a Precomputed Hash<\/h2>\n<p class=\"code-line\" dir=\"auto\" data-line=\"66\">Use <code class=\"codehl\">Account.sign_hash<\/code> only when an external API already gives you the digest. This method skips prefixes and signs the bytes as-is:<\/p>\n<pre><code class=\"language-python\">from wake.testing import *\n\naccount = Account.from_mnemonic(&quot; &quot;.join([&quot;test&quot;] * 11 + [&quot;junk&quot;]))\nmessage_hash = keccak256(b&quot;Hello, world!&quot;)\nsignature = account.sign_hash(message_hash)\n<\/code><\/pre>\n<p class=\"code-line\" dir=\"auto\" data-line=\"75\">Use this when you must match a known hash, such as a contract&#8217;s <code class=\"codehl\">hashTypedData<\/code> output. If you do not control or understand the preimage, do not sign it.<\/p>\n<h2 dir=\"auto\" data-line=\"78\">Hardening Tips for Signature Tests<\/h2>\n<ul>\n<li class=\"code-line\" dir=\"auto\" data-line=\"79\">Align domains: ensure <code class=\"codehl\">name<\/code>, <code class=\"codehl\">version<\/code>, <code class=\"codehl\">chainId<\/code>, and <code class=\"codehl\">verifyingContract<\/code> match exactly between Wake and contract code.<\/li>\n<li class=\"code-line\" dir=\"auto\" data-line=\"80\">Separate raw and typed flows: use <code class=\"codehl\">sign<\/code> for prefixed personal messages, <code class=\"codehl\">sign_structured<\/code> for typed data, and <code class=\"codehl\">sign_hash<\/code> for deliberate edge cases.<\/li>\n<li class=\"code-line\" dir=\"auto\" data-line=\"81\">Label test actors: <code class=\"codehl\">chain.accounts[i].label = &quot;ALICE&quot;<\/code> improves trace readability without affecting behavior.<\/li>\n<li class=\"code-line\" dir=\"auto\" data-line=\"82\">Capture traces on failure: wrap tests with <code class=\"codehl\">@on_revert<\/code> and print <code class=\"codehl\">e.tx.call_trace<\/code> when debugging signature-related reverts.<\/li>\n<li class=\"code-line\" dir=\"auto\" data-line=\"83\">Assert end-to-end: inside Solidity, recompute the digest and check that <code class=\"codehl\">ecrecover<\/code> returns <code class=\"codehl\">account.address<\/code> to catch encoding errors early.<\/li>\n<\/ul>\n<h3 dir=\"auto\" data-line=\"85\">A Simple Permit-Test Recipe<\/h3>\n<ol>\n<li class=\"code-line\" dir=\"auto\" data-line=\"86\">Define the permit struct as a Wake dataclass mirroring the Solidity struct.<\/li>\n<li class=\"code-line\" dir=\"auto\" data-line=\"87\">Build the domain using the contract\u2019s actual name, version, chain ID, and verifying address.<\/li>\n<li class=\"code-line\" dir=\"auto\" data-line=\"88\">Generate the signature with <code class=\"codehl\">sign_structured<\/code> and call the permit or verification function in your test.<\/li>\n<li class=\"code-line\" dir=\"auto\" data-line=\"89\">Recompute the digest in Solidity and ensure <code class=\"codehl\">ecrecover<\/code> yields your signer.<\/li>\n<li class=\"code-line\" dir=\"auto\" data-line=\"90\">Add fuzzing for amounts and deadlines to confirm that hashing stays stable across inputs.<\/li>\n<\/ol>\n<h2 dir=\"auto\" data-line=\"92\">Conclusion<\/h2>\n<div>\n<div>Wake\u2019s signing helpers put a wallet-like interface inside your tests, so you can exercise permit flows and typed approvals without wiring external tools. Use <code class=\"codehl\">sign_structured<\/code> for EIP-712 paths, keep <code class=\"codehl\">sign<\/code> for legacy prompts, and treat <code class=\"codehl\">sign_hash<\/code> as an intentional edge-case hook. The APIs stay one-liners, letting you focus on asserting contract behavior instead of wrestling with signature plumbing.<\/div>\n<\/div>\n","protected":false},"excerpt":{"rendered":"<p>Why Signing Matters in Tests Typed signatures drive permit flows, meta-transactions, and off-chain approvals. Being able to generate them inside tests lets you confirm your verification logic without wiring external wallets. Wake exposes a focused API on Account that covers the three common cases: raw message signing (sign), EIP-712 structured signing (sign_structured), and low-level hash signing (sign_hash). This guide distills the official&hellip;<\/p>\n","protected":false},"author":24,"featured_media":1102,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[61,10],"tags":[96,24,68,104],"class_list":["post-1233","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-education","category-ethereum","tag-educational","tag-ethereum","tag-solidity","tag-wake"],"aioseo_notices":[],"featured_image_src":"https:\/\/ackee.xyz\/blog\/wp-content\/uploads\/2025\/07\/Read-Only-Reentrancy-Attack-600x400.png","featured_image_src_square":"https:\/\/ackee.xyz\/blog\/wp-content\/uploads\/2025\/07\/Read-Only-Reentrancy-Attack-600x600.png","author_info":{"display_name":"Naoki Yoshida","author_link":"https:\/\/ackee.xyz\/blog\/author\/naoki-yoshida\/"},"_links":{"self":[{"href":"https:\/\/ackee.xyz\/blog\/wp-json\/wp\/v2\/posts\/1233","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ackee.xyz\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/ackee.xyz\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/ackee.xyz\/blog\/wp-json\/wp\/v2\/users\/24"}],"replies":[{"embeddable":true,"href":"https:\/\/ackee.xyz\/blog\/wp-json\/wp\/v2\/comments?post=1233"}],"version-history":[{"count":0,"href":"https:\/\/ackee.xyz\/blog\/wp-json\/wp\/v2\/posts\/1233\/revisions"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/ackee.xyz\/blog\/wp-json\/wp\/v2\/media\/1102"}],"wp:attachment":[{"href":"https:\/\/ackee.xyz\/blog\/wp-json\/wp\/v2\/media?parent=1233"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/ackee.xyz\/blog\/wp-json\/wp\/v2\/categories?post=1233"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/ackee.xyz\/blog\/wp-json\/wp\/v2\/tags?post=1233"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}