Skip to content

Contract methods and events

ARIADNE’s rules are enforced by one smart contract, deployed once per network as an Algorand application. Every action (publishing, reviewing, voting, commenting, flagging) is a call to one of its methods, signed by the person who acts. This page lists them all, with the events they emit and the data they store, for developers and auditors. Terms such as application, box, ASA and minimum balance are explained in the Glossary.

The contract is written in Algorand Python (compiled with puyapy 5.10.1), exposes an ARC-4 ABI, is described by an ARC-56 application specification, and emits ARC-28 events. Everything here was checked against the source and the compiled specification, which win over any other description:

  • projects/contracts/smart_contracts/ariadne/contract.py (methods), events.py (events), types.py (box values), keys.py (box keys), constants.py (constants);
  • projects/contracts/smart_contracts/artifacts/ariadne/Ariadne.arc56.json (the ARC-56 specification, with the deployed bytecode).

The TestNet application is 772983107 (see Networks and addresses). The normative text is the protocol specification, sections 5 to 13, amended by the decision log.

Topic Rule
Article number article_id is a sequence assigned by the contract, starting at 1. Each article also has an Algorand asset (ASA) whose id is stored in the article box and in Published.
Addresses ARC-4 address: the raw 32-byte public key.
Boxes Named storage slots of the application, one per record (article, vote, review…). Each box raises the application’s minimum balance, which the caller covers with the pay argument.
CIDs byte[36], the raw CIDv1 bytes: 0x01, the codec, 0x12 0x20 (sha2-256, 32 bytes), then the 32-byte digest. Articles must use codec 0x70 (dag-pb, a folder); reviews and comments codec 0x55 (raw, one file). Any other prefix, length or an all-zero digest is rejected.
pay argument A payment transaction placed in the group just before the call, from the caller to the application address, without close-out or rekey. Its amount must cover the increase of the application’s minimum balance caused by the call (the storage deposit). Overpayment is accepted and kept; there are no refunds.
Fees The caller pays every network fee of the call, including those of the inner transactions, through fee pooling. Fees are read from the network when sending, never hard-coded.
Statuses 1 preprint, 2 under_review, 3 final (shown in the app as “closed version”), 4 disputed, 5 retracted. “Open” below means statuses 1 to 3.
Accepted author The submitter, or a declared co-author who confirmed with accept_coauthorship. Accepted authors may not vote on, review or flag their own article.
Failure Any violated precondition rejects the whole transaction group. The assertion messages are in contract.py.
Events Every state-changing call emits exactly one canonical event, followed by zero to two ReputationChanged.

0 is invalid for every enumeration.

Enumeration Values
type 1 article, 2 notes, 3 amendment, 4 dataset, 5 replication
status 1 preprint, 2 under_review, 3 final, 4 disputed, 5 retracted
recommendation 1 accept, 2 minor_revision, 3 major_revision, 4 reject
flag reason 1 plagiarism, 2 spam, 3 fabricated_data, 4 other
vote target (target_kind) 1 article, 2 review, 3 comment
dispute outcome 1 cleared, 2 retracted
reputation reason 1 article_upvote, 2 review_useful, 3 comment_upvote, 4 comment_resolved
identity scheme 1 ORCID iD

The storage deposit is in microAlgo (1 ALGO = 1 000 000 microAlgo) and goes to the application account through the pay argument. It is a permanent deposit, not a fee: nothing is ever deleted.

Method Who may call Allowed statuses Deposit (pay) Creates
add_field governance not applicable 2 500 + 400 × (3 + name bytes) field box
set_governance governance not applicable none nothing
resolve_dispute governance disputed none nothing
publish anyone not applicable (the article starts as preprint) 212 200 + 29 300 per declared co-author ASA, article box, co-author boxes
extend anyone not applicable none nothing
claim_article the submitter 1 to 4 (not retracted) none (the opt-in costs the author 100 000 on their own account) nothing
new_version the submitter 1, 2 none nothing
set_status the submitter see the transition table none nothing
accept_coauthorship a declared co-author open (1 to 3) none nothing
submit_review anyone but an accepted author 1 to 4 (not retracted) 65 800, or 91 100 with the reviewer’s first reputation box in the field review box, reviewer index box, reputation box if missing
vote_review anyone but the reviewer open 32 100 vote box
vote_article anyone but an accepted author open 28 900 vote box
claim_reputation an accepted author open 0, 25 300 or 50 600 the claimer’s missing reputation boxes
comment anyone every status 56 500, or 81 800 with the commenter’s first reputation box in the field comment box, reputation box if missing
vote_comment anyone but the comment’s author open 32 100 vote box
resolve_comment the submitter open none nothing
flag anyone but an accepted author, with reputation of at least 10 in the primary field 1 to 4 (not retracted) 26 500 flag box
declare_identity anyone not applicable none nothing
declare_doi an accepted author any; a non-empty DOI not when retracted none nothing
follow anyone not applicable none nothing

The create(governance) method runs once, when the application is deployed.

Governance is one address stored in global state. On TestNet it is a native Falcon-1024 (post-quantum) account, and it pays its own fees and deposits like anyone else. It can register fields, resolve disputes and hand governance to another address; it cannot change articles, reputation or the program.

create(governance: address) -> void

Creation only. governance must not be the zero address. Sets article_seq_next to 1 and emits GovernanceChanged with the zero address as previous_governance. The deployer keeps no power.

add_field(pay: pay, field_id: uint16, name: string) -> void
  • Sender: the governance address.
  • field_id is not 0 and not registered yet; name is 1 to 96 bytes. Fields are never renamed or removed.
  • Creates the field box t + field_id, whose value is the name in UTF-8.
  • Emits FieldAdded.
set_governance(new_governance: address) -> void
  • Sender: the current governance address.
  • new_governance is neither the zero address nor the current one.
  • Emits GovernanceChanged. This is how governance will move to a post-quantum multisig account once Algorand offers one.
resolve_dispute(article_id: uint64, outcome: uint8) -> void
  • Sender: the governance address. The article must be disputed.
  • outcome 1 (cleared) restores the status the article had before the dispute; 2 (retracted) retracts it and revokes its ASA (one inner asset-configuration transaction).
  • Increments dispute_round, resets the round’s flag weight to 0 and clears status_before_dispute. Flags of earlier rounds stay on record but no longer count. The last round, 65 535, takes no flags and cannot be resolved, so no article can be stuck in disputed.
  • Emits DisputeResolved (with the round that was resolved). No StatusChanged is emitted.
publish(pay: pay, cid: byte[36], primary_field: uint16, secondary_field: uint16,
article_type: uint8, parent_article: uint64, coauthors: address[]) -> uint64
  • Sender: anyone. The sender becomes the submitter, for ever.
  • cid: a dag-pb CID (codec 0x70).
  • primary_field is a registered field; secondary_field is 0 or a registered field different from the primary.
  • article_type is 1 to 5. parent_article is the number of an existing article when the type is amendment (3), and 0 for every other type.
  • coauthors: 0 to 25 addresses in strictly ascending order of their raw 32 bytes (which proves they are distinct), never the sender. The list can never be changed afterwards.
  • Creates the article’s ASA (one inner transaction), the article box, the submitter’s co-author box (accepted) and one co-author box per declared address (not accepted yet). Creates no reputation box.
  • Returns the new article_id and emits Published. The article starts as preprint, version 1.
  • Deposit: 212 200 microAlgo (ASA 100 000 + article box 82 900 + the submitter’s co-author box 29 300), plus 29 300 per declared co-author (944 700 with 25).
extend() -> void

Changes nothing and emits nothing. A call to extend placed in the same group lends its opcode budget and its box references to the other calls. A publication touches one box per declared co-author, so clients add ceil(boxes / 8) - 1 calls to extend, where boxes = 3 + 1 with a secondary field + 1 for an amendment + the number of co-authors (D-073). Up to 4 co-authors (5 without a secondary field) need none.

claim_article(article_id: uint64) -> void
  • Sender: the submitter, who has opted in to the article’s ASA (paying their own opt-in deposit). The article is not claimed yet and not retracted.
  • Four inner transactions move the token to the author and freeze it there for ever: unfreeze, transfer, refreeze, and an asset configuration that sets the freeze address to zero.
  • Emits ArticleClaimed. Optional: authorship lives in the article box, not in the token.
new_version(article_id: uint64, cid: byte[36]) -> void
  • Sender: the submitter. Status preprint or under_review.
  • cid: a dag-pb CID different from the current one. The version number grows by exactly 1 (at most 65 535).
  • Moves the ASA’s ARC-19 reserve to the new CID’s digest (one inner transaction), sets prev_cid to the old CID.
  • Emits Versioned. The whole version history is in these events.
set_status(article_id: uint64, new_status: uint8) -> void

Sender: the submitter. Exactly these transitions are allowed; every other one fails:

From To
preprint under_review
preprint retracted
under_review final
under_review retracted
final retracted

preprint cannot go straight to final, retracted is final for ever, and only the contract (through flags) and governance (through resolve_dispute) move an article into or out of disputed. A retraction revokes the ASA (one inner transaction: manager, freeze and clawback set to zero). Emits StatusChanged.

accept_coauthorship(article_id: uint64) -> void
  • Sender: an address declared in publish that has not confirmed yet. Status open (1 to 3).
  • Fails if the sender already voted on the article or reviewed it.
  • Increments author_count. The new author’s share counts from publication (see claim_reputation).
  • Emits CoauthorAccepted. One-time and irreversible; there is no way to add, remove or replace a co-author.
submit_review(pay: pay, article_id: uint64, cid: byte[36], recommendation: uint8) -> uint64
  • Sender: anyone who is not an accepted author of the article. Status 1 to 4 (reviews stay allowed while disputed).
  • One review per reviewer and article. cid is a raw CID (codec 0x55); recommendation is 1 to 4.
  • Creates the review box and the reviewer index box, and the reviewer’s own reputation box in the article’s primary field when it does not exist yet (later “useful” votes are paid into it).
  • Returns review_seq (1, 2, … per article) and emits Reviewed. Reviews are immutable.
vote_review(pay: pay, article_id: uint64, review_seq: uint64) -> void
  • Sender: anyone but the reviewer, once per review. Status open.
  • The vote’s weight is 1 + isqrt(rep), where rep is the voter’s reputation in the article’s primary field.
  • Grants weight × 3 to the reviewer, under the daily cap, except when the voter is an accepted author of the article: that vote is recorded and grants 0.
  • Creates a vote box. Emits Voted (target 2), then ReputationChanged when something was granted.
vote_article(pay: pay, article_id: uint64) -> void
  • Sender: anyone but an accepted author, once per article. Status open.
  • Adds the voter’s weight to the article’s vote_total and 1 to vote_count. It touches no reputation box, so its cost does not depend on the number of authors.
  • Creates a vote box. Emits Voted (target 1, target_seq 0) and never ReputationChanged.
claim_reputation(pay: pay, article_id: uint64) -> void
  • Sender: an accepted author. Status open.
  • With N = 1 + the number of declared co-authors and T = vote_total, a confirmed co-author is entitled to floor(T / N) and the submitter to ceil(T / N). The claimable amount is the entitlement minus what the sender already claimed; it must be greater than 0.
  • Grants up to that amount in the primary field, under the daily cap (the grant must be greater than 0), and half of what was granted in the secondary field, if any, under that field’s cap. What the cap holds back stays claimable on a later day; the secondary field’s shortfall is not carried over.
  • Creates the sender’s reputation boxes in the article’s fields when they are missing.
  • Emits ReputationClaimed, then one ReputationChanged per field that received something.

See Reputation and vote weight for the reasoning and worked examples.

comment(pay: pay, article_id: uint64, cid: byte[36], reply_to: uint64, mentions: address[]) -> uint64
  • Sender: anyone, accepted authors included. Allowed in every status, retracted included.
  • cid is a raw CID (codec 0x55). reply_to is 0 for a new thread or the number of an existing comment of the same article; a reply’s depth is its parent’s depth + 1, at most 6.
  • mentions: 0 to 5 addresses in strictly ascending order of their raw 32 bytes, never the sender. They are stored only in the event, for notifications, and carry no reputation.
  • Creates the comment box, increments the parent’s reply count, and creates the commenter’s reputation box in the primary field when it is missing.
  • Returns comment_seq and emits Commented.
vote_comment(pay: pay, article_id: uint64, comment_seq: uint64) -> void
  • Sender: anyone but the comment’s author, once per comment. Status open.
  • Grants floor(weight / 5) to the comment’s author under the daily cap (nothing for a voter of weight below 5).
  • Creates a vote box. Emits Voted (target 3), then ReputationChanged when something was granted.
resolve_comment(article_id: uint64, comment_seq: uint64) -> void
  • Sender: the submitter. Status open.
  • The comment exists, was not written by an accepted author, and is not resolved yet. Any depth may be resolved, once.
  • Grants 5 to the comment’s author, under the daily cap.
  • Emits CommentResolved, then ReputationChanged when something was granted.
flag(pay: pay, article_id: uint64, reason: uint8) -> void
  • Sender: anyone who is not an accepted author and holds a reputation box in the article’s primary field with at least 10 reputation. Status 1 to 4.
  • reason is 1 to 4. One flag per address and dispute round.
  • The flag weighs 1 + isqrt(rep) and is added to the round’s total. When the total reaches 30 and the article is open, it becomes disputed. While disputed, flags are still recorded and the total keeps growing, without a status change.
  • Creates a flag box. Emits Flagged, whose new_status gives the status after the call (no StatusChanged).

See Flags, disputes and governance.

These three methods (contract v3) only emit an event: no box, no deposit, network fee only. The indexer projects them and checks identities and DOIs against outside records.

declare_identity(scheme: uint8, value: string) -> void

scheme at least 1 (1 = ORCID iD); value at most 64 bytes; an empty value withdraws the declaration. The format of the iD (its check character) is checked by the web app and the indexer, not by the contract. Emits IdentityDeclared.

declare_doi(article_id: uint64, version: uint16, doi: string) -> void
  • Sender: an accepted author of an existing article.
  • version is at most the current version; 0 means every version (Zenodo’s concept DOI).
  • A non-empty DOI is 4 to 200 bytes, starts with 10., and needs an article that is not retracted. An empty DOI withdraws the declaration, in any status.
  • Emits DoiDeclared.
follow(target: address, on: bool) -> void

target is neither the zero address nor the sender. on true follows, false unfollows. Emits Followed.

An ABI call starts with the first 4 bytes of the SHA-512/256 hash of the method signature. These values appear in the compiled program:

Selector Signature
cc694eaa create(address)void
5b672353 add_field(pay,uint16,string)void
b1349031 set_governance(address)void
99490947 resolve_dispute(uint64,uint8)void
fafe4bc1 publish(pay,byte[36],uint16,uint16,uint8,uint64,address[])uint64
21ebf21b extend()void
29d89a27 claim_article(uint64)void
d1536be5 new_version(uint64,byte[36])void
4f5856df set_status(uint64,uint8)void
a1b57ed3 accept_coauthorship(uint64)void
bdeb3721 vote_article(pay,uint64)void
51410368 claim_reputation(pay,uint64)void
9c1e9523 submit_review(pay,uint64,byte[36],uint8)uint64
81ab418c vote_review(pay,uint64,uint64)void
9151ca27 comment(pay,uint64,byte[36],uint64,address[])uint64
e7c2f56f vote_comment(pay,uint64,uint64)void
e585f1bd resolve_comment(uint64,uint64)void
566a854f flag(pay,uint64,uint8)void
cf6986fa declare_identity(uint8,string)void
8baaa94e declare_doi(uint64,uint16,string)void
f7bc7f0c follow(address,bool)void

Events are application logs. Each log is the event’s 4-byte selector (the first 4 bytes of the SHA-512/256 hash of the signature, for example Published(uint8,uint64,uint64,address,uint16,uint16,uint8,uint64,byte[36],address[],uint64)) followed by the ARC-4 encoding of its fields. Every event starts with schema_version (uint8, currently 1); ts is the block time in Unix seconds (uint64). Logs that start with 151f7c75 are ARC-4 return values, not events.

Event Fields after schema_version Emitted by Selector
FieldAdded field_id uint16, name string add_field 8f5a55e7
GovernanceChanged previous_governance address, new_governance address, ts create, set_governance b83576f0
Published article_id uint64, asa_id uint64, author address, primary_field uint16, secondary_field uint16, article_type uint8, parent_article uint64, cid byte[36], coauthors address[], ts publish ca215569
ArticleClaimed article_id uint64, author address, ts claim_article 8791e87c
Versioned article_id uint64, version uint16, cid byte[36], prev_cid byte[36], ts new_version 2cd407b6
StatusChanged article_id uint64, from_status uint8, to_status uint8, actor address, ts set_status 70b5c208
CoauthorAccepted article_id uint64, coauthor address, author_count uint16, claimed_total uint64 (always 0), ts accept_coauthorship c2abc036
ReputationClaimed article_id uint64, claimant address, consumed uint64, ts claim_reputation 2a1e4de7
Reviewed article_id uint64, review_seq uint64, reviewer address, recommendation uint8, cid byte[36], ts submit_review f7383e22
Voted target_kind uint8, article_id uint64, target_seq uint64, voter address, weight uint64, ts vote_article, vote_review, vote_comment 0cbb2b9a
Commented article_id uint64, comment_seq uint64, author address, reply_to uint64, root_seq uint64, depth uint8, cid byte[36], mentions address[], ts comment a211c33d
CommentResolved article_id uint64, comment_seq uint64, resolved_by address, ts resolve_comment 57fabb07
Flagged article_id uint64, dispute_round uint16, flagger address, reason uint8, weight uint64, round_total uint64, new_status uint8, ts flag beade69f
DisputeResolved article_id uint64, dispute_round uint16 (the round resolved), outcome uint8, new_status uint8, ts resolve_dispute 35e2de50
ReputationChanged address address, field_id uint16, delta uint64, new_total uint64, reason uint8, ts claim_reputation, vote_review, vote_comment, resolve_comment 13bdfb7b
IdentityDeclared address address, scheme uint8, value string (empty = withdrawn), ts declare_identity 4dbc3ed7
DoiDeclared article_id uint64, version uint16 (0 = every version), doi string (empty = withdrawn), declared_by address, ts declare_doi 05f59bfd
Followed follower address, target address, on bool, ts follow 6f90d760

Details that matter when you decode them:

  • Order within a call: the canonical event first, then the ReputationChanged events (primary field before secondary field for a claim). vote_article never emits ReputationChanged; a grant of 0 emits none.
  • target_seq is 0 for article votes, the review or comment number otherwise.
  • Published.coauthors and Commented.mentions are in ascending address order, not in the order of any text.
  • Entering and leaving disputed emits no StatusChanged: read Flagged.new_status and DisputeResolved.new_status.
  • string values are counted in raw bytes by the contract, which accepts any bytes. Decode them as bytes and convert to text without rejecting invalid UTF-8, as the indexer does (D-117).
  • Size limits per application call: 32 logs and 1 024 bytes. Published takes 114 bytes plus 32 per co-author, Commented with 5 mentions 278 bytes, Flagged 73 bytes.
  • The field names come from events.py. Section 11 of the specification writes some of them differently (type, from, to, author in ReputationClaimed); selectors depend only on the types, and the code is authoritative.

The events carry everything needed to rebuild every box of the application. The contract’s test suite proves it by replaying the logs and rebuilding every box byte for byte; the indexer is built the same way (see Verify without trusting ariadne.press).

Key Type Meaning
governance address the governance address
article_seq_next uint64 the next article_id, starting at 1

Box keys are binary; integers are big-endian; addresses are the raw 32 bytes. The deposit of a box is 2 500 + 400 × (key bytes + value bytes) microAlgo, paid by the caller whose action creates it.

Box Key Key bytes Value Value bytes Deposit Created by
field t + uint16 field_id 3 the name, UTF-8 1 to 96 2 500 + 400 × (3 + name bytes) add_field
article a + uint64 article_id 9 Article 192 82 900 publish
co-author au + uint64 article_id + address 42 CoAuthor 25 29 300 publish (the submitter and each declared co-author)
review r + uint64 article_id + uint64 review_seq 17 Review 85 43 300 submit_review
reviewer index ri + uint64 article_id + address 42 uint64 review_seq 8 22 500 submit_review
comment c + uint64 article_id + uint64 comment_seq 17 Comment 118 56 500 comment
article vote va + uint64 article_id + address 42 Vote 24 28 900 vote_article
review vote vr + uint64 article_id + uint64 review_seq + address 50 Vote 24 32 100 vote_review
comment vote vc + uint64 article_id + uint64 comment_seq + address 50 Vote 24 32 100 vote_comment
flag f + uint64 article_id + uint16 dispute_round + address 43 Flag 17 26 500 flag
reputation p + address + uint16 field_id 35 Reputation 22 25 300 claim_reputation, submit_review, comment

A reputation box is only ever created by an action of its own address, which pays for it. A vote never creates a box for anyone else.

The values are ARC-4 static tuples, so their sizes are fixed (each bool takes one byte).

Article (192 bytes):

Offset Field Type Notes
0 author address the submitter, immutable
32 primary_field uint16 immutable
34 secondary_field uint16 immutable, 0 = none
36 article_type uint8 immutable
37 parent_article uint64 immutable, not 0 only for amendments
45 status uint8
46 status_before_dispute uint8 0 unless disputed
47 version uint16 starts at 1
49 current_cid byte[36]
85 prev_cid byte[36] all zeros for version 1
121 created_at uint64
129 updated_at uint64 stamped by calls that change the article box
137 vote_total uint64 sum of vote weights, never decreases
145 vote_count uint64
153 review_seq_next uint64 starts at 1
161 comment_seq_next uint64 starts at 1
169 dispute_round uint16 starts at 1
171 round_flag_weight uint64 flag weight of the current round
179 author_count uint16 1 + confirmed co-authors
181 invited_count uint16 declared co-authors, immutable
183 claimed bool the ASA was claimed
184 asa_id uint64 the article’s ASA, immutable
Value Fields, in order
CoAuthor (25 bytes) invited_at uint64, accepted bool, accepted_at uint64, claimed_total uint64
Review (85 bytes) reviewer address, cid byte[36], recommendation uint8, created_at uint64, useful_total uint64
Comment (118 bytes) author address, cid byte[36], reply_to uint64, root_seq uint64, depth uint8, created_at uint64, vote_total uint64, reply_count uint64, resolved bool, resolved_at uint64
Vote (24 bytes) weight uint64, granted uint64 (always 0 for article votes), created_at uint64
Flag (17 bytes) reason uint8, weight uint64, created_at uint64
Reputation (22 bytes) rep uint64, updated_at uint64, cap_day uint32, cap_today uint16

Version history, mentions and declarations are not stored in boxes: they live only in the events.

publish creates one Algorand Standard Asset per article, an ARC-71 non-transferable asset whose issuer is the application:

Parameter Value
total, decimals 1, 0
default frozen true
unit name, asset name ARIA, Ariadne Article
URL template-ipfs://{ipfscid:1:dag-pb:reserve:sha2-256} (ARC-19)
reserve the digest of the current CID, as an address; new_version moves it
manager the application; the zero address once retracted
freeze the application; the zero address once claimed
clawback always the zero address

After a claim nobody can move the token: clawback and freeze are zero and the holding is frozen. The article box, not the token, is the authority on authorship.

From constants.py. They are compiled into the program and can only change with a new application.

Constant Value Meaning
REP_CAP_DAY 50 most reputation an address can receive per field and day, from all sources
EPOCH_DAY_SECONDS 86 400 a day for the cap: floor(block time / 86 400)
GRANT_REVIEW_NUM / DEN 3 / 1 a “useful” vote grants weight × 3 to the reviewer
GRANT_COMMENT_NUM / DEN 1 / 5 a comment upvote grants floor(weight / 5) to its author
GRANT_RESOLVED 5 a resolved comment grants 5 to its author
MIN_FLAG_REP 10 reputation in the primary field needed to flag
FLAG_THRESHOLD 30 flag weight in one round that makes an article disputed
MAX_COMMENT_DEPTH 6 deepest reply (a new thread is depth 0)
MAX_MENTIONS 5 addresses mentioned per comment
MAX_COAUTHORS 25 co-authors declared per article
MAX_FIELD_NAME 96 bytes in a field name
MAX_IDENTITY_LEN 64 bytes in a declared identity
MAX_DOI_LEN 200 bytes in a declared DOI (which starts with 10.)
MAX_VERSION 65 535 last version number
MAX_UINT16 65 535 last dispute round (takes no flags)
SCHEMA_VERSION 1 first field of every event
CID_LEN 36 bytes in a CID

Vote and flag weight is 1 + isqrt(rep) (rep 0 gives 1, 100 gives 11, 10 000 gives 101), using the AVM’s integer square root; a missing reputation box reads as 0. All arithmetic is integer arithmetic.

The size limit of an article folder (20 MB) is not a contract constant: the web app and the indexer enforce it.

Measured on LocalNet (algod 5.0.2, consensus V42) and reported in M2_REPORT.md. The approval program is 6 266 bytes (plus 4 for the clear program, 6 270 of the 8 192 allowed); there are 21 ABI methods and 18 events. One application call may spend 700 opcodes; the test gate keeps every call under 600, with at most 8 box references and 1 024 log bytes.

“Minimum fees” is the number of network minimum fees the whole group costs when an Ed25519 account signs it, counting the pay transaction and the inner transactions (multiply by the network’s current minimum fee, 1 000 microAlgo when measured). A Falcon-1024 (post-quantum) signature adds 2 minimum fees per transaction it signs.

Method Highest opcodes per application call Application calls Minimum fees (Ed25519)
add_field 111 1 2
set_governance 50 1 1
resolve_dispute 133 (cleared), 165 (retracted) 1 1, or 2 when retracting
publish, no co-author 370 1 3
publish, 4 co-authors 524 1 3
publish, 9 co-authors 741 in total 2 4
publish, 25 co-authors 1 421 in total 4 6
claim_article 141 1 5 (the asset opt-in is a transaction of its own)
new_version 177 1 2
set_status 104, 134 when retracting 1 1, or 2 when retracting
accept_coauthorship 144 1 1
vote_article 189 1 2
claim_reputation 479 1 2
submit_review 281 1 2
vote_review 344 1 2
comment 479 (a reply with 5 mentions and a new reputation box) 1 2
vote_comment 323 1 2
resolve_comment 259 1 1
flag 248 1 2
declare_identity 55 1 1
declare_doi 135 1 1
follow 48 1 1

Each declared co-author adds about 41 opcodes to publish. For the amounts readers and authors see, in ALGO, see Costs and deposits.