Matryx Platform

This documentation details the features of the Matryx Platform Smart Contract system. You can check out the Matryx Platform source code here.

Entering Matryx

Matryx is a decentralized application for solving difficult scientific problems. The Matryx’s commit system allows you to timestamp and value your work on the Ethereum blockchain, providing you with immutable proof of ownership over your content. The Matryx bounty system enables users to place bounties on scientific problems and to award creative solutions, allowing people to build up chains of work and be rewarded for their contributions.

Welcome!

Approving Platform Transactions

To interact with the platform, you first need to tell MatryxToken that you approve of MatryxPlatform, and specify a number of tokens you want to approve. This is done by calling

token.approve(MatryxPlatform.address, tokens)

Great! Now that you know how to approve platform transactions, you can create tournaments, make submissions, and interact with other platform users.

The Matryx Commit System

The commit system is a collaborative content and IP tracking tool that allows value to be assigned and distributed across sequences of innovation. The commit system is comprised of individual commits, which are units of work containing an IPFS content hash and a self-determined value that indicates how much each commit is worth. Additionally, commits can contain links to previous commits, allowing users to collaborate with each other and build up entire chains of work.

Creating your first Commit

In order to create a new commit, you will first need to claim the hash that you are going to use for it on the system. This is done by calling

commit.claimCommit(commitHash)

Where commitHash is a hash that’s comprised of your public Ethereum address, an IPFS hash of the content of your commit, and some salt used to encrypt the commit’s contents.

The reason you have to claim a commit hash before actually creating the commit is to prevent frontrunning attacks. If a malicious actor were monitoring the system when you try to create the commit, they could potentially steal and take ownership of your commit content if they send the same transaction as you and their transaction gets mined first. The claimCommit function exists to prevent this kind of attack. Once you have claimed a commit hash, the system knows that this particular hash belongs to you. So, when you send the transaction to create the commit and actually reveal the commit’s content, no malicious actor can frontrun the transaction and steal your work.

That said, you can create your commit by calling

commit.createCommit(parentHash, isFork, salt, content, value)

Salt and content are the same hashes that you used to claim your commit. Value is a user-specified amount that indicates how much you think your commit is worth. The first two fields, parentHash and isFork are used whenever you want to work off of someone else’s commit. We will now explain how this collaboration process takes place.

Groups and Collaboration

Commit groups are used to allow people to team up and work freely off of each other’s commits. In order to make a commit off of a parent commit, you must either be in the parent commit’s group, or fork off of the commit and start working with a new group.

To add a new user (or multiple users) to your group, you can call these two functions, respectively:

commit.addGroupMember(commitHash, user)
commit.addGroupMembers(commitHash, users)

Where commitHash is the hash of the commit in the chain that the new user wants to contribute to.

Warning

Group members cannot be removed from the group after you have added them. You should only add to your group users that you trust.

Any group member can add you to their group. Once you become a part of the group, you will be able to make new commits along the same commit chain without having to pay for each of the commits made by your group members. To create a commit off of another commit by someone in your group, you call the createCommit function and pass the hash of their commit as your parentHash. Since you are working in the same group, isFork should be false.

Forking Commits

The process of forking off of a commit is similar to that of creating a new commit. First, you need to claim a commit hash using the same claim function:

commit.claimCommit(commitHash)

Then, you create your commit:

commit.createCommit(parentHash, isFork, salt, content, value)

Now, parentHash is the hash of the commit you want to fork, and isFork should be true.

When you fork off of a commit, you are buying the right to use the entire previous chain of work for your own line of work that you are initiating at this point. The new commit that you create will represent a new starting point, and you will be the only user in the group (until you decide to add more people). After the fork, you will be able to work off of your commit freely, as you now have the right to use the previous line of work before the fork and the work that you and your group members add from that point on.

To fork off of a commit, you have to compensate the owners of commits in the chain for their contributions. The cost of a fork is the sum of the value of the commits in the line of work up until that point. Therefore, before you fork, you should make sure that you have approved at least that many MTX tokens.

Note

Anyone can fork a commit. You do not have to be in a commit’s group in order to fork the commit.

The Matryx Bounty System

The Matryx Bounty system enables and incentivizes decentralized scientific collaboration in the form of tournaments and submissions, where all users participating in a tournament receive credit for their contributions, and the tournament bounty is rightfully distributed among the chosen winners.

Tournament and Round States

Each tournament in Matryx is subdivided into rounds, which are indexed incrementally. In each round, tournament participants make submissions to the tournament, and at the end of each round one or multiple submissions are selected by the tournament owner to be the winners of the round. The round winners then receive the allocated round reward.

A tournament can be in one of five possible states: NotYetOpen, OnHold, Open, Closed, or Abandoned.

If a tournament is NotYetOpen, then its first round has not started yet. If it is OnHold, that means that the tournament has already started but the next upcoming round has yet to begin. Open tournaments are the ones that are currently active: submissions are being made or reviewed. Closed tournaments are no longer active; the tournament owner has decided to end the tournament, and all of the tournament’s bounty has been distributed among the various rounds’ winners. Lastly, a tournament becomes Abandoned if a round ends without receiving any submissions, or if the tournament owner fails to select winners before the end of the round’s review period.

You can check the state of a tournament at any time by calling

tournament.getState()

A round can be in one of seven possible states: NotYetOpen, Unfunded, Open, InReview, HasWinners, Closed, or Abandoned.

Rounds that have not started yet are NotYetOpen. A round is Unfunded if it has already started but the tournament owner has not added any MTX to its bounty yet. Open rounds are currently active; you can enter the round and make new submissions. If a round is InReview, you can no longer make any more submissions (you’re going to have to wait until the next round!). This is the time when the tournament owner reviews all the submissions made to the round and selects the winners. A round is Closed after the InReview period ends. Lastly, a round becomes Abandoned if it reaches the end of its Open state without receiving any submissions.

You can check the state of any round at any time by calling

tournament.getRoundState(roundIndex)

Entering and Exiting Tournaments

To enter a tournament that you’d like to participate in, you can make the following call:

tournament.enter()

Whenever you enter a tournament, you will have to pay the tournament entry fee designated by the tournament creator, so you will need to first approve at least that many MTX tokens. To check what a tournament’s entry fee is before entering, you can call

tournament.getDetails()

You can choose to exit an ongoing tournament at any time with the following call:

tournament.exit()

When you exit the tournament, the entry fee that you paid when you first entered will be returned to you automatically.

Note

If you later decide to enter the tournament again, you will have to pay the tournament entry fee again before making any submissions.

If a tournament you are currently participating in happens to become Abandoned, you can collect your share of the remaining tournament bounty, as well as your original entry fee, with the following call:

tournament.withdrawFromAbandoned()

Making your first Submission

To create a submission, you must first enter the tournament that you want to participate in by calling

tournament.enter()

You can then create a submission in two ways: You can create a new commit and submit it to the tournament, or you can submit one of your previous commits.

To create a new commit, you first need to claim the commit hash:

commit.claimCommit(commitHash)

Then, you can create the commit and submit it to a tournament using the following function:

commit.createSubmission(tournament, content, parentHash, isFork, salt, commitContent, value)

Where tournament is the address of the tournament, content is the Submission content, and parentHash, isFork, salt, commitContent, and value are the data that corresponds to the commit you are creating.

Alternatively, if you want to submit a commit that already exists, you can simply call:

tournament.createSubmission(content, commitHash)

Where content is the content of your submission and commitHash is the hash of your commit.

Checking Commit Balances

If a commit receives some amount of MTX, the appropriate amount will be allocated to the commit on the Matryx platform. To check the current allocated balance of any commit, you can call

commit.getCommitBalance(commitHash)

Collecting your Reward

When a commit in your line of work receives a reward from winning a tournament, you can withdraw your share of the reward by calling:

commit.withdrawAvailableReward(commitHash)

To check the reward that any user is entitled to for any particular commit, you can call

commit.getAvailableRewardForUser(userAddress)

After you withdraw your reward, your available reward for that particular commit goes down to 0.

The share of the reward that is allocated to each commit owner in a commit chain is proportional to the total value of the commits that they created. Therefore, when a commit wins a tournament, everyone who contributed a piece of work used by the winning commit receives compensation for their contributions.

Creating your own Tournament

To create a tournament, you can call the createTournament function on the platform as follows:

platform.createTournament(tournamentDetails, roundDetails)

Where tournamentDetails and roundDetails are:

struct TournamentDetails
{
    string content;
    uint256 bounty;
    uint256 entryFee;
}

struct RoundDetails
{
    uint256 start;
    uint256 duration;
    uint256 review;
    uint256 bounty;
}

These structs contain information about the tournament that you are about to create and the first round that will kick off when the tournament begins. You can add more funds to the tournament bounty at any point, but you cannot remove funds from it after you make the createTournament call, so choose your initial bounty wisely!

Similarly, you cannot remove funds from the share of the tournament bounty you assign to the first round, and you won’t be able to edit the round details after the round has started. Be sure to enter a reasonable amount of time (in seconds) for the round’s start time and duration, as well as its review period. You’ll need some time to look over the submissions and choose your round winners before the review period ends!

Note

The tournament and round bounty will be visible to any users looking to enter your tournament, as well as the tournament and round details.

Updating Tournament Details

To edit the data of your tournament, you can call the updateDetails function as follows:

tournament.updateDetails(tournamentDetails)

Where tournamentDetails is the same data struct used to create the tournament originally. The bounty field, however, will not change when you try to modify the tournament’s data.

Adding to a Tournament Bounty

Suppose you wanted to add MTX to a tournament’s bounty. You can call the addToBounty function as follows:

tournament.addToBounty(amount)

This function transfers MTX to the specified tournament. To allocate these new funds to the current round, you can call the transferToRound function:

tournament.transferToRound(amount)

The added MTX will now also be distributed to this round’s winners when it is time to reward their submissions.

Warning

Remember that you cannot remove funds from a tournament’s bounty after you’ve added them or remove funds from a round after it has already started.

Choosing Tournament Winners

To get all the submissions made to a round, you can call

tournament.getRoundInfo(roundIndex)

Round info contains all the hashes of all the submissions made to the round. To view the contents of each submission, you can call

platform.getSubmission(submissionHash)

To choose your round winners, you can call selectWinners on the tournament as follows:

tournament.selectWinners(winnersData, roundDetails)

Where winnersData is:

struct WinnersData
{
    bytes32[] submissions;
    uint256[] distribution;
    uint256 action;
}

Here, action represents an enumerated value from the following enum:

enum SelectWinnerAction { DoNothing, StartNextRound, CloseTournament }

and RoundDetails are:

struct RoundDetails
{
    uint256 start;
    uint256 duration;
    uint256 review;
    uint256 bounty;
}

In winnersData, you can specify which submissions get rewarded and how much MTX is assigned to each one. The first parameter contains all the winning submissions’ hashes, and the second contains the reward each one will get, respectively, expressed as a percentage or a proportion of the total round bounty.

When selecting round winners, you have three options for how to proceed with the tournament: you can choose to wait until the end of the review period for the next round to start, to start the next round immediately after selecting the winners, or to close the tournament. The action you choose (0, 1 or 2, representing SelectWinnerAction.DoNothing, SelectWinnerAction.StartNextRound and SelectWinnerAction.CloseTournament, respectively) is passed as the third parameter of winnersData and indicates how you would like to proceed.

If you choose to wait until the end of the review period (DoNothing), the next round will automatically be created as an identical copy of the last round, and it will begin once the current review period ends. If you choose to start the next round immediately when you select the winners (StartNextRound), the next round will be initialized with the round data that you provide and will begin immediately. If you choose to close the Tournament (CloseTournament), the remaining bounty unallocated to any round will be allocated to the current round and used to award winnersData.submissions, and the Tournament will end.

Warning

Once you close the tournament, you can’t open it up again. Any remaining funds that might still be in the tournament’s balance will be evenly distributed among the last round’s winners when you decide to close the tournament.

Warning

If the round’s review period ends and you still have not chosen any winners, the tournament will be considered Abandoned, and any remaining funds in the tournament’s balance will be uniformly allocated to all of the round’s participants for them to withdraw.

Matryx Marketplace

Stay tuned!

Frequently Asked Questions

Stay tuned!

Versions

Stay tuned!