WDATA is a wrapped-token contract that lets users exchange native DATA for an
ERC-20-compatible representation at a one-to-one ratio. It is inspired by WETH9
and built on Solady's ERC20.
| Name | Wrapped DATA |
| Symbol | WDATA |
| Decimals | 18 |
| Solidity | 0.8.23 (EVM cancun) |
| Base | solady/tokens/ERC20 |
Deposits mint WDATA 1:1 with the native DATA sent; withdrawals burn WDATA and return the native DATA. The contract holds the native DATA backing the supply, so the WDATA total supply always equals the contract's native balance.
src/WDATA.sol implements:
deposit()(payable) — mintsmsg.valueWDATA to the caller and emitsDeposit. Plain native transfers to the contract route here viareceive().withdraw(uint value)— burnsvalueWDATA from the caller, forwards the same amount of native DATA back via a low-level call, and emitsWithdrawal. Reverts withDATATransferFailedif the transfer fails.
It overrides four inherited functions:
name()/symbol()— return the constants"Wrapped DATA"and"WDATA".approve— reverts withERC20InvalidSpenderon self-approval.transfer/transferFrom— revert withERC20InvalidReceiverwhen the recipient is the zero address or the WDATA contract itself._givePermit2InfiniteAllowance()— returnstrue, granting the canonical Permit2 contract an infinite allowance on every holder's balance.
WDATA is deployed via a CREATE3 factory, so its address depends only on
(factory, salt) — not on the contract's init code:
- Factory:
0x9fBB3DF7C40Da2e5A0dE984fFE2CCB7C47cd0ABf(Story Protocol's Create3 genesis predeploy; override withCREATE3_FACTORY) - Salt:
keccak256("WDATA") - Deterministic address:
0xD18a56346227f25D1410F98f78234305660bB877
forge script script/Deploy.s.sol:Deploy \
--rpc-url https://aeneid.storyrpc.io \
--account <keystore> --broadcast --legacyThe script deploys a Create3 factory itself if none exists at the target, and
is idempotent — re-running against an already-deployed address is a no-op.
script/Smoke.s.sol sends real transactions against a live deployment: it
deposits a small amount, verifies the mint, then withdraws it so the broadcasting
account's balance is left unchanged (minus gas).
forge script script/Smoke.s.sol:Smoke \
--rpc-url https://aeneid.storyrpc.io \
--account aeneid --broadcast --legacy --with-gas-price 1gweiOverride the target with WDATA_ADDRESS, the deposit amount (wei) with
SMOKE_AMOUNT, and the gas reserve with SMOKE_GAS_RESERVE. Fund the sender at
the Story Aeneid faucet.
Built with Foundry. Dependencies are git
submodules under lib/.
git submodule update --init --recursive # fetch forge-std and solady
forge build
forge testA security review by Nethermind (NM-0663-0950, June 2026) reported no issues.
The report is in audit/.
GPL-3.0-only