diff --git a/contracts/guild-factory/README.md b/contracts/guild-factory/README.md
index e69de29..68fd8cc 100644
--- a/contracts/guild-factory/README.md
+++ b/contracts/guild-factory/README.md
@@ -0,0 +1,81 @@
+# Guild Factory
+
+## Objective
+- Easily allow someone to create a guild
+- Make composable for a guild of any type
+- Allow a member to level up, this should also decay without participation
+- Allow path's or journeys that lead to apprenticeships
+- Make members accountable to each other via a reputation system or vouch
+- Always be optimistic by preventing fraud before it occurs
+- Funding payment system should be seperate
+
+
+## Inspiration
+- [Raid Guild](https://handbook.raidguild.org/)
+- [Near Guilds](https://near.org/start-a-guild/)
+- [Guild.xyz](https://guild.xyz/)
+
+## Guild
+
+Guilds can be created by anyone, they are intentionally bare to allow composablity for any use case
+
+
+
+## Constitution
+
+A `Guild` has a `Constitution`. These are a set of rules that `Member`s should abide by.
+
+## Member
+
+Once a user joins a guild, the `Member` resource is added to the users account. It will track the `Guild`s that a `Member` is associated with.
+
+## Apprenticeship
+
+A guild has `Apprenticeships`. These are badges/credentials([Soul Based Tokens?](https://papers.ssrn.com/sol3/papers.cfm?abstract_id=4105763)) that a `Member` earns if they complete a series of specified `Journeys`.
+
+### Journeys
+
+`Journey`s are pathways that consist of a series of `Task`s. These are meant to capture a certain skill set eg Error Handling in Rust.
+
+### Tasks
+
+`Task`s are a step in gaining a skill set(`Journey`). These can be anything and only have two prerequsites(name and description). They track users submissions by a `Member` submitting a deliverable.
+
+## Reputation
+
+> WIP
+
+three varibles in place that could be used to determine reputation(just to get the conversation flowing):
+
+1. Vouching by other users
+2. Member Score: Completion rate at different levels eg Apprenticeship and Journey
+3. Deliverable scoring for tasks by peers(anonymous)
+
+## Payments
+
+> WIP
+
+
+## Basic Functionality
+
+**Guild functions**
+
+- Create Guild
+- Create Apprenticeship
+- Add Constitution
+- Add/remove Constitution rule
+- Create Membership
+- Add/remove Role
+
+
+**Apprenticeship functions**
+
+- Add Journey
+- Add Task
+- Add Deliverable
+
+
+**Member Fuctions**
+
+- Add/remove Detail
+- Change Detail
\ No newline at end of file
diff --git a/contracts/guild-factory/sources/GuildFactory.move b/contracts/guild-factory/sources/GuildFactory.move
index e69de29..ae05205 100644
--- a/contracts/guild-factory/sources/GuildFactory.move
+++ b/contracts/guild-factory/sources/GuildFactory.move
@@ -0,0 +1,544 @@
+// SPDX-License-Identifier: MIT
+
+/// @title GuildFactory
+/// @notice Create composable guilds for public use.
+/// @dev This is a factory for creating `Guild`s.
+
+
+address Std {
+ module GuildFactory {
+ use Std::GAS::GAS;
+ use Std::Vector;
+ use Std::Signer;
+ use Std::DiemConfig;
+ use Std::Diem;
+ use Std::DiemAccount;
+
+ const ADDRESS_DOES_NOT_CONTAIN_GUILD = 1;
+ const GUILD_DOES_NOT_CONTAIN_JOURNEY = 2;
+ const INDEX_DOES_NOT_EXIST = 3;
+ const CANNOT_REMOVE_DEFAULT_ROLE = 4;
+ const GUILD_DOES_NOT_CONTAIN_APPRENTICESHIP = 5;
+ const USER_DOES_NOT_HAVE_APPRENTICESHIP = 6;
+ const GUILD_APPRENTICESHIP_DOES_NOT_CONTAIN_MEMBER_SCORE = 7;
+ const GUILD_JOURNEY_DOES_NOT_CONTAIN_MEMBER_SCORE = 8;
+ const GUILD_DOES_NOT_CONTAIN_TASK = 9;
+
+ // @dev The member resource that is store on a users account to track their memberships.
+ struct Member has key, store {
+ memberships: Vector
,
+ details: vector,
+ }
+
+ // @dev The membership resource that is stored on a member and guild account to track.
+ struct Membership has key, copy {
+ guild: address,
+ user: address,
+ role: Role,
+ level: u64,
+ reputation: Reputation,
+ }
+
+ // @dev allows members to specify outside credentials that may be applicable for indentity verification.
+ struct Detail {
+ key: vector,
+ value: vector
+ }
+
+
+ // @dev guilds are groups of members that are trying to achieve a particular goal/s.
+ struct Guild has key, store {
+ name: string,
+ description: string,
+ constitution: vector>,
+ members: Vector,
+ roles: Vector,
+ apprenticeships: Vector,
+ details: Vector,
+ created: u64,
+ updated: u64,
+ active: bool,
+ }
+
+ // @dev A role that a guild is using and the reputation score.
+ struct Role has copy {
+ name: vector,
+ reputation: u64,
+ }
+
+
+ //TODO: use Memberscore and vouching to determine reputation weight and role.
+ // @dev reputation keeps track of the credentials a member earns in a guild and if their peers support them.
+ struct Reputation {
+ vouchers: vector,
+ credentials: vector,
+ weight: u64,
+
+ }
+
+ //TODO: use Member score as a mechanism to determine reputation.
+ // @dev keeps track of the score a member earns in a apprenticeship/journey compared to the completed state.
+ struct MemberScore {
+ user: address,
+ score: u64,
+ }
+
+ // @dev apprenticeships is a badge of honor that a member would get after completing a set of journeys.
+ struct Apprenticeship {
+ uid: u64,
+ name: string,
+ description: string,
+ journeys: Vector,
+ member_scores: Vector,
+ created: u64,
+ updated: u64,
+ active: bool,
+ }
+
+ // @dev journeys consist of a group of tasks that would help them learn a particular skill or complete a mission.
+ struct Journey {
+ name: string,
+ description: string,
+ tasks: Vector,
+ member_scores: Vector,
+ created: u64,
+ updated: u64,
+ active: bool,
+ }
+
+ // @dev tasks are individual components within a journey that have a specific deliverable.
+ struct Task {
+ name: vector,
+ description: vector,
+ deliverable: vector,
+ created: u64,
+ active: bool,
+ }
+
+ // @dev deliverables are for members to post submissions to tasks.
+ struct Deliverable {
+ member: address,
+ link: vector,
+ }
+
+
+
+ ///////// INIT FUNCTIONS ////////
+
+ // @dev create guild, two values must be specified.
+ public entry fun init_guild(sender: &signer, name: vector, description: vector ) {
+ //Role is defaulted for any new member
+ let r = Role(
+ name: 'New Member',
+ reputation: 0);
+
+ let g = Guild(
+ name: name,
+ description: description,
+ constitution: Vector::empty>(),
+ members: Vector::empty(),
+ roles: Vector::empty(),
+ apprenticeships: Vector::empty(),
+ details: Vector::empty(),
+ created: DiemConfig::get_current_epoch(),
+ updated: DiemConfig::get_current_epoch(),
+ active: true,
+ );
+
+ Vector::push_back(g.roles,r);
+
+ move_to(_sender, g)
+ }
+
+ // @dev create Member resource on the user account if the user does not already have it.
+ fun init_member(_sender: &signer) {
+ if (!exists(Signer::address_of(_sender))) {
+ let new_details = init_details();
+ move_to(_sender, Member {
+ memberships: Vector::empty(),
+ details: new_details,
+ })
+ }
+ }
+
+
+
+ ///////// CREATE FUNCTIONS ////////
+
+ /// @dev create a new membership for the guild.
+ fun create_membership(_sender: &signer, guild: address) {
+ assert(!exists(address), ADDRESS_DOES_NOT_CONTAIN_GUILD);
+
+ //create member resource on sender if they do not currently have it.
+ init_member(_sender);
+ let g = borrow_global(guild)
+ let u = borrow_global(Signer::address_of(_sender))
+ let r = Reputation(
+ vouchers: Vector::create(),
+ credentials: Vector::create(),
+ weight: 0,
+ );
+
+ let m = Membership(
+ guild: guild,
+ user: Signer::address_of(_sender),
+ role: Role(
+ name: 'New Member',
+ reputation: 0,
+ ),
+ level: Vector::empty(),
+ reputation: r,
+ );
+ Vector::push_back(&u.memberships, guild);
+ Vector::push_back(&g.members, m);
+
+ }
+
+ // @dev create a new journey for a guild.
+ fun create_journey(guild: address, apprenticeship: u64, name: vector, description: vector) acquires Guild {
+ assert(!exists(address), ADDRESS_DOES_NOT_CONTAIN_GUILD);
+
+ let g = borrow_global(guild)
+ let j = Journey(
+ name: name,
+ description: description,
+ tasks: Vector::empty(),
+ member_scores: Vector::empty(),
+ created: DiemConfig::get_current_epoch(),
+ updated: DiemConfig::get_current_epoch(),
+ active: true,
+ );
+ Vector::push_back(&g.journeys, j);
+ }
+
+ fun create_task(guild: address, journey: vector, name: vector, description: vector) {
+ assert(!exists(address), ADDRESS_DOES_NOT_CONTAIN_GUILD);
+
+
+ let g = borrow_global(guild)
+ let (t, i) = get_Journey_index_by_name(guild, name);
+ assert(!t, GUILD_DOES_NOT_CONTAIN_JOURNEY);
+
+ let j = Vector::borrow(&g.journeys, i);
+
+ let t = Task(
+ name: name,
+ description: description,
+ deliverable: Vector::empty,
+ created: DiemConfig::get_current_epoch(),
+ active: true,
+ );
+ Vector::push_back(&j.tasks, t);
+ }
+
+
+ ///////// GUILD UTILS ////////
+
+ fun create_constitution(guild: address, constitution: vector>) acquires Guild {
+ assert(!exists(address), ADDRESS_DOES_NOT_CONTAIN_GUILD);
+ let g = borrow_global(guild)
+ g.constitution = constitution;
+ }
+
+
+ fun add_constitution_rule(guild: address, rule: vector) acquires Guild {
+ assert(!exists(address), ADDRESS_DOES_NOT_CONTAIN_GUILD);
+ let g = borrow_global(guild)
+ Vector::push_back>(&g.constitution, rule);
+ }
+
+
+ fun remove_constitution_rule(guild: address, index: u64) acquires Guild {
+ assert(!exists(address), ADDRESS_DOES_NOT_CONTAIN_GUILD);
+ let len = Vector::length(&g.constitution);
+ let g = borrow_global_mut(guild);
+ assert(index <= len - 1 , INDEX_DOES_NOT_EXIST);
+ Vector::remove(&mut g.constitution, index);
+ }
+
+ //TODO: check reputation is below threshold
+ fun add_role(guild: address, name: vector, reputation: u64) acquires Guild {
+ assert(!exists(address), ADDRESS_DOES_NOT_CONTAIN_GUILD);
+ let g = borrow_global_mut(guild)
+ let r = Role(
+ name: name,
+ reputation: reputation,
+ );
+ Vector::push_back(&mut g.roles, r);
+ }
+
+
+ //TODO: check if members have role, no members should have a role that is being removed.
+ fun remove_role(guild: address, name: vector) acquires Guild {
+ assert(name == 'New Member', CANNOT_REMOVE_DEFAULT_ROLE);
+ assert(!exists(address), ADDRESS_DOES_NOT_CONTAIN_GUILD);
+ let len = Vector::length(&g.roles);
+ let g = borrow_global_mut(guild);
+ assert(index <= len - 1 , INDEX_DOES_NOT_EXIST);
+ Vector::remove(&mut g.roles, index);
+ }
+
+
+
+ ///////// COMPLETION UTILS ////////
+
+ //TODO: likely a better way to bubble up the completion. Seems super inefficient.
+ //@dev update the completion(MemberScore) of a Apprenticship for a user.
+ fun update_apprenticeship_completion(user: address, guild: address, name: vector) acquires Guild {
+ assert(!exists(address), ADDRESS_DOES_NOT_CONTAIN_GUILD);
+ let g = borrow_global(guild);
+ let (t, i) = get_apprenticeship_index_by_name(guild, name);
+ if(!t) {
+ assert(false, GUILD_DOES_NOT_CONTAIN_APPRENTICESHIP);
+ }
+ let a = Vector::borrow(&g.apprenticeships, i);
+ let journey_length = Vector::length(&a.journeys);
+ let apprenticeship_score = 0;
+ let i = 0;
+ while(i < journey_length){
+ let j = 0;
+ let journey = Vector::borrow(&a.journeys, i);
+ let ms_len = Vector::length(&journey.member_scores);
+ while(j < ms_len){
+ let ms = Vector::borrow(&journey.member_scores, j);
+ if(ms.user == user){
+ apprenticeship_score += ms.score;
+ }
+ }
+ }
+ let (t2, i2) = get_apprenticeship_member_score_index(a, user);
+ if(!t2) {
+ assert(false, GUILD_APPRENTICESHIP_DOES_NOT_CONTAIN_MEMBER_SCORE);
+ }
+ let ams = Vector::borrow(&a.member_scores, i2);
+ ams.score = apprenticeship_score;
+ }
+
+ //@dev update the completion(MemberScore) of a Journey for a user.
+ fun update_journey_completion(user: address, guild: address, name: vector) acquires Guild {
+ assert(!exists(address), ADDRESS_DOES_NOT_CONTAIN_GUILD);
+ let g = borrow_global(guild);
+ let (t, i) = get_journey_index_by_name(guild, name);
+ if(!t) {
+ assert(false, GUILD_DOES_NOT_CONTAIN_JOURNEY);
+ }
+ let j = Vector::borrow(&g.journeys, i);
+ let journey_length = Vector::length(&j.tasks);
+ let journey_score = 0;
+ let i = 0;
+ while(i < journey_length){
+ let t = Vector::borrow(&j.tasks, i);
+ let d_len = Vector::length(&t.deliverable);
+ let j = 0;
+ while(j < d_len){
+ let d = Vector::borrow(&t.deliverable, j);
+ if(d.user == user){
+ journey_score += d.score;
+ }
+ }
+ }
+ let (t2, i2) = get_journey_member_score_index(j, user);
+ if(!t2) {
+ assert(false, GUILD_JOURNEY_DOES_NOT_CONTAIN_MEMBER_SCORE);
+ }
+ let jms = Vector::borrow(&j.member_scores, i2);
+ jms.score = journey_score;
+ }
+
+ //@dev Get the completion status(MemberScore) of an apprenticeship for a user.
+ fun get_apprenticeship_percentage_completion(user: address, guild: address, name: vector) acquires Guild {
+ assert(!exists(address), ADDRESS_DOES_NOT_CONTAIN_GUILD);
+ let g = borrow_global(guild);
+ let (t, i) = get_apprenticeship_index_by_name(guild, name);
+ if(!t) {
+ assert(false, GUILD_DOES_NOT_CONTAIN_APPRENTICESHIP);
+ }
+ let a = Vector::borrow(&g.apprenticeships, i);
+ let ms_len = Vector::length(&a.member_scores);
+ let i = 0;
+ while(i < ms_len){
+ let ms = Vector::borrow(&a.member_scores, i);
+
+ if (ms.address == user) return (true, ms.score);
+
+ i = i + 1;
+ };
+ (false, 0)
+ }
+
+
+ ///////// TASK INTERATIONS ////////
+
+ fun add_deliverable(guild: address, task: vector, apprenticeship: vector, journey: vector) acquires Guild {
+ assert(!exists(address), ADDRESS_DOES_NOT_CONTAIN_GUILD);
+ let g = borrow_global_mut(guild);
+ let d = Deliverable(
+ name: name,
+ score: 0,
+ );
+ let (t, i) = get_apprenticeship_index_by_name(guild, apprenticeship);
+ if(!t) {
+ assert(false, GUILD_DOES_NOT_CONTAIN_APPRENTICESHIP);
+ }
+ let a = Vector::borrow_mut(&mut g.apprenticeships, i);
+ let (t2, i2) = get_journey_index_by_name(guild, journey);
+ if(!t2) {
+ assert(false, GUILD_DOES_NOT_CONTAIN_JOURNEY);
+ }
+ let j = Vector::borrow_mut(&mut a.journeys, i2);
+ let (t3, i3) = get_task_index_by_name(guild, task);
+ if(!t3) {
+ assert(false, GUILD_DOES_NOT_CONTAIN_TASK);
+ }
+ let t = Vector::borrow_mut(&mut j.tasks, i3);
+ Vector::push(&mut t.deliverable, d);
+
+ //bubble up completion to update scores.
+ update_journey_completion(g.owner, guild, journey);
+ update_apprenticeship_completion(g.owner, guild, apprenticeship);
+
+ }
+
+
+
+ ///////// UTILS ////////
+
+ fun init_details(): Vector acquires Detail{
+ //creates a details array for a worker
+ let details = Vector::empty();
+ //initialized with some defaults Alias, github, twitter, discord
+ Vector::push_back(details,Detail {key: 'alias',value: Vector::empty()});
+ Vector::push_back(details,Detail {key: 'github',value: Vector::empty()});
+ Vector::push_back(details,Detail {key: 'twitter',value: Vector::empty()});
+ Vector::push_back(details,Detail {key: 'discord',value: Vector::empty()});
+
+ details
+ }
+
+
+ //TODO: make below three details functions reusable between guild and Member
+ public fun add_detail(_sender: &signer, key: vector, value: vector) acquires Member, Details {
+ let w = borrow_global_mut(_sender);
+ Vector::push_back(&w.details, Detail{
+ key: key,
+ value: value
+ })
+ }
+
+
+ public fun remove_detail(_sender: &signer, key: vector) acquires Member, Details {
+ let m = borrow_global_mut(_sender);
+ let (t,i) = get_index_by_key(Signer::address_of(_sender));
+ assert(!t, KEY_DOES_NOT_EXIST);
+ if (t) {
+ Vector::remove(&mut m.details, i);
+ }
+ }
+
+
+ public fun change_detail(_sender: &signer, key: vector, value: vector) acquires Member, Details {
+ let m = borrow_global_mut(_sender);
+ let (t,i) = get_index_by_key(Signer::address_of(_sender));
+ assert(!t, KEY_DOES_NOT_EXIST);
+ if (t) {
+ Vector::remove(&mut m.details, i);
+ let d = Vector::borrow(&mut m.details, i);
+ d.value = value;
+ }
+
+ }
+
+
+ fun get_index_by_key(_worker: address, _key: Vector): (bool, u64) acquires Worker, Detail {
+ let w = borrow_global(_worker);
+ let len = Vector::length(&w.details);
+
+ let i = 0;
+ while (i < len) {
+ let d = Vector::borrow(&w.details, i);
+
+ if (d.key == _key) return (true, i);
+
+ i = i + 1;
+ };
+ (false, 0)
+ }
+
+
+ // @dev removes an element from the list of payments, and returns in to scope.
+ fun get_journey_index_by_name(_guild_addr: address, _name: vector): (bool, u64) acquires Guild {
+ let g = borrow_global(_guild_addr);
+
+ let len = Vector::length(&g.journeys);
+
+ let i = 0;
+ while (i < len) {
+ let j = Vector::borrow(&g.journeys, i);
+
+ if (g.name == _name) return (true, i);
+
+ i = i + 1;
+ };
+ (false, 0)
+ }
+
+
+ // @dev removes an element from the list of payments, and returns in to scope.
+ fun get_role_index_by_name(_guild_addr: address, _name: vector): (bool, u64) acquires Guild {
+ let g = borrow_global(_guild_addr);
+
+ let len = Vector::length(&g.roles);
+
+ let i = 0;
+ while (i < len) {
+ let j = Vector::borrow(&g.roles, i);
+
+ if (j.name == _name) return (true, i);
+
+ i = i + 1;
+ };
+ (false, 0)
+ }
+
+
+ fun get_apprenticeship_index_by_name(_guild_addr: address, _name: vector): (bool, u64) acquires Guild {
+ let g = borrow_global(_guild_addr);
+
+ let len = Vector::length(&g.apprenticeships);
+
+ let i = 0;
+ while (i < len) {
+ let a = Vector::borrow(&g.apprenticeship, i);
+
+ if (a.name == _name) return (true, i);
+
+ i = i + 1;
+ };
+ (false, 0)
+ }
+
+
+ fun get_apprenticeship_member_score_index(&mut _apprenticeship: Apprenticeship, user: address): (bool, u64) acquires Apprenticeship {
+ let ms_len = Vector::length(&_apprenticeship.member_scores);
+ let i = 0;
+ while (i < ms_len) {
+ let ms = Vector::borrow(&_apprenticeship.member_scores, i);
+ if (ms.address == user) return (true,i);
+ i = i + 1;
+ };
+ (false,0)
+ }
+
+
+ fun get_journey_member_score_index(&mut _journey: Journey, user: address): (bool, u64) acquires Journey {
+ let ms_len = Vector::length(&_journey.member_scores);
+ let i = 0;
+ while (i < ms_len) {
+ let ms = Vector::borrow(&_journey.member_scores, i);
+ if (ms.address == user) return (true,i);
+ i = i + 1;
+ };
+ (false,0)
+ }
+}
+}
\ No newline at end of file