# `gno.land/r/nym-moultest123/demo/vault` Step 7 and last of the `r/moul/demo` walkthrough: a time-locked vault over the GRC20 token from [`grc20`](../grc20). Withdrawing is deliberately two steps, so that a stolen key does not drain the vault in one transaction: ```go func Deposit(cur realm, amount uint, recoverAddress address) // caller -> vault func Unvault(cur realm, amount uint) // arm the timer func Redeem(cur realm, amount uint) // after the lock func Recover(cur realm, target address) // escape hatch ``` `Unvault` moves an amount from `vaulted` to `pending` and stamps `unlockAt = ChainHeight() + 100`. `Redeem` refuses until the chain passes that height. In between, the depositor (or whoever is watching) can call `Recover` to push the still-locked balance to the recovery address recorded at deposit time. That is the pattern: a withdrawal announces itself, and the announcement window is when a theft can be reversed. Deposited tokens live at the realm's own address (`cur.Address()`), which is what makes the vault custodial rather than an accounting fiction. ## What is wrong with it on purpose This is a demo, and two things would sink it in production: - **`Recover` has no caller check.** Anyone can call `Recover(target)` for any target. It only ever pays out to the address the target itself recorded, so it cannot steal, but it is a free denial of service: a bystander can rewind anyone's deposit at will. - **Only `Unvault`/`Redeem` are covered by tests.** `Recover` has none, flagged as a `TODO` in the test file. Read it for the two-step withdrawal shape, not as a vault to deploy. (Note that `r/moul/x/daily/vault` is a different thing entirely: a key-value store, not a token vault.) Previous: [`grc20`](../grc20). --- Part of **[moul/gno-contracts](https://github.com/moul/gno-contracts)** — moul's versioned gno.land contracts. See the repository for the full catalog, build/test tooling, and usage. **On mainnet:** [![deployment status](https://gnoscope.com/_badges/shield/status/r/nym-moultest123/demo/vault/v0?network=mainnet)](https://gnoscope.com/realm/r/nym-moultest123/demo/vault/v0) [![transactions](https://gnoscope.com/_badges/shield/txs/r/nym-moultest123/demo/vault/v0?network=mainnet)](https://gnoscope.com/realm/r/nym-moultest123/demo/vault/v0) [![unique callers](https://gnoscope.com/_badges/shield/users/r/nym-moultest123/demo/vault/v0?network=mainnet)](https://gnoscope.com/realm/r/nym-moultest123/demo/vault/v0) [![deployed revision](https://gnoscope.com/_badges/shield/version/r/nym-moultest123/demo/vault/v0?network=mainnet)](https://gnoscope.com/realm/r/nym-moultest123/demo/vault/v0) **Dependency graph:** ![gno.land/r/nym-moultest123/demo/vault/v0 dependency graph](https://raw.githubusercontent.com/moul/gno-contracts/main/_assets/gno.land/r/nym-moultest123/demo/vault/v0/deps.png) > ⚠️ **Disclaimer:** provided as-is, without warranty; not security-audited. Full disclaimer: [DISCLAIMER](https://github.com/moul/gno-contracts/blob/main/DISCLAIMER.md).