Contract Reference
All addresses are Ethereum mainnet (chainId 1) and verifiable on a block explorer.
Token
| Field | Value |
|---|---|
| Name | Wren Staked tGBP |
| Symbol | wstGBP |
| Decimals | 18 |
| Address | 0x57C3571f10767E49C9d7b60feb6c67804783B7aE |
Underlying (gem) | tGBP (0x27f6c8289550fCE67f6B50BeD1F519966aFE5287) |
Module addresses
The token holds six module references. Proxy modules are bound at their proxy address; the implementation is where the logic (and event ABI) lives.
| Ref | Role | Proxy | Implementation |
|---|---|---|---|
gem | Underlying (tGBP) | 0x27f6c8289550fCE67f6B50BeD1F519966aFE5287 | n/a |
pip | Price oracle | 0x6A79dCe61A12aa4b75449e0B03746260765D07dF | 0x44BFEB1110bA6091034DBaAb450eF1e7469fF072 |
act | Market gate | 0xB59cB4d3075a8ce5013C78e8Bd7aDA3Fd1300f7f | 0x635dbb7841c27c74b6bDbf1BEd548aAe2C6C9D77 |
adm | Treasury | 0xa8F5bE8457D6ed5c659647fa8d107C3F2086626A | 0x192575eeb42644a8014eB545c69f5125e2437A56 |
cop | Ban-list screen (inherited from tGBP) | 0x794cF5948444b14105587455EbE96Caace036d52 | 0x3bb8eBb11816e1C20c3Db57e2E7e5b421b159255 |
flo | Output conduit | 0x57C3571f10767E49C9d7b60feb6c67804783B7aE (= token) | n/a |
| n/a | Multicall3 | 0xcA11bde05977b3631167028862bE2a173976CA11 | n/a |
Compiled with Solidity 0.8.34 (pragma floor ^0.8.28). Source is verified on
Etherscan at the addresses above; the deployed contracts are covered by the
independent Prototech Labs audit report.
View functions for integrators
| Function | Returns | Notes |
|---|---|---|
navprice() | uint256 | Raw oracle NAV price (WAD). |
mintcost() | uint256 | NAV adjusted up by bpsin (0 for wstGBP). Use directly to quote mints. |
burncost() | uint256 | NAV adjusted down by bpsout (25 = 0.25%). Use directly to quote redeems. |
mintable() | bool | Whether minting is currently open. |
burnable() | bool | Whether redeeming is currently open. |
capacity() | uint256 | Max total supply (effectively unbounded for wstGBP). |
cooldown() | uint256 | Redemption delay in seconds (currently 0, so redeems are atomic). |
totalSupply() | uint256 | wstGBP in circulation. |
balanceOf(address) | uint256 | wstGBP balance. |
gem() | address | The underlying token (tGBP). |
redemptionCount() | uint256 | Number of redemptions ever opened. |
redemptions(uint256) | (uint256 amount, address redeemer, uint96 date) | A queued redemption by id. |
canPass(address) | bool | Screening pre-check: whether the address passes the cop ban-list screen. Check before submitting instead of catching NotAuthorized. |
terms() | string | On-chain pointer to the current terms document. |
nonces(address) | uint256 | Current EIP-2612 permit nonce for the owner. |
DOMAIN_SEPARATOR() | bytes32 | EIP-712 domain separator used by permit. |
Gate (act) schedule reads
mintable() / burnable() on the token are derived from a time window configured on the
market gate. The gate exposes the window itself. Call these on the act proxy
0xB59cB4d3075a8ce5013C78e8Bd7aDA3Fd1300f7f (the token does not forward them):
| Function | Returns | Notes |
|---|---|---|
openMint() / haltMint() | uint256 | Unix timestamps bounding the mint window. |
openBurn() / haltBurn() | uint256 | Unix timestamps bounding the redeem window. |
nextOpenMint() / nextHaltMint() | uint256 | The upcoming mint-window transition, if any (see sentinels below). |
nextOpenBurn() / nextHaltBurn() | uint256 | The upcoming redeem-window transition, if any (see sentinels below). |
bpsin() / bpsout() | uint256 | Mint / redeem fee in basis points (currently 0 / 25). |
The next* reads have two sentinel values, not one: 0 means the boundary is
already in the past (no transition ahead), and type(uint256).max means the transition
is never scheduled. Under the current mainnet config the market is open indefinitely, so
nextOpen*() returns 0 and nextHalt*() returns type(uint256).max. Treat both
as “no date to show”, never render them as timestamps.
Useful for UIs that show when the market opens next instead of a bare closed state; see the Gate snippet.
Write functions
| Function | Signature | Notes |
|---|---|---|
mint | mint(uint256 amt) returns (uint256 _out) | Pull amt tGBP, mint wstGBP. Requires prior tGBP approve. |
redeem | redeem(uint256 amt) returns (uint256 _id) | Burn amt wstGBP; settles tGBP atomically when cooldown 0. |
exit | exit(uint256 id) returns (uint256 _out) | Settle a queued redemption once claimable (cooldown > 0 only). |
smelt | smelt(uint256 amt) | Burn your own wstGBP without redeeming (no tGBP out). Emits Smelted. |
settle | settle() returns (uint256 _out) | Sweep surplus tGBP (balance above pending claims) to the output conduit flo. Emits Settled. |
Standard ERC-20 (transfer, approve, transferFrom, allowance) and EIP-2612
permit are also available, plus a one-argument approve(address) overload that sets
max allowance. All user-facing calls, including smelt(uint256) and settle() above,
are screened against tGBP’s ban list via the cop module (see
Architecture); there is no allowlist and no
administrative approval step.
issue(uint256) and the two-argument smelt(address, uint256) are issuer-only
supply operations, and proxy/oracle administration is owner-gated. These are on-chain
governance functions, not part of normal integration. (The one-argument
smelt(uint256) self-burn above is callable by any holder.) See
Privileged surface.
EIP-2612 permit
permit(owner, spender, value, deadline, v, r, s) accepts a standard EIP-712 Permit
signature (Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline))
over this domain:
const domain = {
name: 'Wren Staked tGBP',
version: '1',
chainId: 1,
verifyingContract: '0x57C3571f10767E49C9d7b60feb6c67804783B7aE',
} as constRead the owner’s current nonce from nonces(owner). permit is
ban-list screened like everything else: the submitting relayer (msg.sender), the
owner, and the spender must all pass the cop screen.
Events
event ContractCreated(address indexed creator, uint256 indexed price, uint256 indexed amount);
event ContractRedemption(uint256 indexed id, uint256 indexed date, address indexed redeemer, uint256 amount);
event ClaimProcessed(uint256 indexed id, address indexed claimer, uint256 indexed amount);
event Settled(address indexed conduit, uint256 indexed amount); // settle() swept surplus tGBP to flo
event Issued(address indexed issuer, uint256 indexed amount); // issuer mint (no tGBP in)
event Smelted(address indexed smelter, uint256 indexed amount); // burn without redemption
// plus standard ERC-20 Transfer / ApprovalErrors
Custom errors thrown by the token. Decode them to show users why a call reverted (the subgraph indexes the corresponding lifecycle events):
| Error | Thrown when |
|---|---|
MarketClosed() | mint while mintable() is false, or redeem while burnable() is false. |
InvalidPrice() | The oracle reads 0 (navprice() == 0); quoting is paused. |
DustThreshold(uint256 min) | mint below mintcost(), or redeem below 1 wstGBP (1e18). |
ExceedsCap() | The mint would push totalSupply above capacity(). |
ClaimableAfter(uint256 time) | exit(id) before the redemption’s claimable date. |
NoPendingClaim() | exit(id) on a settled or nonexistent redemption. |
NotAuthorized(address usr) | An address involved fails the cop ban-list screen, or an issuer-only call by a non-issuer. |
TransferToContract() | transfer / transferFrom with the token contract as destination. |
TransferToZeroAddress() | transfer / transferFrom to the zero address. |
TransferFailed() | The underlying tGBP transfer returned false. |
PermitDeadlineExpired(uint256 deadline, uint256 actual) | permit submitted after its deadline. |
InvalidSigner(address recovered, address expected) | permit signature does not recover to owner. |
InvalidChain(uint256 expected, uint256 actual) | permit domain guard after a chain split; not expected in practice. |
ABI
A curated ABI covering mint/redeem/exit, the integrator views, and the three lifecycle events. Sufficient for viem/wagmi integration.
export const wstgbpAbi = [
{ type: 'function', name: 'mint', stateMutability: 'nonpayable',
inputs: [{ name: 'amt', type: 'uint256' }], outputs: [{ name: '_out', type: 'uint256' }] },
{ type: 'function', name: 'redeem', stateMutability: 'nonpayable',
inputs: [{ name: 'amt', type: 'uint256' }], outputs: [{ name: '_id', type: 'uint256' }] },
{ type: 'function', name: 'exit', stateMutability: 'nonpayable',
inputs: [{ name: 'id', type: 'uint256' }], outputs: [{ name: '_out', type: 'uint256' }] },
{ type: 'function', name: 'navprice', stateMutability: 'view', inputs: [], outputs: [{ type: 'uint256' }] },
{ type: 'function', name: 'mintcost', stateMutability: 'view', inputs: [], outputs: [{ type: 'uint256' }] },
{ type: 'function', name: 'burncost', stateMutability: 'view', inputs: [], outputs: [{ type: 'uint256' }] },
{ type: 'function', name: 'mintable', stateMutability: 'view', inputs: [], outputs: [{ type: 'bool' }] },
{ type: 'function', name: 'burnable', stateMutability: 'view', inputs: [], outputs: [{ type: 'bool' }] },
{ type: 'function', name: 'capacity', stateMutability: 'view', inputs: [], outputs: [{ type: 'uint256' }] },
{ type: 'function', name: 'cooldown', stateMutability: 'view', inputs: [], outputs: [{ type: 'uint256' }] },
{ type: 'function', name: 'totalSupply', stateMutability: 'view', inputs: [], outputs: [{ type: 'uint256' }] },
{ type: 'function', name: 'balanceOf', stateMutability: 'view',
inputs: [{ name: 'account', type: 'address' }], outputs: [{ type: 'uint256' }] },
{ type: 'function', name: 'gem', stateMutability: 'view', inputs: [], outputs: [{ type: 'address' }] },
{ type: 'function', name: 'redemptionCount', stateMutability: 'view', inputs: [], outputs: [{ type: 'uint256' }] },
{ type: 'function', name: 'canPass', stateMutability: 'view',
inputs: [{ name: 'usr', type: 'address' }], outputs: [{ type: 'bool' }] },
{ type: 'function', name: 'terms', stateMutability: 'view', inputs: [], outputs: [{ type: 'string' }] },
{ type: 'function', name: 'nonces', stateMutability: 'view',
inputs: [{ name: 'owner', type: 'address' }], outputs: [{ type: 'uint256' }] },
{ type: 'function', name: 'DOMAIN_SEPARATOR', stateMutability: 'view', inputs: [], outputs: [{ type: 'bytes32' }] },
{ type: 'function', name: 'redemptions', stateMutability: 'view',
inputs: [{ type: 'uint256' }],
outputs: [
{ name: 'amount', type: 'uint256' },
{ name: 'redeemer', type: 'address' },
{ name: 'date', type: 'uint96' },
] },
{ type: 'event', name: 'ContractCreated', anonymous: false,
inputs: [
{ name: 'creator', type: 'address', indexed: true },
{ name: 'price', type: 'uint256', indexed: true },
{ name: 'amount', type: 'uint256', indexed: true },
] },
{ type: 'event', name: 'ContractRedemption', anonymous: false,
inputs: [
{ name: 'id', type: 'uint256', indexed: true },
{ name: 'date', type: 'uint256', indexed: true },
{ name: 'redeemer', type: 'address', indexed: true },
{ name: 'amount', type: 'uint256', indexed: false },
] },
{ type: 'event', name: 'ClaimProcessed', anonymous: false,
inputs: [
{ name: 'id', type: 'uint256', indexed: true },
{ name: 'claimer', type: 'address', indexed: true },
{ name: 'amount', type: 'uint256', indexed: true },
] },
] as const