Skip to content

Commit

Permalink
Refactor token out of repo (#34)
Browse files Browse the repository at this point in the history
* refactor token out of this repo

* most tests working again

* fix timelock_test

* tests compiling

* governor tests working

* add some e2e tests and some other nits

* improve and simplify the interface of the staker

* refactoring, testing, cleanup

* delete 2 unused files

* scarb 2.6.3
  • Loading branch information
moodysalem authored Mar 13, 2024
1 parent ab9e2e5 commit e72a70c
Show file tree
Hide file tree
Showing 21 changed files with 1,018 additions and 997 deletions.
2 changes: 1 addition & 1 deletion .tool-versions
Original file line number Diff line number Diff line change
@@ -1 +1 @@
scarb 2.6.1
scarb 2.6.3
17 changes: 9 additions & 8 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,14 +8,6 @@ Simple contracts for governance on Starknet.

Each component of the governance contracts in this repository may be used independently.

### GovernanceToken

`GovernanceToken` is an ERC20 that tracks delegations as well as time-weighted average delegations for any period

- Users MAY delegate their tokens to other addresses
- The average historical delegation weight is computable over *any* historical period
- The contract has no owner and is not upgradeable.

### Airdrop

`Airdrop` can be used to distribute any fungible token, including the `GovernanceToken`. To use it, you must compute a binary merkle tree using the pedersen hash function. The root of this tree and the token address are passed as constructor arguments.
Expand All @@ -25,6 +17,15 @@ Each component of the governance contracts in this repository may be used indepe
- Transfer the total amount of tokens to the `Airdrop` contract
- The contract has no owner and is not upgradeable. Unclaimed tokens, by design, cannot be recovered.

### Staker

`Staker` is a contract used by the governor for staking tokens to be used in voting.

- Users MAY delegate their tokens to other addresses
- Users lock up their tokens, staking them which allows them to be delegated
- The average historical delegation weight is computable over *any* historical period
- The contract has no owner and is not upgradeable.

### Timelock

`Timelock` allows a list of calls to be executed, after a configurable delay, by its owner
Expand Down
4 changes: 2 additions & 2 deletions Scarb.toml
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@ name = "governance"
version = "0.1.0"
description = "Contracts for governance of Starknet-native protocols"
homepage = "https://ekubo.org"
cairo-version = "2.6.1"
cairo-version = "2.6.3"
edition = '2023_11'

[dependencies]
starknet = "=2.6.1"
starknet = "=2.6.3"

[[target.starknet-contract]]
allowed-libfuncs-list.name = "audited"
Expand Down
22 changes: 12 additions & 10 deletions src/airdrop.cairo
Original file line number Diff line number Diff line change
Expand Up @@ -13,27 +13,29 @@ pub struct Claim {
}

#[starknet::interface]
pub trait IAirdrop<TStorage> {
pub trait IAirdrop<TContractState> {
// Return the root of the airdrop
fn get_root(self: @TStorage) -> felt252;
fn get_root(self: @TContractState) -> felt252;

// Return the token being dropped
fn get_token(self: @TStorage) -> IERC20Dispatcher;
fn get_token(self: @TContractState) -> ContractAddress;

// Claims the given allotment of tokens.
// Because this method is idempotent, it does not revert in case of a second submission of the same claim.
// This makes it simpler to batch many claims together in a single transaction.
// Returns true iff the claim was processed. Returns false if the claim was already claimed.
// Panics if the proof is invalid.
fn claim(ref self: TStorage, claim: Claim, proof: Span<felt252>) -> bool;
fn claim(ref self: TContractState, claim: Claim, proof: Span<felt252>) -> bool;

// Claims the batch of up to 128 claims that must be aligned with a single bitmap, i.e. the id of the first must be a multiple of 128
// and the claims should be sequentially in order. The proof verification is optimized in this method.
// Returns the number of claims that were executed
fn claim_128(ref self: TStorage, claims: Span<Claim>, remaining_proof: Span<felt252>) -> u8;
fn claim_128(
ref self: TContractState, claims: Span<Claim>, remaining_proof: Span<felt252>
) -> u8;

// Return whether the claim with the given ID has been claimed
fn is_claimed(self: @TStorage, claim_id: u64) -> bool;
fn is_claimed(self: @TContractState, claim_id: u64) -> bool;
}

#[starknet::contract]
Expand All @@ -47,7 +49,7 @@ pub mod Airdrop {
use super::{IAirdrop, ContractAddress, Claim, IERC20Dispatcher};


pub(crate) fn hash_function(a: felt252, b: felt252) -> felt252 {
pub fn hash_function(a: felt252, b: felt252) -> felt252 {
let a_u256: u256 = a.into();
if a_u256 < b.into() {
core::pedersen::pedersen(a, b)
Expand All @@ -57,7 +59,7 @@ pub mod Airdrop {
}

// Compute the pedersen root of a merkle tree by combining the current node with each sibling up the tree
pub(crate) fn compute_pedersen_root(current: felt252, mut proof: Span<felt252>) -> felt252 {
pub fn compute_pedersen_root(current: felt252, mut proof: Span<felt252>) -> felt252 {
match proof.pop_front() {
Option::Some(proof_element) => {
compute_pedersen_root(hash_function(current, *proof_element), proof)
Expand Down Expand Up @@ -146,8 +148,8 @@ pub mod Airdrop {
self.root.read()
}

fn get_token(self: @ContractState) -> IERC20Dispatcher {
self.token.read()
fn get_token(self: @ContractState) -> ContractAddress {
self.token.read().contract_address
}

fn claim(ref self: ContractState, claim: Claim, proof: Span<felt252>) -> bool {
Expand Down
Loading

0 comments on commit e72a70c

Please sign in to comment.