// gen generates contracts/username_registry/username_registry.wasm // Run from repo root: go run ./contracts/username_registry/gen/ // // Methods: register, resolve, lookup, transfer, release, fee // // State layout: // "name:" → owner address bytes // "addr:
" → name bytes // // Fee schedule (µT): // len=1 → 10_000_000 len=2 → 1_000_000 len=3 → 100_000 // len=4 → 10_000 len=5 → 1_000 len≥6 → 100 // // Fees are transferred from caller to the contract treasury address // (sha256(contractID+":treasury") — ownerless, only the contract can spend). package main import ( "fmt" "os" ) // ── LEB128 ─────────────────────────────────────────────────────────────────── func u(v uint64) []byte { var b []byte for { bt := byte(v & 0x7f) v >>= 7 if v != 0 { bt |= 0x80 } b = append(b, bt) if v == 0 { return b } } } func s(v int64) []byte { var b []byte for { bt := byte(v & 0x7f) v >>= 7 sign := (bt & 0x40) != 0 if (v == 0 && !sign) || (v == -1 && sign) { return append(b, bt) } b = append(b, bt|0x80) } } // ── Builders ────────────────────────────────────────────────────────────────── func cat(slices ...[]byte) []byte { var out []byte for _, sl := range slices { out = append(out, sl...) } return out } func wstr(str string) []byte { return cat(u(uint64(len(str))), []byte(str)) } func section(id byte, content []byte) []byte { return cat([]byte{id}, u(uint64(len(content))), content) } func vec(items ...[]byte) []byte { out := u(uint64(len(items))) for _, it := range items { out = append(out, it...) } return out } func functype(params, results []byte) []byte { return cat([]byte{0x60}, u(uint64(len(params))), params, u(uint64(len(results))), results) } func importFunc(mod, name string, typeIdx uint32) []byte { return cat(wstr(mod), wstr(name), []byte{0x00}, u(uint64(typeIdx))) } func exportEntry(name string, kind byte, idx uint32) []byte { return cat(wstr(name), []byte{kind}, u(uint64(idx))) } func dataSegment(offset int32, data []byte) []byte { return cat( []byte{0x00}, []byte{0x41}, s(int64(offset)), []byte{0x0B}, u(uint64(len(data))), data, ) } func funcBody(localDecls []byte, instrs ...[]byte) []byte { inner := cat(localDecls) for _, ins := range instrs { inner = append(inner, ins...) } inner = append(inner, 0x0B) // end return cat(u(uint64(len(inner))), inner) } var noLocals = u(0) func localDecl(n uint32, typ byte) []byte { return cat(u(uint64(n)), []byte{typ}) } func withLocals(decls ...[]byte) []byte { return cat(u(uint64(len(decls))), cat(decls...)) } // ── Instructions ────────────────────────────────────────────────────────────── const ( tI32 byte = 0x7F tI64 byte = 0x7E ) func call(fn uint32) []byte { return cat([]byte{0x10}, u(uint64(fn))) } func lget(i uint32) []byte { return cat([]byte{0x20}, u(uint64(i))) } func lset(i uint32) []byte { return cat([]byte{0x21}, u(uint64(i))) } func ic32(v int32) []byte { return cat([]byte{0x41}, s(int64(v))) } func ic64(v int64) []byte { return cat([]byte{0x42}, s(v)) } func block_() []byte { return []byte{0x02, 0x40} } func loop_() []byte { return []byte{0x03, 0x40} } func if_() []byte { return []byte{0x04, 0x40} } func ifI32() []byte { return []byte{0x04, tI32} } func else_() []byte { return []byte{0x05} } func end_() []byte { return []byte{0x0B} } func br_(lbl uint32) []byte { return cat([]byte{0x0C}, u(uint64(lbl))) } func brIf_(lbl uint32) []byte { return cat([]byte{0x0D}, u(uint64(lbl))) } func return_() []byte { return []byte{0x0F} } func drop() []byte { return []byte{0x1A} } func i32Eqz() []byte { return []byte{0x45} } func i32Ne() []byte { return []byte{0x47} } func i32GtU() []byte { return []byte{0x4B} } func i32GeU() []byte { return []byte{0x4F} } func i32LeU() []byte { return []byte{0x4D} } func i32Add() []byte { return []byte{0x6A} } func i64LtU() []byte { return []byte{0x54} } func i64Eqz() []byte { return []byte{0x50} } func i32Load8U() []byte { return []byte{0x2D, 0x00, 0x00} } func i32Store8() []byte { return []byte{0x3A, 0x00, 0x00} } // ── Memory layout ───────────────────────────────────────────────────────────── // // 0x000 64 arg[0] name buffer // 0x040 128 arg[1] new_owner buffer // 0x0C0 128 caller buffer // 0x140 64 contract treasury buffer // 0x180 128 state-read result buffer // // Constant string data (read-only, written by data segments): // 0x200 5 "name:" // 0x206 5 "addr:" // 0x20C 12 "registered: " // 0x218 12 "name taken: " // 0x224 11 "not found: " // 0x230 7 "owner: " // 0x238 13 "transferred: " // 0x246 14 "unauthorized: " // 0x255 10 "released: " // 0x260 6 "name: " // 0x267 9 "no name: " // 0x271 14 "insufficient: " // 0x280 13 "fee: 10000000" // 0x28D 12 "fee: 1000000" // 0x299 11 "fee: 100000" // 0x2A4 10 "fee: 10000" // 0x2AE 9 "fee: 1000" // 0x2B7 8 "fee: 100" // // 0x300 256 scratch buffer (used by buildKey + logPrefixName) const ( offArg0 int32 = 0x000 offArg1 int32 = 0x040 offCaller int32 = 0x0C0 offTreasury int32 = 0x140 offStateRead int32 = 0x180 offPfxName int32 = 0x200 // "name:" 5 bytes offPfxAddr int32 = 0x206 // "addr:" 5 bytes offRegisteredPfx int32 = 0x20C // "registered: " 12 offNameTakenPfx int32 = 0x218 // "name taken: " 12 offNotFoundPfx int32 = 0x224 // "not found: " 11 offOwnerPfx int32 = 0x230 // "owner: " 7 offTransferredPfx int32 = 0x238 // "transferred: " 13 offUnauthPfx int32 = 0x246 // "unauthorized: " 14 offReleasedPfx int32 = 0x255 // "released: " 10 offNamePfx int32 = 0x260 // "name: " 6 offNoNamePfx int32 = 0x267 // "no name: " 9 offInsuffPfx int32 = 0x271 // "insufficient: " 14 offFee1 int32 = 0x280 // "fee: 10000000" 13 offFee2 int32 = 0x28D // "fee: 1000000" 12 offFee3 int32 = 0x299 // "fee: 100000" 11 offFee4 int32 = 0x2A4 // "fee: 10000" 10 offFee5 int32 = 0x2AE // "fee: 1000" 9 offFee6 int32 = 0x2B7 // "fee: 100" 8 offScratch int32 = 0x300 ) // ── Import / function indices ───────────────────────────────────────────────── const ( // imports (0-based) fnGetArgStr = 0 fnGetCaller = 1 fnGetState = 2 fnSetState = 3 fnLog = 4 fnTransfer = 5 fnGetBalance = 6 fnGetContractTreasury = 7 // local functions (after 8 imports) fnBytesEqual = 8 fnMemcpy = 9 fnLogPrefixName = 10 fnCalcFee = 11 fnBuildKey = 12 fnRegister = 13 fnResolve = 14 fnLookup = 15 fnTransferFn = 16 fnRelease = 17 fnFee = 18 ) // ── Helper function bodies ──────────────────────────────────────────────────── // $bytes_equal(aPtr, bPtr, len i32) → i32 (1=equal, 0=not) // extra locals: i(3), same(4) func bytesEqualBody() []byte { return funcBody( withLocals(localDecl(2, tI32)), ic32(1), lset(4), ic32(0), lset(3), block_(), loop_(), lget(3), lget(2), i32GeU(), brIf_(1), lget(0), lget(3), i32Add(), i32Load8U(), lget(1), lget(3), i32Add(), i32Load8U(), i32Ne(), if_(), ic32(0), lset(4), br_(2), end_(), lget(3), ic32(1), i32Add(), lset(3), br_(0), end_(), end_(), lget(4), ) } // $memcpy(dst, src, len i32) // extra local: i(3) func memcpyBody() []byte { return funcBody( withLocals(localDecl(1, tI32)), ic32(0), lset(3), block_(), loop_(), lget(3), lget(2), i32GeU(), brIf_(1), lget(0), lget(3), i32Add(), lget(1), lget(3), i32Add(), i32Load8U(), i32Store8(), lget(3), ic32(1), i32Add(), lset(3), br_(0), end_(), end_(), ) } // $log_prefix_name(prefixPtr, prefixLen, suffixPtr, suffixLen i32) // Concatenates prefix+suffix into scratch and logs the result. func logPrefixNameBody() []byte { return funcBody( noLocals, ic32(offScratch), lget(0), lget(1), call(fnMemcpy), ic32(offScratch), lget(1), i32Add(), lget(2), lget(3), call(fnMemcpy), ic32(offScratch), lget(1), lget(3), i32Add(), call(fnLog), ) } // $calc_fee(nameLen i32) → i64 // Fee tiers: 1→10M, 2→1M, 3→100K, 4→10K, 5→1K, ≥6→100 µT func calcFeeBody() []byte { return funcBody( noLocals, lget(0), ic32(1), i32LeU(), if_(), ic64(10_000_000), return_(), end_(), lget(0), ic32(2), i32Ne(), if_(), // len>=3 lget(0), ic32(3), i32Ne(), if_(), // len>=4 lget(0), ic32(4), i32Ne(), if_(), // len>=5 lget(0), ic32(5), i32Ne(), if_(), // len>=6 ic64(100), return_(), end_(), ic64(1_000), return_(), end_(), ic64(10_000), return_(), end_(), ic64(100_000), return_(), end_(), ic64(1_000_000), ) } // $build_key(pfxOff, pfxLen, dataOff, dataLen i32) → keyLen i32 // Writes pfx+data into scratch (offScratch) and returns total length. func buildKeyBody() []byte { return funcBody( noLocals, ic32(offScratch), lget(0), lget(1), call(fnMemcpy), ic32(offScratch), lget(1), i32Add(), lget(2), lget(3), call(fnMemcpy), lget(1), lget(3), i32Add(), ) } // isOwnerCheck emits code that, given two length locals, leaves i32(1=owner,0=not) on stack. // Assumes caller bytes are at offCaller and existing owner bytes at offStateRead. func isOwnerCheck(callerLenLocal, existingLenLocal uint32) []byte { return cat( lget(callerLenLocal), lget(existingLenLocal), i32Ne(), ifI32(), ic32(0), else_(), ic32(offCaller), ic32(offStateRead), lget(callerLenLocal), call(fnBytesEqual), end_(), ) } // ── Contract method bodies ──────────────────────────────────────────────────── // register(name string) // Locals (i32): nameLen(0), callerLen(1), existingLen(2), treasuryLen(3), keyLen(4) // Locals (i64): fee(5) func registerBody() []byte { return funcBody( withLocals(localDecl(5, tI32), localDecl(1, tI64)), // Read name arg ic32(0), ic32(offArg0), ic32(64), call(fnGetArgStr), lset(0), lget(0), i32Eqz(), if_(), return_(), end_(), // Check name not already taken ic32(offPfxName), ic32(5), ic32(offArg0), lget(0), call(fnBuildKey), lset(4), ic32(offScratch), lget(4), ic32(offStateRead), ic32(128), call(fnGetState), lset(2), lget(2), ic32(0), i32GtU(), if_(), ic32(offNameTakenPfx), ic32(12), ic32(offArg0), lget(0), call(fnLogPrefixName), return_(), end_(), // Get caller ic32(offCaller), ic32(128), call(fnGetCaller), lset(1), // Compute fee lget(0), call(fnCalcFee), lset(5), // Check balance >= fee ic32(offCaller), lget(1), call(fnGetBalance), lget(5), i64LtU(), if_(), ic32(offInsuffPfx), ic32(14), ic32(offArg0), lget(0), call(fnLogPrefixName), return_(), end_(), // Get treasury address ic32(offTreasury), ic32(64), call(fnGetContractTreasury), lset(3), // Transfer fee: caller → treasury ic32(offCaller), lget(1), ic32(offTreasury), lget(3), lget(5), call(fnTransfer), drop(), // Write name→owner ic32(offPfxName), ic32(5), ic32(offArg0), lget(0), call(fnBuildKey), lset(4), ic32(offScratch), lget(4), ic32(offCaller), lget(1), call(fnSetState), // Write addr→name (reverse index) ic32(offPfxAddr), ic32(5), ic32(offCaller), lget(1), call(fnBuildKey), lset(4), ic32(offScratch), lget(4), ic32(offArg0), lget(0), call(fnSetState), // Log success ic32(offRegisteredPfx), ic32(12), ic32(offArg0), lget(0), call(fnLogPrefixName), ) } // resolve(name string) // Locals: nameLen(0), ownerLen(1), keyLen(2) func resolveBody() []byte { return funcBody( withLocals(localDecl(3, tI32)), ic32(0), ic32(offArg0), ic32(64), call(fnGetArgStr), lset(0), lget(0), i32Eqz(), if_(), return_(), end_(), ic32(offPfxName), ic32(5), ic32(offArg0), lget(0), call(fnBuildKey), lset(2), ic32(offScratch), lget(2), ic32(offStateRead), ic32(128), call(fnGetState), lset(1), lget(1), i32Eqz(), if_(), ic32(offNotFoundPfx), ic32(11), ic32(offArg0), lget(0), call(fnLogPrefixName), return_(), end_(), ic32(offOwnerPfx), ic32(7), ic32(offStateRead), lget(1), call(fnLogPrefixName), ) } // lookup(address string) — reverse lookup address → name // Locals: addrLen(0), nameLen(1), keyLen(2) func lookupBody() []byte { return funcBody( withLocals(localDecl(3, tI32)), ic32(0), ic32(offArg0), ic32(128), call(fnGetArgStr), lset(0), lget(0), i32Eqz(), if_(), return_(), end_(), ic32(offPfxAddr), ic32(5), ic32(offArg0), lget(0), call(fnBuildKey), lset(2), ic32(offScratch), lget(2), ic32(offStateRead), ic32(128), call(fnGetState), lset(1), lget(1), i32Eqz(), if_(), ic32(offNoNamePfx), ic32(9), ic32(offArg0), lget(0), call(fnLogPrefixName), return_(), end_(), ic32(offNamePfx), ic32(6), ic32(offStateRead), lget(1), call(fnLogPrefixName), ) } // transfer(name, new_owner) — transfer username ownership // Locals: nameLen(0), newOwnerLen(1), callerLen(2), existingLen(3), keyLen(4) func transferBody() []byte { return funcBody( withLocals(localDecl(5, tI32)), ic32(0), ic32(offArg0), ic32(64), call(fnGetArgStr), lset(0), lget(0), i32Eqz(), if_(), return_(), end_(), ic32(1), ic32(offArg1), ic32(128), call(fnGetArgStr), lset(1), lget(1), i32Eqz(), if_(), return_(), end_(), // Look up existing owner ic32(offPfxName), ic32(5), ic32(offArg0), lget(0), call(fnBuildKey), lset(4), ic32(offScratch), lget(4), ic32(offStateRead), ic32(128), call(fnGetState), lset(3), lget(3), i32Eqz(), if_(), ic32(offNotFoundPfx), ic32(11), ic32(offArg0), lget(0), call(fnLogPrefixName), return_(), end_(), // Verify caller is the current owner ic32(offCaller), ic32(128), call(fnGetCaller), lset(2), isOwnerCheck(2, 3), i32Eqz(), if_(), ic32(offUnauthPfx), ic32(14), ic32(offArg0), lget(0), call(fnLogPrefixName), return_(), end_(), // Delete old reverse index: addr: → "" ic32(offPfxAddr), ic32(5), ic32(offStateRead), lget(3), call(fnBuildKey), lset(4), ic32(offScratch), lget(4), ic32(offScratch), ic32(0), call(fnSetState), // Update forward index: name: → newOwner ic32(offPfxName), ic32(5), ic32(offArg0), lget(0), call(fnBuildKey), lset(4), ic32(offScratch), lget(4), ic32(offArg1), lget(1), call(fnSetState), // Add new reverse index: addr: → name ic32(offPfxAddr), ic32(5), ic32(offArg1), lget(1), call(fnBuildKey), lset(4), ic32(offScratch), lget(4), ic32(offArg0), lget(0), call(fnSetState), ic32(offTransferredPfx), ic32(13), ic32(offArg0), lget(0), call(fnLogPrefixName), ) } // release(name) — release a username registration // Locals: nameLen(0), callerLen(1), existingLen(2), keyLen(3) func releaseBody() []byte { return funcBody( withLocals(localDecl(4, tI32)), ic32(0), ic32(offArg0), ic32(64), call(fnGetArgStr), lset(0), lget(0), i32Eqz(), if_(), return_(), end_(), ic32(offPfxName), ic32(5), ic32(offArg0), lget(0), call(fnBuildKey), lset(3), ic32(offScratch), lget(3), ic32(offStateRead), ic32(128), call(fnGetState), lset(2), lget(2), i32Eqz(), if_(), ic32(offNotFoundPfx), ic32(11), ic32(offArg0), lget(0), call(fnLogPrefixName), return_(), end_(), ic32(offCaller), ic32(128), call(fnGetCaller), lset(1), isOwnerCheck(1, 2), i32Eqz(), if_(), ic32(offUnauthPfx), ic32(14), ic32(offArg0), lget(0), call(fnLogPrefixName), return_(), end_(), // Delete reverse index: addr: → "" ic32(offPfxAddr), ic32(5), ic32(offStateRead), lget(2), call(fnBuildKey), lset(3), ic32(offScratch), lget(3), ic32(offScratch), ic32(0), call(fnSetState), // Delete forward index: name: → "" ic32(offPfxName), ic32(5), ic32(offArg0), lget(0), call(fnBuildKey), lset(3), ic32(offScratch), lget(3), ic32(offScratch), ic32(0), call(fnSetState), ic32(offReleasedPfx), ic32(10), ic32(offArg0), lget(0), call(fnLogPrefixName), ) } // fee(name) — log the registration fee for a given name // Uses pre-baked static strings; no arithmetic needed. // Locals: nameLen(0) func feeBody() []byte { return funcBody( withLocals(localDecl(1, tI32)), ic32(0), ic32(offArg0), ic32(64), call(fnGetArgStr), lset(0), lget(0), i32Eqz(), if_(), return_(), end_(), // Branch on name length and log the matching static fee string. lget(0), ic32(1), i32LeU(), if_(), ic32(offFee1), ic32(13), call(fnLog), return_(), end_(), lget(0), ic32(2), i32Ne(), if_(), // len >= 3 lget(0), ic32(3), i32Ne(), if_(), // len >= 4 lget(0), ic32(4), i32Ne(), if_(), // len >= 5 lget(0), ic32(5), i32Ne(), if_(), // len >= 6 ic32(offFee6), ic32(8), call(fnLog), return_(), end_(), ic32(offFee5), ic32(9), call(fnLog), return_(), end_(), ic32(offFee4), ic32(10), call(fnLog), return_(), end_(), ic32(offFee3), ic32(11), call(fnLog), return_(), end_(), // len == 2 ic32(offFee2), ic32(12), call(fnLog), ) } // ── main ────────────────────────────────────────────────────────────────────── func main() { // ── Type table ──────────────────────────────────────────────────────────── // 0: (i32,i32,i32)→(i32) get_arg_str, bytes_equal // 1: (i32,i32)→(i32) get_caller, get_contract_treasury // 2: (i32,i32,i32,i32)→(i32) get_state, build_key // 3: (i32,i32,i32,i32)→() set_state, log_prefix_name // 4: (i32,i32)→() log // 5: (i32,i32,i32,i32,i64)→(i32) transfer // 6: (i32,i32)→(i64) get_balance // 7: ()→() exported methods // 8: (i32,i32,i32)→() memcpy // 9: (i32)→(i64) calc_fee typeSection := section(0x01, vec( functype([]byte{tI32, tI32, tI32}, []byte{tI32}), // 0 functype([]byte{tI32, tI32}, []byte{tI32}), // 1 functype([]byte{tI32, tI32, tI32, tI32}, []byte{tI32}), // 2 functype([]byte{tI32, tI32, tI32, tI32}, []byte{}), // 3 functype([]byte{tI32, tI32}, []byte{}), // 4 functype([]byte{tI32, tI32, tI32, tI32, tI64}, []byte{tI32}), // 5 functype([]byte{tI32, tI32}, []byte{tI64}), // 6 functype([]byte{}, []byte{}), // 7 functype([]byte{tI32, tI32, tI32}, []byte{}), // 8 functype([]byte{tI32}, []byte{tI64}), // 9 )) importSection := section(0x02, vec( importFunc("env", "get_arg_str", 0), // 0 type 0 importFunc("env", "get_caller", 1), // 1 type 1 importFunc("env", "get_state", 2), // 2 type 2 importFunc("env", "set_state", 3), // 3 type 3 importFunc("env", "log", 4), // 4 type 4 importFunc("env", "transfer", 5), // 5 type 5 importFunc("env", "get_balance", 6), // 6 type 6 importFunc("env", "get_contract_treasury", 1), // 7 type 1 )) // 11 local functions functionSection := section(0x03, vec( u(0), // bytes_equal type 0 u(8), // memcpy type 8 u(3), // log_prefix_name type 3 u(9), // calc_fee type 9 u(2), // build_key type 2 u(7), // register type 7 u(7), // resolve type 7 u(7), // lookup type 7 u(7), // transfer_fn type 7 u(7), // release type 7 u(7), // fee type 7 )) memorySection := section(0x05, vec(cat([]byte{0x00}, u(1)))) exportSection := section(0x07, vec( exportEntry("memory", 0x02, 0), exportEntry("register", 0x00, fnRegister), exportEntry("resolve", 0x00, fnResolve), exportEntry("lookup", 0x00, fnLookup), exportEntry("transfer", 0x00, fnTransferFn), exportEntry("release", 0x00, fnRelease), exportEntry("fee", 0x00, fnFee), )) dataSection := section(0x0B, cat( u(19), dataSegment(offPfxName, []byte("name:")), dataSegment(offPfxAddr, []byte("addr:")), dataSegment(offRegisteredPfx, []byte("registered: ")), dataSegment(offNameTakenPfx, []byte("name taken: ")), dataSegment(offNotFoundPfx, []byte("not found: ")), dataSegment(offOwnerPfx, []byte("owner: ")), dataSegment(offTransferredPfx, []byte("transferred: ")), dataSegment(offUnauthPfx, []byte("unauthorized: ")), dataSegment(offReleasedPfx, []byte("released: ")), dataSegment(offNamePfx, []byte("name: ")), dataSegment(offNoNamePfx, []byte("no name: ")), dataSegment(offInsuffPfx, []byte("insufficient: ")), dataSegment(offFee1, []byte("fee: 10000000")), dataSegment(offFee2, []byte("fee: 1000000")), dataSegment(offFee3, []byte("fee: 100000")), dataSegment(offFee4, []byte("fee: 10000")), dataSegment(offFee5, []byte("fee: 1000")), dataSegment(offFee6, []byte("fee: 100")), // pad entry to make count = 19 (u(19) above) — actually 18 strings above // Let me count: pfxName, pfxAddr, registered, nameTaken, notFound, owner, // transferred, unauth, released, name, noName, insuff, fee1..fee6 = 18 // Fix: change u(19) → u(18) — corrected below in final assembly. )) // Recount: 18 data segments total — rebuild without the u() wrapper mismatch. dataSection = section(0x0B, cat( u(18), dataSegment(offPfxName, []byte("name:")), dataSegment(offPfxAddr, []byte("addr:")), dataSegment(offRegisteredPfx, []byte("registered: ")), dataSegment(offNameTakenPfx, []byte("name taken: ")), dataSegment(offNotFoundPfx, []byte("not found: ")), dataSegment(offOwnerPfx, []byte("owner: ")), dataSegment(offTransferredPfx, []byte("transferred: ")), dataSegment(offUnauthPfx, []byte("unauthorized: ")), dataSegment(offReleasedPfx, []byte("released: ")), dataSegment(offNamePfx, []byte("name: ")), dataSegment(offNoNamePfx, []byte("no name: ")), dataSegment(offInsuffPfx, []byte("insufficient: ")), dataSegment(offFee1, []byte("fee: 10000000")), dataSegment(offFee2, []byte("fee: 1000000")), dataSegment(offFee3, []byte("fee: 100000")), dataSegment(offFee4, []byte("fee: 10000")), dataSegment(offFee5, []byte("fee: 1000")), dataSegment(offFee6, []byte("fee: 100")), )) codeSection := section(0x0A, cat( u(11), bytesEqualBody(), memcpyBody(), logPrefixNameBody(), calcFeeBody(), buildKeyBody(), registerBody(), resolveBody(), lookupBody(), transferBody(), releaseBody(), feeBody(), )) module := cat( []byte{0x00, 0x61, 0x73, 0x6d}, []byte{0x01, 0x00, 0x00, 0x00}, typeSection, importSection, functionSection, memorySection, exportSection, dataSection, codeSection, ) out := "contracts/username_registry/username_registry.wasm" if err := os.WriteFile(out, module, 0644); err != nil { fmt.Fprintln(os.Stderr, "write:", err) os.Exit(1) } fmt.Printf("Written %s (%d bytes)\n", out, len(module)) }