README.md
gno.land/r/moul/x/nativeify/v0
wugnot, backwards: escrow a GRC20, issue a native coin against it 1:1.
wugnot takes GNOT, a coin the bank holds, and issues a GRC20 receipt, because a GRC20 can be pulled by a contract and a native coin cannot. This realm runs the other direction, because a native coin can do four things a GRC20 cannot:
- move with no realm call at all, from any wallet
- ride the
-sendenvelope of a call, so it can pay for something - sit beside GNOT on an account page, with nothing registered anywhere
- be named as the gas denom by a chain whose genesis says so
What you give up, and it is not small
A native coin cannot be pulled. banker.SendCoins refuses any from that is not
the banker's own realm address, so there is no allowance, no TransferFrom, and
no way for an AMM, an escrow or a subscription to take what you approved.
Everything downstream of Approve stops working the moment a coin becomes native.
A test in this package pins it: the realm holds the strongest banker the chain
offers, the one that can mint and destroy this denom at will, and it still cannot
move a unit it does not already hold.
And the issuer of a native coin can always delete a balance, because RemoveCoin
takes an arbitrary address. This realm never calls it on an address other than its
own, and it is deployed public rather than private = true so that the code
saying so can never be replaced. Those two together are the entire guarantee;
there is no on-chain way to prove a negative about code.
Use it
# 1. play money
maketx call -pkgpath gno.land/r/moul/x/grc20faucet/v0 -func Claim
# 2. let this realm pull your RED (Home() prints the address)
maketx call -pkgpath gno.land/r/moul/x/grc20faucet/v0 -func Approve \
-args RED -args <home> -args 1000000
# 3. create the pair once, then wrap into it
maketx call -pkgpath gno.land/r/moul/x/nativeify/v0 -func Nativeify \
-args gno.land/r/moul/x/grc20faucet/v0.RED -args nred
maketx call -pkgpath gno.land/r/moul/x/nativeify/v0 -func Wrap -args nred -args 500000
# 4. it is an ordinary coin now
maketx send -to <address> -send 1000/gno.land/r/moul/x/nativeify/v0:nred
# 5. redeem, by sending the coins back
maketx call -pkgpath gno.land/r/moul/x/nativeify/v0 -func Unwrap -args nred \
-send 1000/gno.land/r/moul/x/nativeify/v0:nred
Step 5 is the interesting one. This realm could delete your coins directly and save you a flag, and it does not: a realm whose normal operation is to remove coins from addresses that never handed them over has no way left to demonstrate that it only ever does so consensually.
The rate is 1, and solvency is checkable without trusting this realm
One smallest unit of the underlying is one unit of the coin. Not 10^decimals:
the bank has no notion of divisibility, so a token with 6 decimals produces a coin
counted in the token's own smallest units, and the 6 travels to
nativereg as a display hint and
nowhere else.
Solvency reads the escrow from the GRC20 ledger and the supply from the bank,
and consults this realm's own bookkeeping for neither. If the two ever disagree,
the disagreement is the answer.
One native denom per underlying token: a second would double the chain's per-denom storage for no new capability, and realm-denom balances live under their own store keys, which are not gas-metered.
Part of moul/gno-contracts — moul's versioned gno.land contracts. See the repository for the full catalog, build/test tooling, and usage.
Dependency graph:

🧪 Highly experimental — potentially vibe-coded. Not audited; may break, change, or be removed at any time. Do not use with anything of value. Full disclaimer: DISCLAIMER.