Skip to content Search Apps Documentation Source Content File Folder Download Copy Actions State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

Community realm. Read the code first. Community realm, deployed by its author. Read the code before you interact or send coins.

payslips package

Overview

Package payslips publishes graduated withholding statements over the wage facts of a live r/payroll.

An employer sets a withholding schedule — a p/tiers bracket table — and publishes a payslip naming the employees it covers. For each one this realm reads payroll's own views, reconstructs the settled gross, prices it through the schedule, and records the result. Nothing is supplied by the caller except the schedule and the selection: every amount comes from payroll.

WHAT THIS REALM IS, AND WHAT IT CANNOT BE

It is a REPORTER. It holds no coins, has no withdrawal path, and moves nothing. It does not deduct the withholding it computes — payroll settles wages and this realm states what a graduated schedule would have withheld from them. The separation is deliberate and it is also forced: r/payroll is live and immutable, so a graduated rate cannot be charged inside it, and a realm that charged one here would be a second custody surface over coins payroll already holds.

The consequence is the realm's only real safety argument and it is a strong one: THIS REALM CANNOT WRITE A WRONG PAYMENT, BECAUSE IT CANNOT WRITE A PAYMENT. The failure mode it does have is a wrong or incomplete REPORT, and every mitigation below is aimed there.

SETTLED IS NOT EARNED

The gross on a payslip is the gross payroll has SETTLED for the position that is open right now:

Example
1gross = PaidPeriodsOf(employer, employee) * PerPeriodOf(employer, employee)

That identity is exact rather than approximate, and the reason is structural: payroll exports no setter for perPeriod, so a position's rate is fixed for its whole life by the Hire that created it, and paidPeriods only ever increases. The product is therefore the position's lifetime settled gross and not an estimate of it.

It is still not the employee's lifetime earnings under this employer, and the gap is not small. payroll's Release removes a settled position and frees its storage, and Hire refuses only while a position is OPEN — so Terminate → Release → Hire is a legal sequence that resets paidPeriods to zero and makes every period before it unreadable from any view. The Released event carries paidPeriods, but an event is not realm-readable. So:

Example
1A PAYSLIP IS SCOPED TO THE POSITION OPEN AT ITS OWN HEIGHT, AND MUST NEVER
2BE READ AS LIFETIME GROSS.

The failure mode is silent under-reporting, which is the one error a reader cannot detect from the number itself. The mitigations are that every payslip records its height, its own scope, and a coverage line; that Coverage and OmittedRoster say how much of the employer's roster the payslip left out; and that an employee named with no open position PANICS rather than being dropped — a silently-dropped line is exactly the under-report this realm cannot detect after the fact.

PERIODS THAT ARE DUE BUT NOT ACCRUED ARE EXCLUDED, AND DISCLOSED

payroll accrues on demand: anyone may call Accrue, and until someone does, completed periods are due and unsettled. A payslip published before an Accrue therefore reports a smaller gross than the employee is owed. Rather than guess, each line records dueGross — DuePeriods times perPeriod at the payslip's height — and UnsettledGrossOf totals it. A payslip whose UnsettledGrossOf is non-zero is complete about what was settled and explicit about what was not.

THE PLATFORM FEE IS AN INTERVAL, AND THAT IS A MEASUREMENT

payroll takes an accrual fee of AccrueFeeBps from each settlement, and the obvious reconstruction — a flat rate on the cumulative gross — is wrong. Its Accrue settles every due period in ONE deposit and floors the fee on that aggregate, so the fee actually taken depends on how the accruals were BATCHED, and payroll exports no view of the batching. What it does export is paidPeriods and perPeriod, and those bound the fee exactly:

Example
1feeLo = paidPeriods * floor(perPeriod * bps / RateScale)   one period per call
2feeHi = floor(gross * bps / RateScale)                     one call for all

Both endpoints are achievable, so the interval is tight and not a hedge: floor(x) + floor(y) <= floor(x+y) gives the upper bound, and floor(n*x) >= n*floor(x) gives the lower. They coincide whenever perPeriod * bps divides RateScale evenly, which is the common case.

So PlatformFeeRange and NetRange return pairs. A single platform-fee number here would have been plausible, derivable, and wrong for any employee whose accruals were batched — and nothing on the chain would have contradicted it.

THE SCHEDULE PRICES GROSS, AND THE TWO DEDUCTIONS ARE NEVER COMBINED

The withholding schedule is applied to gross. payroll's platform fee is a separate deduction that payroll has already taken. They are reported side by side and never folded into one effective rate, because they have different payees, different arithmetic (graduated versus flat) and different certainty (exact versus an interval).

A schedule in p/tiers carries no identity and no effective date, and a falling rate array is legal there — it is a volume discount — so a transposed table is a silent authoring error that tiers.New cannot detect. Two consequences this realm acts on: every payslip SNAPSHOTS the schedule that priced it, so a later SetSchedule cannot retroactively re-price a published payslip; and OverWithheld names the one arithmetic outcome that is almost certainly an authoring error — a schedule withholding more than the employee actually received — rather than hiding it or refusing to publish it.

AUTHORITY

An employer publishes about their OWN roster: the employer of every payslip is cur.Previous().Address(), never an argument. This realm therefore cannot publish a payslip about a roster the caller does not hold, and a payslip's key is the employer that published it.

Function

PlatformFeeRange

func PlatformFeeRange(employer address, seq int64) (lo, hi int64)
Ask AI Claude ChatGPT

PlatformFeeRange bounds the accrual fee r/payroll already took on this gross. It is an interval because the fee depends on accrual batching, which payroll does not expose — see the package doc. lo == hi is common and means the batching could not have mattered.

Params

Command

gnokey query vm/qeval -remote "https://rpc.onyx.testnets.gno.land" -data "gno.land/r/g1ut6uspuh73e02yauxpmyt8g3wwddaq8utagvm3/payslips.PlatformFeeRange(,)"

Result