Skip to content

Instantly share code, notes, and snippets.

@jparklev
Last active November 10, 2025 04:18
Show Gist options
  • Select an option

  • Save jparklev/dc2ac2f1c5e4c9d6ead0c5ab6e150ee3 to your computer and use it in GitHub Desktop.

Select an option

Save jparklev/dc2ac2f1c5e4c9d6ead0c5ab6e150ee3 to your computer and use it in GitHub Desktop.
Kinetiq S1 Terms Signing Batch

Kinetiq S1 Terms Signing Batch

  • HyperEVM transaction: 0x7f18dca48520b8345cacd01e72607da87733852f0fe852f18fa1e6cc66a7ef33
  • Typed-data digest: 0x3eb32f6453b8fb3ab0eef3f8290cedaa139d604a3a5c06d13364e19525f7848a
  • Wallet list: kinetiq-wallets.json
  • Typed data: kinetiq-typed-data.json

1. Check who signed

kinetiq-wallets.json enumerates the 38 Rumpel Safes that signed (with their Kinetiq S1 balances).

2. Verify ERC‑1271 signatures

bun verify-1271.mjs

This script hits each Safe’s isValidSignature(bytes32,bytes) on HyperEVM with the digest above and prints ✅ when the Safe returns the ERC‑1271 magic value 0x1626ba7e (EIP‑1271).

Manual command, if preferred:

cast call \
  --rpc-url https://rpc.hyperliquid.xyz/evm \
  <SAFE_ADDRESS> \
  'isValidSignature(bytes32,bytes)' \
  0x3eb32f6453b8fb3ab0eef3f8290cedaa139d604a3a5c06d13364e19525f7848a \
  0x

3. Recompute the digest

bun verify-digest.mjs

This re-hashes the typed data JSON and prints the digest used in the batch transaction above.

{
"primaryType": "AcceptTerms",
"domain": {
"name": "Kinetiq",
"version": "1",
"chainId": 999,
"salt": "0x0456c9c833dd04de820193e57bcdec9d1c2b033be28b67d37c162a78aa223af1"
},
"types": {
"AcceptTerms": [
{ "name": "hyperliquidChain", "type": "string" },
{ "name": "message", "type": "string" },
{ "name": "cid", "type": "string" },
{ "name": "time", "type": "uint256" }
]
},
"message": {
"hyperliquidChain": "Mainnet",
"message": "I acknowledge and agree to the Terms of Use at https://kinetiq-foundation.org/terms.",
"cid": "bafkreiheqihimggxn2kuh6zugih3fxwxgrshfwvvjxsc3cizjwbzmtxrfq",
"time": 1762726431881
}
}
{
"wallets": [
{
"address": "0x03313d5ba602eabfc4dbabcfc7647d630b56d45f",
"kinetiqPoints": "11215949292748686000"
},
{
"address": "0x10df5f5571622038dbc413e6140262f0ff2512d2",
"kinetiqPoints": "123628340920322540"
},
{
"address": "0x1dd9c281b1ba3beafbbf8c0cce4321c9d87133fc",
"kinetiqPoints": "1359919446648767400"
},
{
"address": "0x1ed03a24f60f995e696fb3432082b13dab2b73c9",
"kinetiqPoints": "113060498055563040000"
},
{
"address": "0x2b03b0516c0bd158e55078a5c81b22454e391b4b",
"kinetiqPoints": "861702327749725400000"
},
{
"address": "0x3837c3434a46f109db6f731eede7a02615ff31bc",
"kinetiqPoints": "7299110052954493000"
},
{
"address": "0x377503269080b604a002f8409e1c49ab67a6ead9",
"kinetiqPoints": "1149915798409428100000"
},
{
"address": "0x451d9af73517a5f69c6ec6bae2059bca3e90f46f",
"kinetiqPoints": "12487123229555467000"
},
{
"address": "0x45d9f683cff65be4ba113535e74e41247530d311",
"kinetiqPoints": "136646830020117500"
},
{
"address": "0x47305295358b70d76ccaeb4f302901e8a94b43c2",
"kinetiqPoints": "104562598067292000"
},
{
"address": "0x558259b09942856e9b3a1e2afda1baec61fad44a",
"kinetiqPoints": "17714479603127206000"
},
{
"address": "0x5f4ac749a3cd56852a5215d572f26e725e67b6d0",
"kinetiqPoints": "9069395055350048000"
},
{
"address": "0x63ddd964d13acd08a0b52b26ac4ee2d2b02522fd",
"kinetiqPoints": "1539121068581702700"
},
{
"address": "0x6690de18d898d070eb037f2d6ed1766f58d4986b",
"kinetiqPoints": "515122583547535900"
},
{
"address": "0x726ba61886d178ebcf7898da6546b71728e009c2",
"kinetiqPoints": "7359404606047708000"
},
{
"address": "0x745cf3076d8fc8bcce945381b9473ec8ce3b866b",
"kinetiqPoints": "148252752259980270000"
},
{
"address": "0x84807a0ae29facaacc76a5979a4b32c52f493948",
"kinetiqPoints": "36365443318937960000"
},
{
"address": "0x8b90736a0aa76a2821572210d81dc588ae5f8cec",
"kinetiqPoints": "390126786043492500"
},
{
"address": "0x8f0de7c3b9d106c9d3886949e69821a6d5f8c01c",
"kinetiqPoints": "761653168369544200"
},
{
"address": "0x90511925618681b84676c63f59a864f876f33b54",
"kinetiqPoints": "174129518285918470"
},
{
"address": "0x91af26d75c4d9ff042187406a7e94eee7d1ee544",
"kinetiqPoints": "332090263086813550"
},
{
"address": "0x9f502beeeddb4241a7bbd40dfa92a062c719d27a",
"kinetiqPoints": "8278417812004774000"
},
{
"address": "0xa97924bd0e21d53d2c369c340faca852486883c6",
"kinetiqPoints": "90817115972455280000"
},
{
"address": "0xafb7df4fc4f89a0e4b182e18cacdc8513bfab0a0",
"kinetiqPoints": "7010697322559591000"
},
{
"address": "0xb1b3cddcb5a4cba883fed5a12f940781d37f8240",
"kinetiqPoints": "1156188137747607000"
},
{
"address": "0xb1cfebd87789d4c4ffb7e6d667304c12c19686d4",
"kinetiqPoints": "62995130199963434000"
},
{
"address": "0xb8e9f40203effc57aebe0f144a359bedca9e581c",
"kinetiqPoints": "4383638674646852000"
},
{
"address": "0xbb25f533b178d2cdfe3ef980a9ca275b5327ff9e",
"kinetiqPoints": "10050136000591774000"
},
{
"address": "0xbb79230aa3895fee9cca03498550315470d38570",
"kinetiqPoints": "24014942193743910000"
},
{
"address": "0xc77b56831d19a30ea8e1cce9128c3275f8e6fa5d",
"kinetiqPoints": "125078632276382520"
},
{
"address": "0xddb227b8ba763ff80c95dd41cb188bba16c80a94",
"kinetiqPoints": "9976334561001618000"
},
{
"address": "0xe263d077205f58815afa01d0fe16e3d92709d219",
"kinetiqPoints": "19683897801746475000"
},
{
"address": "0xe5e0408e1e79dd2c7ee27f46aeac73f2f460dffa",
"kinetiqPoints": "680833669890086400000"
},
{
"address": "0xe7c8498c2ed6e41c8ed3c63ed6f61b1c328b85bb",
"kinetiqPoints": "1130606155569158400"
},
{
"address": "0xe91c7ff4233e2d15db539a7925b934a6ac48f847",
"kinetiqPoints": "11839830274047062000"
},
{
"address": "0xede5cf1ee0b1fe6d177a7afd212e23da982d0e43",
"kinetiqPoints": "9066126760660135000"
},
{
"address": "0xee6ed78876e4c78c41052cd6a7e6f4d10ca2a26f",
"kinetiqPoints": "9128189910110410000"
},
{
"address": "0xf8eba703f43d0b04f95f7a87636fe9d708fbe969",
"kinetiqPoints": "3223965015712727800"
}
]
}
#!/usr/bin/env bun
import { JsonRpcProvider, Interface, TypedDataEncoder } from 'ethers';
import { readFileSync } from 'node:fs';
const provider = new JsonRpcProvider('https://rpc.hyperliquid.xyz/evm');
const typedData = JSON.parse(readFileSync(new URL('./kinetiq-typed-data.json', import.meta.url)));
const digest = TypedDataEncoder.hash(typedData.domain, typedData.types, typedData.message);
const wallets = JSON.parse(readFileSync(new URL('./kinetiq-wallets.json', import.meta.url))).wallets;
const iface = new Interface(['function isValidSignature(bytes32,bytes) view returns (bytes4)']);
const ERC1271_MAGIC = '0x1626ba7e';
async function main() {
console.log('Typed-data digest:', digest);
for (const { address } of wallets) {
const data = iface.encodeFunctionData('isValidSignature', [digest, '0x']);
try {
const ret = await provider.call({ to: address, data });
console.log(`${address}: ${ret.slice(0, 10).toLowerCase() === ERC1271_MAGIC ? '✅ valid' : '⚠️ ' + ret}`);
} catch (err) {
console.error(`${address}: ✗`, err);
}
}
}
main().catch((err) => {
console.error(err);
process.exit(1);
});
#!/usr/bin/env bun
import { readFileSync } from 'node:fs';
import { TypedDataEncoder } from 'ethers';
const typedData = JSON.parse(readFileSync(new URL('./kinetiq-typed-data.json', import.meta.url)));
const digest = TypedDataEncoder.hash(typedData.domain, typedData.types, typedData.message);
console.log('Typed-data digest:', digest);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment