This guide is for anyone who holds an Ethereum address from the 2017 DOT sale that never claimed. The claims page on Polkadotjs currently doesn’t work (sequel to the migration of claims from Relay chain to Asset Hub). An issue has been created for it, but in the mean time, you can use this guide to claim .
A couple of things to keep in mind
- The claims live on Polkadot Asset Hub, not on the Polkadot relay chain. Which means the steps below happens with polkadot.js apps connected to Asset Hub, not the Relay chain.
- The “Claim Tokens” page in polkadot.js apps currently does not work on Asset Hub. It leaves the required statement out of the message. Do not use it. Use Developer → Extrinsics, as described here.
- You do not need any DOT. The claim is a free, unsigned transaction.
- The DOT is paid to the Polkadot account whose hex is inside the message you sign. If that hex is wrong, the DOT goes to an account nobody controls and cannot be recovered. Use an account you control and check the hex twice.
What you need
- The Ethereum key that held the sale tokens, in a wallet that can sign a plain message: MetaMask, Rabby, a Ledger through MetaMask, or any wallet with “Sign message”.
- A Polkadot account you control: its seed phrase, or a Ledger or Polkadot Vault that holds it. It does not need to exist on chain yet and does not need any balance.
- polkadot.js apps, opened at this address so it connects to Asset Hub: Polkadot/Substrate Portal
Check the top left of apps says Polkadot Asset Hub. If it says “Polkadot”, you are on the wrong chain.
Step 1: confirm the claim and find out which statement it needs
In apps: Developer → Chain state. In the left dropdown choose claims, in the right one claims(EthereumAddress). Paste your Ethereum address, press the + button on the right.
- A number appears: that is your claim in planck. Divide by 10,000,000,000 for DOT. Write it down.
<none>appears: this address has no unclaimed DOT on Asset Hub. Check the address, or the claim was already made.
Now change the right dropdown to signing(EthereumAddress), paste the same address, press +.
RegularorSaftappears. Write it down. This decides the text in step 3.- As of 2026-09-11 every unclaimed address shows one of the two.
Step 2: choose the destination account and get its hex
Pick the Polkadot account that should receive the DOT. Copy its address (it starts with 1).
In apps: Developer → Utilities → Convert address. Paste the address into “address to convert”. The page shows hex public key, a string starting with 0x followed by 64 characters.
Copy those 64 characters without the 0x. Check:
- Exactly 64 characters.
- Only the digits 0 to 9 and the letters a to f, all lowercase.
Keep the address and the hex together; you will need both.
Step 3: build the message
The message is three pieces joined into one line with nothing in between: the prefix, the 64 hex characters, and the statement.
The prefix, exactly:
Pay DOTs to the Polkadot account: [the HEX of your DOT address that you got in step 2]
The statement, if step 1 said Regular:
I hereby agree to the terms of the statement whose SHA-256 multihash is Qmc1XYqT6S39WNp2UeiRUrZichUWUPpGEThDE6dAb3f6Ny. (This may be found at the URL: https://statement.polkadot.network/regular.html)
The statement, if step 1 said Saft:
I hereby agree to the terms of the statement whose SHA-256 multihash is QmXEkMahfhHJPzT3RjkXiZVFi77ZeVeuxtAjhojGRNYckz. (This may be found at the URL: https://statement.polkadot.network/saft.html)
Worked example, using the treasury address 13UVJyLnbVp9RBZYFwFGyDvVd1y27Tt8tkntv6Q7JVPhFsTB as the destination and the Regular statement. Do not sign this one; it is here so you can see the shape:
Pay DOTs to the Polkadot account:6d6f646c70792f74727372790000000000000000000000000000000000000000I hereby agree to the terms of the statement whose SHA-256 multihash is Qmc1XYqT6S39WNp2UeiRUrZichUWUPpGEThDE6dAb3f6Ny. (This may be found at the URL: https://statement.polkadot.network/regular.html)
Check your message:
- It starts with
Pay DOTs(with the s). - There is no space between the colon and the hex, and none between the hex and
I hereby. - It is one line. No line break at the end.
- The hex in it is the hex from step 2.
Step 4: sign the message with the Ethereum sale key
Use the wallet’s plain “Sign message” function, the one that signs text. In wallet terms this is personal_sign (EIP-191). Do not sign typed data, and do not hash the message yourself.
- MetaMask, Rabby and similar have no sign-message screen of their own; a website has to ask them. Any site with a “Sign message” tool works.
- MyEtherWallet has a sign-message tool under Message. You can use MyCrypto app too.
- On a Ledger, sign through MetaMask connected to the Ledger; the device shows the message for approval.
The result is the signature: 0x followed by exactly 130 characters. If you get a JSON block instead, the signature is the value of its sig field.
Worth doing: recover the address from the signature before submitting. The recovered address must be your Ethereum sale address. If it is not, the message you signed differs from the message in step 3.
Step 5: submit the claim
In apps, connected to Asset Hub: Developer → Extrinsics. Ignore “using the selected account” at the top; it is not used.
-
Under “submit the following extrinsic”, left dropdown:
claims. Right dropdown:claimAttest(dest, ethereumSignature, statement). -
dest: AccountId32: paste the destination address from step 2 (the one starting with1). -
ethereumSignature: paste the signature from step 4, with its0x. -
statement: Bytes: paste the statement bytes for your kind. Use the hex form; it cannot pick up stray spaces.Regular:
0x492068657265627920616772656520746f20746865207465726d73206f66207468652073746174656d656e742077686f7365205348412d323536206d756c74696861736820697320516d63315859715436533339574e70325565695255725a6963685557555070474554684445366441623366364e792e202854686973206d617920626520666f756e64206174207468652055524c3a2068747470733a2f2f73746174656d656e742e706f6c6b61646f742e6e6574776f726b2f726567756c61722e68746d6c29Saft:
0x492068657265627920616772656520746f20746865207465726d73206f66207468652073746174656d656e742077686f7365205348412d323536206d756c74696861736820697320516d58456b4d61686668484a507a5433526a6b58695a56466937375a655665757874416a686f6a47524e59636b7a2e202854686973206d617920626520666f756e64206174207468652055524c3a2068747470733a2f2f73746174656d656e742e706f6c6b61646f742e6e6574776f726b2f736166742e68746d6c29 -
Before pressing anything, check all five:
- Top left says Polkadot Asset Hub.
- The method is
claimAttest, notclaim. destis the same account whose hex is in the signed message.- The signature is
0x(plus 130 characters but you probably don’t need to count it :)). - The statement is the kind step 1 gave you, and the same kind you signed.
-
Press Submit Unsigned. Not Submit Transaction.
Step 6: read the result
It worked if a green notice appears with claims.Claimed, and the destination account’s balance on Asset Hub goes up by the claim within a block. Nothing else to do.
It was refused if a red notice says 1010: Invalid Transaction: Custom error: N. Nothing happened on chain. The number tells you what to fix:
| N | Meaning | Fix |
|---|---|---|
| 0 | The signature is not a plain message signature | Sign again with “Sign message”, not typed data or a hash |
| 1 | The signature is valid but for a different message or key | The hex, the statement or the wallet account differs from step 3. Rebuild the message and sign again |
| 3 | Right key and message, wrong statement bytes in the form | Paste the statement hex for the kind from step 1 |
BadOrigin, or “Inability to pay some fees”: you pressed Submit Transaction. Press Submit Unsigned.
A couple more notes
Can someone who sees my signature take the DOT? No. The signature only works for the destination named inside the message. Changing the destination breaks it.
My entry had vesting. Will the DOT be locked? No. Every remaining vested schedule started at block 0 and finished long ago. The DOT arrives unlocked.
Can I use the relay chain account I already have? Yes. Addresses are the same on both chains. The DOT arrives on Asset Hub.






