// gen generates contracts/governance/governance.wasm // Run from repo root: go run ./contracts/governance/gen/ // // Methods: init, propose, approve, reject, get, get_pending, set_admin // // State layout (all keys are raw UTF-8 strings): // "admin" → admin address bytes // "param:" → current live value bytes // "prop:" → pending proposed value bytes // // Access control: // approve / reject / set_admin → admin only // propose / get / get_pending → anyone // init → anyone (but only writes if admin not set) 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) } } 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) 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...)) } 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 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 i32Eqz() []byte { return []byte{0x45} } func i32Ne() []byte { return []byte{0x47} } func i32GtU() []byte { return []byte{0x4B} } func i32GeU() []byte { return []byte{0x4F} } func i32Add() []byte { return []byte{0x6A} } func i32Load8U() []byte { return []byte{0x2D, 0x00, 0x00} } func i32Store8() []byte { return []byte{0x3A, 0x00, 0x00} } // ── Memory layout ───────────────────────────────────────────────────────────── // // 0x000 64 arg[0] key buffer // 0x040 256 arg[1] value buffer // 0x140 128 caller buffer // 0x1C0 128 admin state-read buffer // 0x240 256 value state-read buffer // 0x340 256 scratch (build_key writes here, log_prefix_name writes here) // // Constant strings: // 0x500 6 "admin" (state key) // 0x506 6 "param:" (state key prefix) // 0x50D 5 "prop:" (state key prefix) // 0x513 13 "initialized: " // 0x521 9 "proposed: " // 0x52B 10 "approved: " // 0x536 10 "rejected: " // 0x541 8 "value: " // 0x549 11 "not set: " // 0x555 9 "pending: " // 0x55F 12 "no pending: " // 0x56C 7 "admin: " // 0x574 14 "unauthorized: " // 0x583 14 "already init: " const ( offArg0 int32 = 0x000 offArg1 int32 = 0x040 offCaller int32 = 0x140 offAdminRead int32 = 0x1C0 offValRead int32 = 0x240 offScratch int32 = 0x340 offKeyAdmin int32 = 0x500 // "admin" 5 bytes offPfxParam int32 = 0x506 // "param:" 6 bytes offPfxProp int32 = 0x50D // "prop:" 5 bytes offInitedPfx int32 = 0x513 // "initialized: " 14 offProposedPfx int32 = 0x521 // "proposed: " 9 (key=val shown as arg0=arg1) offApprovedPfx int32 = 0x52B // "approved: " 10 offRejectedPfx int32 = 0x536 // "rejected: " 10 offValuePfx int32 = 0x541 // "value: " 7 offNotSetPfx int32 = 0x549 // "not set: " 9 offPendingPfx int32 = 0x555 // "pending: " 9 offNoPendingPfx int32 = 0x55F // "no pending: " 12 offAdminPfx int32 = 0x56C // "admin: " 7 offUnauthPfx int32 = 0x574 // "unauthorized: " 14 offAlreadyPfx int32 = 0x583 // "already init" 12 ) const ( fnGetArgStr = 0 fnGetCaller = 1 fnGetState = 2 fnSetState = 3 fnLog = 4 fnBytesEqual = 5 fnMemcpy = 6 fnLogPrefixName = 7 fnBuildKey = 8 fnInit = 9 fnPropose = 10 fnApprove = 11 fnReject = 12 fnGet = 13 fnGetPending = 14 fnSetAdmin = 15 ) // ── Helper bodies ───────────────────────────────────────────────────────────── 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), ) } 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_(), ) } 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), ) } // $build_key(pfxOff, pfxLen, dataOff, dataLen i32) → keyLen i32 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(), ) } // isCallerAdmin: reads admin from state into offAdminRead, returns 1 if caller==admin. // (callerLenLocal i32) → i32 // Leaves adminLen on stack as side effect (stored in local adminLenLocal). // Emits code that: reads admin, compares with caller. // Uses offAdminRead for the state read buffer. func isCallerAdminCode(callerLenLocal, adminLenLocal uint32) []byte { return cat( // adminLen = get_state("admin", 5, offAdminRead, 128) ic32(offKeyAdmin), ic32(5), ic32(offAdminRead), ic32(128), call(fnGetState), lset(adminLenLocal), // if adminLen == 0: not initialized → return 0 lget(adminLenLocal), i32Eqz(), ifI32(), ic32(0), else_(), // bytes_equal(offCaller, offAdminRead, callerLen) if callerLen==adminLen else 0 lget(callerLenLocal), lget(adminLenLocal), i32Ne(), ifI32(), ic32(0), else_(), ic32(offCaller), ic32(offAdminRead), lget(callerLenLocal), call(fnBytesEqual), end_(), end_(), ) } // ── Contract method bodies ──────────────────────────────────────────────────── // init() — set caller as admin (only if not already initialized) func initBody() []byte { return funcBody( withLocals(localDecl(2, tI32)), // callerLen = get_caller(offCaller, 128) ic32(offCaller), ic32(128), call(fnGetCaller), lset(0), // Check if admin already set ic32(offKeyAdmin), ic32(5), ic32(offAdminRead), ic32(128), call(fnGetState), lset(1), lget(1), ic32(0), i32GtU(), if_(), ic32(offAlreadyPfx), ic32(12), ic32(offCaller), lget(0), call(fnLogPrefixName), return_(), end_(), // set state["admin"] = caller ic32(offKeyAdmin), ic32(5), ic32(offCaller), lget(0), call(fnSetState), ic32(offInitedPfx), ic32(14), ic32(offCaller), lget(0), call(fnLogPrefixName), ) } // propose(key, value) — store pending proposal // Locals: keyLen(0), valLen(1), keyBufLen(2) func proposeBody() []byte { return funcBody( withLocals(localDecl(3, tI32)), ic32(0), ic32(offArg0), ic32(64), call(fnGetArgStr), lset(0), lget(0), i32Eqz(), if_(), return_(), end_(), ic32(1), ic32(offArg1), ic32(256), call(fnGetArgStr), lset(1), lget(1), i32Eqz(), if_(), return_(), end_(), // set state["prop:"] = value ic32(offPfxProp), ic32(5), ic32(offArg0), lget(0), call(fnBuildKey), lset(2), ic32(offScratch), lget(2), ic32(offArg1), lget(1), call(fnSetState), // log "proposed: " ic32(offProposedPfx), ic32(9), ic32(offArg0), lget(0), call(fnLogPrefixName), ) } // approve(key) — admin: move prop: → param: // Locals: keyLen(0), callerLen(1), adminLen(2), propLen(3), keyBufLen(4) func approveBody() []byte { return funcBody( withLocals(localDecl(5, tI32)), ic32(0), ic32(offArg0), ic32(64), call(fnGetArgStr), lset(0), lget(0), i32Eqz(), if_(), return_(), end_(), ic32(offCaller), ic32(128), call(fnGetCaller), lset(1), isCallerAdminCode(1, 2), i32Eqz(), if_(), ic32(offUnauthPfx), ic32(14), ic32(offArg0), lget(0), call(fnLogPrefixName), return_(), end_(), // Read pending value: get_state("prop:", offValRead, 256) ic32(offPfxProp), ic32(5), ic32(offArg0), lget(0), call(fnBuildKey), lset(4), ic32(offScratch), lget(4), ic32(offValRead), ic32(256), call(fnGetState), lset(3), lget(3), i32Eqz(), if_(), ic32(offNoPendingPfx), ic32(12), ic32(offArg0), lget(0), call(fnLogPrefixName), return_(), end_(), // set state["param:"] = offValRead[0..propLen) ic32(offPfxParam), ic32(6), ic32(offArg0), lget(0), call(fnBuildKey), lset(4), ic32(offScratch), lget(4), ic32(offValRead), lget(3), call(fnSetState), // delete pending: set state["prop:"] = "" ic32(offPfxProp), ic32(5), ic32(offArg0), lget(0), call(fnBuildKey), lset(4), ic32(offScratch), lget(4), ic32(offScratch), ic32(0), call(fnSetState), ic32(offApprovedPfx), ic32(10), ic32(offArg0), lget(0), call(fnLogPrefixName), ) } // reject(key) — admin: delete prop: // Locals: keyLen(0), callerLen(1), adminLen(2), keyBufLen(3) func rejectBody() []byte { return funcBody( withLocals(localDecl(4, tI32)), ic32(0), ic32(offArg0), ic32(64), call(fnGetArgStr), lset(0), lget(0), i32Eqz(), if_(), return_(), end_(), ic32(offCaller), ic32(128), call(fnGetCaller), lset(1), isCallerAdminCode(1, 2), i32Eqz(), if_(), ic32(offUnauthPfx), ic32(14), ic32(offArg0), lget(0), call(fnLogPrefixName), return_(), end_(), // delete pending ic32(offPfxProp), ic32(5), ic32(offArg0), lget(0), call(fnBuildKey), lset(3), ic32(offScratch), lget(3), ic32(offScratch), ic32(0), call(fnSetState), ic32(offRejectedPfx), ic32(10), ic32(offArg0), lget(0), call(fnLogPrefixName), ) } // get(key) — read live parameter value // Locals: keyLen(0), valLen(1), keyBufLen(2) func getBody() []byte { return funcBody( withLocals(localDecl(3, tI32)), ic32(0), ic32(offArg0), ic32(64), call(fnGetArgStr), lset(0), lget(0), i32Eqz(), if_(), return_(), end_(), ic32(offPfxParam), ic32(6), ic32(offArg0), lget(0), call(fnBuildKey), lset(2), ic32(offScratch), lget(2), ic32(offValRead), ic32(256), call(fnGetState), lset(1), lget(1), i32Eqz(), if_(), ic32(offNotSetPfx), ic32(9), ic32(offArg0), lget(0), call(fnLogPrefixName), return_(), end_(), ic32(offValuePfx), ic32(7), ic32(offValRead), lget(1), call(fnLogPrefixName), ) } // get_pending(key) — read pending proposal // Locals: keyLen(0), valLen(1), keyBufLen(2) func getPendingBody() []byte { return funcBody( withLocals(localDecl(3, tI32)), ic32(0), ic32(offArg0), ic32(64), call(fnGetArgStr), lset(0), lget(0), i32Eqz(), if_(), return_(), end_(), ic32(offPfxProp), ic32(5), ic32(offArg0), lget(0), call(fnBuildKey), lset(2), ic32(offScratch), lget(2), ic32(offValRead), ic32(256), call(fnGetState), lset(1), lget(1), i32Eqz(), if_(), ic32(offNoPendingPfx), ic32(12), ic32(offArg0), lget(0), call(fnLogPrefixName), return_(), end_(), ic32(offPendingPfx), ic32(9), ic32(offValRead), lget(1), call(fnLogPrefixName), ) } // set_admin(new_admin) — transfer admin role // Locals: newAdminLen(0), callerLen(1), adminLen(2) func setAdminBody() []byte { return funcBody( withLocals(localDecl(3, tI32)), ic32(0), ic32(offArg0), ic32(128), call(fnGetArgStr), lset(0), lget(0), i32Eqz(), if_(), return_(), end_(), ic32(offCaller), ic32(128), call(fnGetCaller), lset(1), isCallerAdminCode(1, 2), i32Eqz(), if_(), ic32(offUnauthPfx), ic32(14), ic32(offArg0), lget(0), call(fnLogPrefixName), return_(), end_(), ic32(offKeyAdmin), ic32(5), ic32(offArg0), lget(0), call(fnSetState), ic32(offAdminPfx), ic32(7), ic32(offArg0), lget(0), call(fnLogPrefixName), ) } // ── main ────────────────────────────────────────────────────────────────────── func main() { // Types: // 0: (i32,i32,i32)→(i32) get_arg_str, bytes_equal // 1: (i32,i32)→(i32) get_caller // 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: ()→() exported methods // 6: (i32,i32,i32)→() memcpy 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{}, []byte{}), // 5 functype([]byte{tI32, tI32, tI32}, []byte{}), // 6 )) 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 )) // 11 local functions functionSection := section(0x03, vec( u(0), // bytes_equal type 0 u(6), // memcpy type 6 u(3), // log_prefix_name type 3 u(2), // build_key type 2 u(5), // init type 5 u(5), // propose type 5 u(5), // approve type 5 u(5), // reject type 5 u(5), // get type 5 u(5), // get_pending type 5 u(5), // set_admin type 5 )) memorySection := section(0x05, vec(cat([]byte{0x00}, u(2)))) // 2 pages = 128KB exportSection := section(0x07, vec( exportEntry("memory", 0x02, 0), exportEntry("init", 0x00, fnInit), exportEntry("propose", 0x00, fnPropose), exportEntry("approve", 0x00, fnApprove), exportEntry("reject", 0x00, fnReject), exportEntry("get", 0x00, fnGet), exportEntry("get_pending", 0x00, fnGetPending), exportEntry("set_admin", 0x00, fnSetAdmin), )) dataSection := section(0x0B, cat( u(14), dataSegment(offKeyAdmin, []byte("admin")), dataSegment(offPfxParam, []byte("param:")), dataSegment(offPfxProp, []byte("prop:")), dataSegment(offInitedPfx, []byte("initialized: ")), dataSegment(offProposedPfx, []byte("proposed: ")), dataSegment(offApprovedPfx, []byte("approved: ")), dataSegment(offRejectedPfx, []byte("rejected: ")), dataSegment(offValuePfx, []byte("value: ")), dataSegment(offNotSetPfx, []byte("not set: ")), dataSegment(offPendingPfx, []byte("pending: ")), dataSegment(offNoPendingPfx, []byte("no pending: ")), dataSegment(offAdminPfx, []byte("admin: ")), dataSegment(offUnauthPfx, []byte("unauthorized: ")), dataSegment(offAlreadyPfx, []byte("already init")), )) codeSection := section(0x0A, cat( u(11), bytesEqualBody(), memcpyBody(), logPrefixNameBody(), buildKeyBody(), initBody(), proposeBody(), approveBody(), rejectBody(), getBody(), getPendingBody(), setAdminBody(), )) module := cat( []byte{0x00, 0x61, 0x73, 0x6d}, []byte{0x01, 0x00, 0x00, 0x00}, typeSection, importSection, functionSection, memorySection, exportSection, dataSection, codeSection, ) out := "contracts/governance/governance.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)) }