---
type: Attested Computation
title: Monthly salary tax (TDS) for a Nepal payroll run, FY 2083/84
description: The sanctioned way to compute monthly TDS, net pay and employer cost from a gross salary under either the PF+CIT or the SSF system.
resource: https://nepalhrm.com/tools/salary-tax-calculator/
tags: [nepal, payroll, tax, tds, fy-2083-84]
runtime: javascript
parameters:
  - name: gross
    type: number
    required: true
  - name: basicPct
    type: number
    required: true
  - name: system
    type: string
    required: true
  - name: citPercent
    type: number
    required: false
executor:
  resource: skills/run-nepal-payroll.md
  receipt: [computation_ref, computation_sha256, parameters, fiscal_year, result]
attester:
  resource: attesters/receipt_equality.mjs
computation_sha256: d4dacf0e37203bd88996fab883d8aa68e85f221935ac4b39545e7c43f6eaae54
constants: salary-tax.constants.json
service:
  resource: https://nepalhrm.com/api/okf/verify
  skill: skills/verify-via-api.md
generated:
  by: process:nepalhrm-site-build
  at: 2026-08-06T00:00:00Z
verified:
  - by: human:rajesh
    at: 2026-08-06T00:00:00Z
status: stable
stale_after: 2027-07-17
sources:
  - id: budget-2083-84
    resource: https://en.ican.org.np/_browsable/file/resouces/Federal_Budget_2083_84_Highlights_V1.pdf
    title: Federal Budget 2083/84 highlights (Institute of Chartered Accountants of Nepal)
    author: org:ican.org.np
    last_modified: 2026-06-15
  - id: income-tax-act-2058
    resource: https://ird.gov.np/content/13405/income-tax-act--2058--as-amended-by/
    title: Income Tax Act 2058, as amended (Inland Revenue Department)
    author: org:ird.gov.np
  - id: ssf-act-2074
    resource: https://ssf.gov.np/list/act_regulation/contribution-based-social-security-act-2074
    title: Contribution Based Social Security Act 2074 (Social Security Fund)
    author: org:ssf.gov.np
  - id: nepalhrm-payroll-module
    resource: nepalhrm:lib/nepal-payroll.ts
    title: The single module every NepalHRM calculator, payslip and tool on this site computes from
    author: process:nepalhrm-site-build
---

# Monthly salary tax (TDS), FY 2083/84

Binds four declared parameters and returns a full payroll breakdown. An agent **may only supply values for the declared parameters**; it must not author or edit the computation. A result produced any other way is not attested, whatever its arithmetic.

## Parameters

| Name | Type | Required | Meaning |
|---|---|---|---|
| gross | number | yes | Monthly gross remuneration, NPR |
| basicPct | number | yes | Basic as a fraction of gross, e.g. 0.6 |
| system | string | yes | "pf-cit" or "ssf" - the two are alternatives |
| citPercent | number | no | CIT as a percentage of basic, 0 to 33. Ignored under "ssf" |

## Computation

Portable ESM, hashed to `d4dacf0e37203bd88996fab883d8aa68e85f221935ac4b39545e7c43f6eaae54`. Save it as `salary-tax.mjs` and run it. It has no imports and no dependencies.

```javascript
// NepalHRM sanctioned computation: monthly salary tax (TDS), FY 2083/84.
// Portable ESM. No imports, no dependencies. Run with: node salary-tax.mjs
//
// Constants below are generated from the single source of truth at
// https://nepalhrm.com/okf/statutory/index.md - do not edit them by hand.

export const FISCAL_YEAR = "2083/84";

// Marginal annual income-tax slabs (NPR). The first band is the 1% social
// security tax; SSF assessees have it waived because SSF already covers it.
export const SLABS = [
  { upTo: 1000000, rate: 0.01 },
  { upTo: 1500000, rate: 0.1 },
  { upTo: 2500000, rate: 0.2 },
  { upTo: 4000000, rate: 0.27 },
  { upTo: Infinity, rate: 0.29 },
];

// Statutory contribution rates. All are assessed on BASIC salary, not gross.
export const RATES = {
  pfEmployee: 0.1,
  pfEmployer: 0.1,
  ssfEmployee: 0.11,
  ssfEmployer: 0.2,
  citMax: 0.33,
};

// Retirement contributions reduce taxable income only up to the LOWEST of the
// actual contribution, this ceiling, or one-third of assessable income.
export const RETIREMENT_DEDUCTION_CAP = 500000;

export function slabsFor(system) {
  return system === "ssf"
    ? SLABS.map((s, i) => (i === 0 ? { ...s, rate: 0 } : s))
    : SLABS;
}

export function taxBreakdown(taxable, system) {
  const rows = [];
  let lower = 0;
  for (const s of slabsFor(system)) {
    if (taxable <= lower) break;
    const amount = Math.min(taxable, s.upTo) - lower;
    rows.push({ from: lower, upTo: s.upTo, rate: s.rate, amount, tax: amount * s.rate });
    lower = s.upTo;
  }
  return rows;
}

export function annualTax(taxable, system) {
  return taxBreakdown(taxable, system).reduce((sum, r) => sum + r.tax, 0);
}

/**
 * @param {{ gross: number, basicPct: number, system: "pf-cit"|"ssf", citPercent: number }} opts
 *   gross      monthly gross remuneration, NPR
 *   basicPct   basic as a fraction of gross, e.g. 0.6
 *   system     "pf-cit" (Provident Fund + Citizen Investment Trust) or "ssf"
 *   citPercent CIT contribution as a percentage of basic; ignored under "ssf"
 */
export function compute(opts) {
  const { gross, basicPct, system, citPercent } = opts;
  const basic = Math.round(gross * basicPct);
  const allowance = gross - basic;

  const pfEmp = system === "pf-cit" ? Math.round(basic * RATES.pfEmployee) : 0;
  const pfEr = system === "pf-cit" ? Math.round(basic * RATES.pfEmployer) : 0;
  const cit = system === "pf-cit" ? Math.round(basic * (citPercent / 100)) : 0;
  const ssfEmp = system === "ssf" ? Math.round(basic * RATES.ssfEmployee) : 0;
  const ssfEr = system === "ssf" ? Math.round(basic * RATES.ssfEmployer) : 0;

  const annualGross = gross * 12;
  const annualContrib = (pfEmp + cit + ssfEmp) * 12;
  const annualDeductible = Math.min(
    annualContrib,
    RETIREMENT_DEDUCTION_CAP,
    annualGross / 3,
  );
  const annualTaxable = Math.max(0, annualGross - annualDeductible);
  const annualTds = annualTax(annualTaxable, system);
  const tds = Math.round(annualTds / 12);

  const net = gross - (pfEmp + cit + ssfEmp + tds);
  const employerCost = gross + pfEr + ssfEr;

  return {
    basic,
    allowance,
    pfEmp,
    pfEr,
    cit,
    ssfEmp,
    ssfEr,
    tds,
    annualTds: Math.round(annualTds),
    annualDeductible: Math.round(annualDeductible),
    deductionCapped: annualDeductible < annualContrib,
    annualTaxable: Math.round(annualTaxable),
    net,
    employerCost,
  };
}
```

## Test vectors

Produced by the NepalHRM site's own payroll module at build time. The computation above reproduces every row; [the attester](../attesters/receipt_equality.mjs) checks that, and so can you.

| Gross | System | Basic % | CIT % | Monthly TDS | Net pay | Employer cost |
|---|---|---|---|---|---|---|
| NPR 30,000 | pf-cit | 60% | 0% | 282 | 27918 | 31800 |
| NPR 30,000 | ssf | 60% | 0% | 0 | 28020 | 33600 |
| NPR 75,000 | pf-cit | 60% | 10% | 660 | 65340 | 79500 |
| NPR 75,000 | ssf | 60% | 0% | 0 | 70050 | 84000 |
| NPR 150,000 | pf-cit | 50% | 20% | 5500 | 122000 | 157500 |
| NPR 400,000 | pf-cit | 60% | 33% | 62667 | 234133 | 424000 |
| NPR 400,000 | ssf | 60% | 0% | 66261 | 307339 | 448000 |
| NPR 1,200,000 | pf-cit | 60% | 33% | 294667 | 595733 | 1272000 |

```json
[
  {
    "input": {
      "gross": 30000,
      "basicPct": 0.6,
      "system": "pf-cit",
      "citPercent": 0
    },
    "output": {
      "basic": 18000,
      "allowance": 12000,
      "pfEmp": 1800,
      "pfEr": 1800,
      "cit": 0,
      "ssfEmp": 0,
      "ssfEr": 0,
      "tds": 282,
      "annualTds": 3384,
      "annualDeductible": 21600,
      "deductionCapped": false,
      "annualTaxable": 338400,
      "net": 27918,
      "employerCost": 31800
    }
  },
  {
    "input": {
      "gross": 30000,
      "basicPct": 0.6,
      "system": "ssf",
      "citPercent": 0
    },
    "output": {
      "basic": 18000,
      "allowance": 12000,
      "pfEmp": 0,
      "pfEr": 0,
      "cit": 0,
      "ssfEmp": 1980,
      "ssfEr": 3600,
      "tds": 0,
      "annualTds": 0,
      "annualDeductible": 23760,
      "deductionCapped": false,
      "annualTaxable": 336240,
      "net": 28020,
      "employerCost": 33600
    }
  },
  {
    "input": {
      "gross": 75000,
      "basicPct": 0.6,
      "system": "pf-cit",
      "citPercent": 10
    },
    "output": {
      "basic": 45000,
      "allowance": 30000,
      "pfEmp": 4500,
      "pfEr": 4500,
      "cit": 4500,
      "ssfEmp": 0,
      "ssfEr": 0,
      "tds": 660,
      "annualTds": 7920,
      "annualDeductible": 108000,
      "deductionCapped": false,
      "annualTaxable": 792000,
      "net": 65340,
      "employerCost": 79500
    }
  },
  {
    "input": {
      "gross": 75000,
      "basicPct": 0.6,
      "system": "ssf",
      "citPercent": 0
    },
    "output": {
      "basic": 45000,
      "allowance": 30000,
      "pfEmp": 0,
      "pfEr": 0,
      "cit": 0,
      "ssfEmp": 4950,
      "ssfEr": 9000,
      "tds": 0,
      "annualTds": 0,
      "annualDeductible": 59400,
      "deductionCapped": false,
      "annualTaxable": 840600,
      "net": 70050,
      "employerCost": 84000
    }
  },
  {
    "input": {
      "gross": 150000,
      "basicPct": 0.5,
      "system": "pf-cit",
      "citPercent": 20
    },
    "output": {
      "basic": 75000,
      "allowance": 75000,
      "pfEmp": 7500,
      "pfEr": 7500,
      "cit": 15000,
      "ssfEmp": 0,
      "ssfEr": 0,
      "tds": 5500,
      "annualTds": 66000,
      "annualDeductible": 270000,
      "deductionCapped": false,
      "annualTaxable": 1530000,
      "net": 122000,
      "employerCost": 157500
    }
  },
  {
    "input": {
      "gross": 400000,
      "basicPct": 0.6,
      "system": "pf-cit",
      "citPercent": 33
    },
    "output": {
      "basic": 240000,
      "allowance": 160000,
      "pfEmp": 24000,
      "pfEr": 24000,
      "cit": 79200,
      "ssfEmp": 0,
      "ssfEr": 0,
      "tds": 62667,
      "annualTds": 752000,
      "annualDeductible": 500000,
      "deductionCapped": true,
      "annualTaxable": 4300000,
      "net": 234133,
      "employerCost": 424000
    }
  },
  {
    "input": {
      "gross": 400000,
      "basicPct": 0.6,
      "system": "ssf",
      "citPercent": 0
    },
    "output": {
      "basic": 240000,
      "allowance": 160000,
      "pfEmp": 0,
      "pfEr": 0,
      "cit": 0,
      "ssfEmp": 26400,
      "ssfEr": 48000,
      "tds": 66261,
      "annualTds": 795128,
      "annualDeductible": 316800,
      "deductionCapped": false,
      "annualTaxable": 4483200,
      "net": 307339,
      "employerCost": 448000
    }
  },
  {
    "input": {
      "gross": 1200000,
      "basicPct": 0.6,
      "system": "pf-cit",
      "citPercent": 33
    },
    "output": {
      "basic": 720000,
      "allowance": 480000,
      "pfEmp": 72000,
      "pfEr": 72000,
      "cit": 237600,
      "ssfEmp": 0,
      "ssfEr": 0,
      "tds": 294667,
      "annualTds": 3536000,
      "annualDeductible": 500000,
      "deductionCapped": true,
      "annualTaxable": 13900000,
      "net": 595733,
      "employerCost": 1272000
    }
  }
]
```

## Attestation

A receipt is a JSON object with the fields listed in `executor.receipt`:

```json
{
  "computation_ref": "/okf/computations/salary-tax.md",
  "computation_sha256": "d4dacf0e37203bd88996fab883d8aa68e85f221935ac4b39545e7c43f6eaae54",
  "parameters": { "gross": 75000, "basicPct": 0.6, "system": "pf-cit", "citPercent": 10 },
  "fiscal_year": "2083/84",
  "result": {"basic":45000,"allowance":30000,"pfEmp":4500,"pfEr":4500,"cit":4500,"ssfEmp":0,"ssfEr":0,"tds":660,"annualTds":7920,"annualDeductible":108000,"deductionCapped":false,"annualTaxable":792000,"net":65340,"employerCost":79500}
}
```

Verify it with:

```sh
node receipt_equality.mjs --concept salary-tax.md --receipt receipt.json
```

The attester is deterministic and involves no language model. It checks that the hash pins this exact computation, that only declared parameters were bound, that every required one is present, and that re-running the computation on those parameters reproduces the receipt's result exactly. Any mismatch exits non-zero.

If you cannot execute JavaScript, [`https://nepalhrm.com/api/okf/verify`](https://nepalhrm.com/api/okf/verify) will compute a receipt or check one for you over HTTP. [How to call it](../skills/verify-via-api.md), and why running the computation yourself is still the better option where you can.

## Constants as data

The same slabs, rates and ceiling in machine-readable form, for a consumer that needs the numbers without running the code: [`salary-tax.constants.json`](salary-tax.constants.json). It is generated from the same module as the computation above, so the two cannot disagree.

## Scope

This computes tax on **employment income under a monthly payroll**. It does not model other income heads, foreign income, non-resident status, medical tax credit, or the remote-area allowance. Read [the statutory concepts](../statutory/index.md) for the figures it applies, and treat the output as an estimator rather than a filing.
