DAO Contract Source Code

Fd8kfCuqU8BoFFp6GcXv5pC8XXRkBK7gUPQX5XDz7iXj
proof/auth-money-transfer.zk
  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
k = 11;
field = "pallas";

constant "AuthMoneyTransfer" {
    EcFixedPointBase NULLIFIER_K,
}

witness "AuthMoneyTransfer" {
    # Proposal parameters
    Base proposal_auth_calls_commit,
    Base proposal_creation_blockwindow,
    Base proposal_duration_blockwindows,
    Base proposal_user_data,
    Base proposal_blind,

    # DAO parameters
    Base dao_proposer_limit,
    Base dao_quorum,
    Base dao_early_exec_quorum,
    Base dao_approval_ratio_quot,
    Base dao_approval_ratio_base,
    Base dao_gov_token_id,
    EcNiPoint dao_notes_public_key,
    Base dao_proposer_public_x,
    Base dao_proposer_public_y,
    Base dao_proposals_public_x,
    Base dao_proposals_public_y,
    Base dao_votes_public_x,
    Base dao_votes_public_y,
    Base dao_exec_public_x,
    Base dao_exec_public_y,
    Base dao_early_exec_public_x,
    Base dao_early_exec_public_y,
    Base dao_bulla_blind,

    # Dao input(s) user data blind
    Base input_user_data_blind,

    # Dao output coin attrs
    Base dao_value,
    Base dao_token_id,
    Base dao_coin_blind,

    # Should be set to DAO_CONTRACT_ID
    Base dao_exec_func_id,

    # Epehemeral secret used for diffie-hellman shared secret derivation
    Base ephem_secret,
}

circuit "AuthMoneyTransfer" {
    # Cast to EcPoint
    # (otherwise zkas refuses to compile)
    ONE = witness_base(1);
    dao_notes_pubkey = ec_mul_var_base(ONE, dao_notes_public_key);
    dao_notes_public_x = ec_get_x(dao_notes_pubkey);
    dao_notes_public_y = ec_get_y(dao_notes_pubkey);

    dao_bulla = poseidon_hash(
        dao_proposer_limit,
        dao_quorum,
        dao_early_exec_quorum,
        dao_approval_ratio_quot,
        dao_approval_ratio_base,
        dao_gov_token_id,
        dao_notes_public_x,
        dao_notes_public_y,
        dao_proposer_public_x,
        dao_proposer_public_y,
        dao_proposals_public_x,
        dao_proposals_public_y,
        dao_votes_public_x,
        dao_votes_public_y,
        dao_exec_public_x,
        dao_exec_public_y,
        dao_early_exec_public_x,
        dao_early_exec_public_y,
        dao_bulla_blind,
    );

    # Proposal bulla being valid means DAO bulla is also valid because
    # dao-propose-main.zk already checks that when we first create the
    # proposal - so it is redundant to check DAO bulla exists here.
    proposal_bulla = poseidon_hash(
        proposal_auth_calls_commit,
        proposal_creation_blockwindow,
        proposal_duration_blockwindows,
        proposal_user_data,
        dao_bulla,
        proposal_blind,
    );
    constrain_instance(proposal_bulla);

    # Check inputs are spending from the correct DAO
    input_user_data_enc = poseidon_hash(dao_bulla, input_user_data_blind);
    constrain_instance(input_user_data_enc);

    # Change output should be sending back to the DAO
    dao_change_coin = poseidon_hash(
        dao_notes_public_x,
        dao_notes_public_y,
        # We don't need to check this value.
        # money::transfer() checks that sum(input values) = sum(output values)
        # which ensures it will be correct.
        dao_value,
        # Likewise the token_id must match the other output coins.
        dao_token_id,
        dao_exec_func_id,
        dao_bulla,
        dao_coin_blind,
    );
    constrain_instance(dao_change_coin);
    constrain_instance(dao_exec_func_id);

    # Reveal content commit. This should contain the set of coins.
    # We check these are set in the runtime.
    constrain_instance(proposal_auth_calls_commit);

    # Now do verifiable encryption for DAO change output

    # Ephemeral public key
    ephem_public = ec_mul_base(ephem_secret, NULLIFIER_K);
    constrain_instance(ec_get_x(ephem_public));
    constrain_instance(ec_get_y(ephem_public));

    # The shared_point C = eP = dE
    shared_point = ec_mul_var_base(ephem_secret, dao_notes_public_key);
    shared_secret = poseidon_hash(
        ec_get_x(shared_point),
        ec_get_y(shared_point),
    );

    const_1 = witness_base(1);
    const_2 = witness_base(2);
    const_3 = witness_base(3);

    # Value
    shared_secret_1 = poseidon_hash(shared_secret, const_1);
    enc_value = base_add(dao_value, shared_secret_1);
    constrain_instance(enc_value);

    # Token ID
    shared_secret_2 = poseidon_hash(shared_secret, const_2);
    enc_token_id = base_add(dao_token_id, shared_secret_2);
    constrain_instance(enc_token_id);

    # Serial
    shared_secret_3 = poseidon_hash(shared_secret, const_3);
    enc_coin_blind = base_add(dao_coin_blind, shared_secret_3);
    constrain_instance(enc_coin_blind);
}