Skip to Content
ContractsDelay Structure

Delay Structure

The MACI protocol uses a dynamic delay mechanism to give Operators reasonable processing time, while penalizing overdue behavior. Delay limits are computed dynamically based on circuit tier and actual vote message count, rather than using a fixed value.


Core Formula

delay_allowed = (BASE_DELAY + msg_count × PER_VOTE_DELAY) × 3 tally_timeout = delay_allowed + 2 days
VariableMeaning
BASE_DELAYCircuit-specific base processing time (seconds), derived from benchmarks
msg_countActual number of vote messages published (msg_chain_length)
PER_VOTE_DELAYPer-vote processing time (flat 2 seconds/vote)
×3Adaptation multiplier, gives Operator extra buffer
+2 daysHard timeout added on top of delay_allowed

Parameters

Base Delay (per circuit tier)

CircuitMax VotersBenchmark TimeBase Delay
2-1-1-5≤ 25~0.48 min (0.2267 + 0.2516 min)60s
4-2-2-25≤ 625~2.88 min (2.5346 + 0.3404 min)180s
6-3-3-125≤ 15,625~22.26 min (21.9313 + 0.3308 min)1380s
9-4-3-125≤ 1,953,125(benchmark in progress)14400s (TODO)

Per-Vote Delay (unified)

ParameterValueRationale
PER_VOTE_DELAY2 seconds/voteBased on 4-2-2-25 (0.2531s) and 6-3-3-125 (0.2289s); rounded up to 1s then doubled for additional safety margin

Example Calculations

2-1-1-5, 10 votes

delay_allowed = (60 + 10 × 2) × 3 = 240s = 4 min tally_timeout = 240 + 172800 = 173040s ≈ 2 days 4 min

4-2-2-25, 500 votes

delay_allowed = (180 + 500 × 2) × 3 = 3540s = 59 min tally_timeout = 3540 + 172800 = 176340s ≈ 2 days 59 min

6-3-3-125, 10000 votes

delay_allowed = (1380 + 10000 × 2) × 3 = 64140s ≈ 17.8 hours tally_timeout = 64140 + 172800 = 236940s ≈ 2.74 days

Delay Checkpoints

Tally Delay

Evaluated when stop_tallying_period is called:

Triggered when: current_time - voting_end_time > delay_allowed

When triggered, a TallyDelay record is written on-chain and the following event attributes are emitted (consumed by the indexer):

AttributeDescription
delay_timestampVoting end time (delay start point)
delay_durationActual elapsed time (seconds)
delay_reasonTimeout description string
delay_type"tally_delay"

Deactivate Delay

Evaluated when process_deactivate_message is called (fixed 10-minute window; not affected by this change).


Timeout Penalty (execute_claim)

When claim is called:

Note: fee_recipient (set by the registry at round creation) and admin (the round admin) are different addresses. When a timeout occurs, fee_recipient receives nothing.

Scenariofee_recipientOperatorAdmin
No delay, completed on time10%90%0%
1 TallyDelay record10%45%45%
2 TallyDelay records10%0%90%
N DeactivateDelay messages10%90% - N x 4.5%N x 4.5%
Exceeded tally_timeout0%0%100%

Relationship to Fee Structure

delay_allowed and tally_timeout are both computed dynamically from the actual msg_chain_length (votes published). This is independent of the Base Fee which is charged upfront based on max_voter:

DimensionFeeDelay limit
Basismax_voter (maximum scale)msg_chain_length (actual messages)
TimingCharged once at round creationComputed dynamically when tallying ends
Circuit differentiationBase Fee varies by circuitBase Delay varies by circuit
Unified componentVote Fee = 0.06 DORA/vote (flat)Per-Vote Delay = 2s/vote (flat)
Last updated on