Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 54 additions & 0 deletions contracts/superliquidity/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# SuperLiquidity Module for OpenLib.FunC

This module provides implementation of SuperLiquidity concept using GitHub reputation as microcollateral.

## Components

### github_reputation.fc
Implements reputation scoring system for GitHub accounts based on:
- Repository stars (40% weight)
- Followers count (30% weight)
- Contributions (20% weight)
- Account age (10% weight)

### superliquidity.fc
Main smart contract implementing:
- Transaction management
- State transitions
- Reputation verification
- Microcollateral handling

## Usage

```func
#include "contracts/superliquidity/github_reputation.fc";

;; Calculate reputation score
int score = calculate_reputation_score(
stars, followers, contributions, account_age_days
);

;; Verify for collateral
int is_valid = verify_reputation_for_collateral(
stars, followers, contributions, account_age_days,
required_score
);
```

## Testing

Run tests using:
```bash
func -SPA contracts/superliquidity/tests/github_reputation_tests.fc
```

## Security

- Minimum requirements prevent spam accounts
- Weighted scoring ensures balanced evaluation
- Transaction states prevent double-spending
- Trusted oracle required for GitHub data

## License

This module is released under the GPL-3.0 License.
59 changes: 59 additions & 0 deletions contracts/superliquidity/github_reputation.fc
Original file line number Diff line number Diff line change
@@ -0,0 +1,59 @@
;; GitHub Reputation Calculator for SuperLiquidity
;; This module evaluates GitHub accounts for microcollateral

#include "stdlib.fc";

const int MIN_ACCOUNT_AGE_DAYS = 180; ;; 6 months minimum
const int MIN_STARS = 10;
const int MIN_FOLLOWERS = 5;
const int MIN_CONTRIBUTIONS = 50;

;; Reputation structure
;; stars:int, followers:int, contributions:int, account_age_days:int -> reputation:int
(int, int, int, int) load_reputation(slice s) inline {
return (s~load_uint(32), ;; stars
s~load_uint(32), ;; followers
s~load_uint(32), ;; contributions
s~load_uint(32)); ;; account_age_days
}

;; Store reputation data
builder store_reputation(builder b, int stars, int followers, int contributions, int account_age_days) inline {
return b.store_uint(stars, 32)
.store_uint(followers, 32)
.store_uint(contributions, 32)
.store_uint(account_age_days, 32);
}

;; Calculate reputation score (0-100)
int calculate_reputation_score(int stars, int followers, int contributions, int account_age_days) inline {
;; Basic requirements check
if (account_age_days < MIN_ACCOUNT_AGE_DAYS) {
return 0;
}
if ((stars < MIN_STARS) | (followers < MIN_FOLLOWERS) | (contributions < MIN_CONTRIBUTIONS)) {
return 0;
}

;; Weighted score calculation
int star_score = min(stars * 40 / 100, 40); ;; 40% weight for stars
int follower_score = min(followers * 30 / 100, 30); ;; 30% weight for followers
int contribution_score = min(contributions * 20 / 100, 20); ;; 20% weight for contributions
int age_score = min(account_age_days * 10 / 365, 10); ;; 10% weight for account age

return min(star_score + follower_score + contribution_score + age_score, 100);
}

;; Verify if reputation meets minimum requirements for microcollateral
int verify_reputation_for_collateral(int stars, int followers, int contributions, int account_age_days, int required_score) inline {
int score = calculate_reputation_score(stars, followers, contributions, account_age_days);
return score >= required_score;
}

;; Get reputation data message
cell create_reputation_data_message(int stars, int followers, int contributions, int account_age_days) inline {
return begin_cell()
.store_uint(0x52455055, 32) ;; "REPU" marker
.store_reputation(stars, followers, contributions, account_age_days)
.end_cell();
}
131 changes: 131 additions & 0 deletions contracts/superliquidity/superliquidity.fc
Original file line number Diff line number Diff line change
@@ -0,0 +1,131 @@
;; SuperLiquidity Smart Contract with GitHub Reputation
;; Implements microcollateral system using GitHub account metrics

#include "stdlib.fc";
#include "github_reputation.fc";

const int op::provide_reputation = 0x50524f56; ;; "PROV"
const int op::create_transaction = 0x43524554; ;; "CRET"
const int op::match_transaction = 0x4d415443; ;; "MATC"
const int op::liquidate = 0x4c495155; ;; "LIQU"

;; Transaction States
const int state::matching = 0;
const int state::done = 1;
const int state::liquidated = 2;

;; Storage TL-B:
;; storage#_ owner_address:MsgAddress
;; transactions:(HashmapE 64 Transaction)
;; min_reputation:uint32
;; = Storage;

;; Transaction TL-B:
;; transaction#_ id:uint64
;; state:uint8
;; owner:MsgAddress
;; reputation_score:uint32
;; amount:Coins
;; = Transaction;

(slice, (cell, int)) load_data() inline {
slice ds = get_data().begin_parse();
return (ds~load_msg_addr(), (ds~load_dict(), ds~load_uint(32)));
}

() save_data(slice owner_address, cell transactions, int min_reputation) impure inline {
set_data(begin_cell()
.store_slice(owner_address)
.store_dict(transactions)
.store_uint(min_reputation, 32)
.end_cell());
}

() recv_internal(int msg_value, cell in_msg_full, slice in_msg_body) impure {
if (in_msg_body.slice_empty?()) {
return ();
}

slice cs = in_msg_full.begin_parse();
int flags = cs~load_uint(4);
if (flags & 1) {
return ();
}
slice sender_address = cs~load_msg_addr();

(slice owner_address, (cell transactions, int min_reputation)) = load_data();

int op = in_msg_body~load_uint(32);

if (op == op::provide_reputation) {
;; Process GitHub reputation data
(int stars, int followers, int contributions, int account_age_days) = load_reputation(in_msg_body);
int score = calculate_reputation_score(stars, followers, contributions, account_age_days);

if (score >= min_reputation) {
;; Store reputation data for the sender
cell reputation_data = create_reputation_data_message(stars, followers, contributions, account_age_days);
transactions~udict_set_ref(256, slice_hash(sender_address), reputation_data);
}
return save_data(owner_address, transactions, min_reputation);
}

if (op == op::create_transaction) {
;; Create new transaction with reputation check
int amount = in_msg_body~load_coins();
int tx_id = now();

;; Check if sender has valid reputation
(cell reputation_data, int found) = transactions~udict_get_ref?(256, slice_hash(sender_address));
throw_unless(450, found);

builder tx = begin_cell()
.store_uint(tx_id, 64)
.store_uint(state::matching, 8)
.store_slice(sender_address)
.store_coins(amount);

transactions~udict_set_builder(64, tx_id, tx);
return save_data(owner_address, transactions, min_reputation);
}

if (op == op::match_transaction) {
;; Match existing transaction
int tx_id = in_msg_body~load_uint(64);
(slice tx_data, int found) = transactions~udict_get?(64, tx_id);
throw_unless(451, found);

int current_state = tx_data~load_uint(8);
throw_unless(452, current_state == state::matching);

;; Update transaction state
builder new_tx = begin_cell()
.store_uint(tx_id, 64)
.store_uint(state::done, 8)
.store_slice(tx_data);

transactions~udict_set_builder(64, tx_id, new_tx);
return save_data(owner_address, transactions, min_reputation);
}

if (op == op::liquidate) {
;; Liquidate transaction
int tx_id = in_msg_body~load_uint(64);
(slice tx_data, int found) = transactions~udict_get?(64, tx_id);
throw_unless(451, found);

int current_state = tx_data~load_uint(8);
throw_unless(453, current_state != state::done);

;; Update transaction state to liquidated
builder new_tx = begin_cell()
.store_uint(tx_id, 64)
.store_uint(state::liquidated, 8)
.store_slice(tx_data);

transactions~udict_set_builder(64, tx_id, new_tx);
return save_data(owner_address, transactions, min_reputation);
}

throw(0xffff);
}
54 changes: 54 additions & 0 deletions contracts/superliquidity/tests/github_reputation_tests.fc
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
;; Tests for GitHub reputation calculation module

#include "../github_reputation.fc";

int __test_basic_reputation_calculation() {
int stars = 100;
int followers = 50;
int contributions = 200;
int account_age_days = 365; ;; 1 year

int score = calculate_reputation_score(stars, followers, contributions, account_age_days);
;; Expected: ~85 (40 for stars + 30 for followers + 10 for age + 5 for contributions)
return score > 80 & score <= 100;
}

int __test_minimum_requirements() {
;; Test with values below minimum requirements
int score1 = calculate_reputation_score(5, 3, 20, 100); ;; Should be 0
int score2 = calculate_reputation_score(100, 100, 100, 100); ;; Should be 0 (too young account)
return (score1 == 0) & (score2 == 0);
}

int __test_reputation_data_serialization() {
int stars = 100;
int followers = 50;
int contributions = 200;
int account_age_days = 365;

cell msg = create_reputation_data_message(stars, followers, contributions, account_age_days);
slice s = msg.begin_parse();

;; Skip marker
s~load_uint(32);

;; Load and verify data
(int loaded_stars, int loaded_followers, int loaded_contributions, int loaded_age) = load_reputation(s);

return (loaded_stars == stars) &
(loaded_followers == followers) &
(loaded_contributions == contributions) &
(loaded_age == account_age_days);
}

int __test_collateral_verification() {
int required_score = 70;

;; Test valid collateral
int valid = verify_reputation_for_collateral(100, 50, 200, 365, required_score);

;; Test invalid collateral
int invalid = verify_reputation_for_collateral(10, 5, 50, 180, required_score);

return valid & ~invalid;
}