-
Notifications
You must be signed in to change notification settings - Fork 44
/
Copy pathairdrop.cairo
84 lines (71 loc) · 2.7 KB
/
airdrop.cairo
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
// https://github.com/CarmineOptions/carmine-api/blob/master/carmine-api-airdrop/src/merkle_tree.rs
use starknet::ContractAddress;
#[starknet::interface]
trait IAirdrop<TContractState> {
fn claim(
ref self: TContractState, claimee: ContractAddress, amount: u128, proof: Array::<felt252>
);
}
#[starknet::component]
mod airdrop {
use array::ArrayTrait;
use hash::LegacyHash;
use konoha::contract::Governance::ContractState;
use konoha::contract::Governance;
use konoha::contract::IGovernance;
use konoha::merkle_tree::MerkleTree;
use konoha::merkle_tree::MerkleTreeTrait;
use konoha::traits::IGovernanceTokenDispatcher;
use konoha::traits::IGovernanceTokenDispatcherTrait;
use option::OptionTrait;
use starknet::ContractAddress;
use starknet::ContractAddressIntoFelt252;
use traits::Into;
use traits::TryInto;
#[storage]
struct Storage {
airdrop_claimed: LegacyMap::<ContractAddress, u128>,
merkle_root: felt252
}
#[derive(starknet::Event, Drop)]
#[event]
enum Event {
Claimed: Claimed
}
#[derive(starknet::Event, Drop)]
struct Claimed {
address: ContractAddress,
received: u128
}
#[embeddable_as(AirdropImpl)]
impl Airdrop<
TContractState, +HasComponent<TContractState>
> of super::IAirdrop<ComponentState<TContractState>> {
// Lets claimee claim from merkle tree the amount - claimed_so_far
fn claim(
ref self: ComponentState<TContractState>,
claimee: ContractAddress,
amount: u128,
proof: Array::<felt252>
) {
let mut merkle_tree = MerkleTreeTrait::new();
let amount_felt: felt252 = amount.into();
let leaf = LegacyHash::hash(claimee.into(), amount_felt);
let root = merkle_tree.compute_root(leaf, proof.span());
let state = Governance::unsafe_new_contract_state();
let stored_root = self.merkle_root.read();
assert(root == stored_root, 'invalid proof');
let claimed_so_far: u128 = self.airdrop_claimed.read(claimee);
assert(claimed_so_far < amount, 'claiming more than eligible for');
let to_mint = amount - claimed_so_far;
// Mint
let govtoken_addr = state.get_governance_token_address();
IGovernanceTokenDispatcher { contract_address: govtoken_addr }
.mint(claimee, u256 { high: 0, low: to_mint });
// Write new claimed amt
self.airdrop_claimed.write(claimee, to_mint + claimed_so_far);
// Emit event
self.emit(Claimed { address: claimee, received: to_mint });
}
}
}