$RENT on Pons. Contract address: launch soon Follow @rentdayxyz for the address
Rentday
CAsoon

Roll format

The exact bytes that get hashed, so anyone can rebuild a Roll and get the same hash.

Encoding

  • UTF-8 text with no byte order mark.
  • Every line ends with a single line feed (\n). There are no carriage returns.
  • The file ends with a line feed after the last row.
  • A field is wrapped in double quotes only if it contains a comma, a double quote or a line break. A double quote inside a quoted field is written twice.
  • Sections are separated by exactly one blank line.
  • A section with no rows still prints its name line and its column line.

The reference implementation is toCsv() in site/js/close.js. parseCsv() in the same file reads a Roll back. For all six sample Rolls, parsing the file and writing it again with toCsv() reproduces the same bytes.

Four lines, then a blank line:

rentday.roll/1
roll,<id>
period,<YYYY-MM>
published,<YYYY-MM-DD>

The first line names the format and its version. <id> is the Roll number padded to three digits: 001, 002 and so on. period is the month closed and published is the date the Roll came out. Sample Rolls use the ids S1 to S6 and put placeholder text in the period and published fields.

Sections

Each section starts with a line holding # and the section name, followed by a column line. The sections always appear in this order:

SectionColumn lineRows
#apartmentsbuilding,unit,beds,lease_rent,statusOne per apartment, sorted by building, then by unit. Status is paid, late or vacant.
#recoveredbuilding,unit,for_period,amountOne per late payment recovered this month, sorted by the key building-unit (for example A-202).
#costsitem,amountSeven rows in fixed order: repairs, capital_works, property_tax, insurance, property_manager, vault_management, vault_performance.
#token_feeseth_claimed,usdg_received,claim_tx,swap_txExactly one row. With no token fee it reads 0,0.000000,,.
#appraisalsbuilding,change,reasonOne per appraisal change, in the order the operator entered them.
#balanceitem,valueFifteen rows in fixed order, listed below.

Sorting compares the fields as text, character by character.

The balance rows, in order:

  1. rent_collected
  2. rent_recovered
  3. costs
  4. net_rent
  5. shortfall_open
  6. settled
  7. shortfall_close
  8. token_fees
  9. flows
  10. usdg_prev
  11. usdg_open
  12. usdg_close
  13. shares_open
  14. price_open
  15. price_close

What each value means is on Reading a Roll.

Numbers

KindDecimalsExample
USDG amounts61040.000000
vRENT amounts (shares_open)184679023.703779488775338943
Prices (price_open, price_close)121.017995143292
  • Every decimal place is printed, trailing zeros included.
  • Values are truncated toward zero at the last decimal, never rounded.
  • There are no thousands separators. Negative values, which can occur in net_rent, flows and an appraisal's change, start with a minus sign.
  • beds is a whole number. eth_claimed is written as the operator entered it (for example 0.9600) and is not padded.

Sample excerpt

The lines below are sample data, produced by running the close engine on the sample portfolio. They come from sample month 4, the month a boiler was replaced. This is not a published Roll. The file opens like this; the apartments section continues for 34 rows in all.

rentday.roll/1
roll,S4
period,sample-4
published,rent day 4

#apartments
building,unit,beds,lease_rent,status
A,101,1,1040.000000,paid
A,102,1,1060.000000,paid
A,201,2,1110.000000,paid

Two of those rows show the other statuses: D,401,3,1440.000000,vacant and E,103,2,1330.000000,late. After the last apartment, the file runs to its end like this. The recovered and appraisals sections are empty this month and still print their headers.

#recovered
building,unit,for_period,amount

#costs
item,amount
repairs,2210.000000
capital_works,41500.000000
property_tax,3507.083333
insurance,1181.333333
property_manager,2774.800000
vault_management,2975.163784
vault_performance,0.000000

#token_fees
eth_claimed,usdg_received,claim_tx,swap_tx
0.9600,2961.350000,,

#appraisals
building,change,reason

#balance
item,value
rent_collected,39640.000000
rent_recovered,0.000000
costs,54148.380450
net_rent,-14508.380450
shortfall_open,0.000000
settled,0.000000
shortfall_close,14508.380450
token_fees,2961.350000
flows,0.000000
usdg_prev,4760262.055797
usdg_open,4760262.055797
usdg_close,4763223.405797
shares_open,4679023.703779488775338943
price_open,1.017362244168
price_close,1.017995143292

Sample Rolls leave claim_tx and swap_tx empty. A published Roll carries the two transaction hashes there.

To print the whole sample file, run this from the project root:

node -e "import('./site/js/close.js').then(async C=>{const S=await import('./site/js/sample-data.js');const {rolls}=C.closeAll(S.SAMPLE_PORTFOLIO,S.SAMPLE_OPENING_USDG,S.SAMPLE_MONTHS,{sample:true});console.log(C.toCsv(rolls[3]))})"

console.log adds a line feed after the file's own trailing newline. To hash the output, write the string to a file with fs.writeFileSync instead of redirecting the printout.