Olympics & Competitions

Olympics DAO consists a set of smart contracts that aim to implement a truly decentralized competition management.

Overview

Olympics

The Olympics contract is managing the community and the competitions. When an Olympics contract is deployed, it also deploys an instance of Community (see below). The Olympics contract consists the functions for creating competition, closing competition (once finished), and fetching all the competitions within the Olympics.

A modified onlyOlympicsCoreTeam is used to ensure access to the functions for managing the competitions.

modifier onlyOlympicsCoreTeam() {
    require(
        community.isCoreTeamMember(msg.sender),
        "Only Olympics Core Team can call this"
    );
    _;
}

Only a SkillWallet holder, that's marked as a core team member can call those functions.

    function createCompetition(
        uint256 role,
        uint256 skill1,
        uint256 skill2,
        uint256 skill3,
        string calldata metadata,
        uint startTime, 
        uint endTime
    ) external;

    function getCompetitions() external view returns (address[] memory);

Community

Olympics DAO uses SkillWallet implementation of community with a single difference that there is no high cap on members allowed. Everyone can join and participate in a competition. The community has the concept of core team members. An attribute called onlyCoreTeam member is used to secure the functions that can be called only by the team.

 modifier onlyCoreTeam() {
        require(
            isCoreTeamMember[msg.sender],
            "The signer is not whitelisted as core team member!"
        );
        require(
            skillWallet.balanceOf(msg.sender) > 0,
            "SkillWallet not created by the whitelisted member"
        );
        _;
    }

For more information about the community please visit [link].

Competition

Once a user has created their SkillWallet and is part of the Olympics DAO community, they can also join a competition. One Olympics instance has multiple competitions that can be created by core team members. When a core team member calls createCompetition function, a Competition contract is deployed and is assigned to this specific Olympics contract. Each competition is assigned to a role and skill. Each Olympics community has 3 roles, and each role has 4 skills. There are 12 competitions in total covering all the skills within these roles.

Each competition can be associated with one role and up to 3 skills.

Each competition has a partner/co-host. The core team members of Olympics DAO can be added to the cohost whitelist of the competition. This gives them rights to set the winners, create checkpoints and pass checkpoints for a member.

The competition contract is managing the participants, cohosts and skills.

    string public metadataUri;

    address[] participants;
    address[] partners;
    mapping(address => bool) public override isParticipant;
    mapping(address => bool) public override isPartner;


    uint256 public role;
    uint256[] public skills;
    mapping(uint256 => bool) public isCompetitionSkill;
    uint256 public startDate;
    uint256 public endDate;

Only a SkillWallet holder that's a part of the Olympics Community can join a competition.

Each competition has off-chain metadata that's stored as a JSON file on IPFS and the CID is assigned to the competition. This off-chain metadata holds information such as Name, Description, Competition Logo etc.

Within competition, there are three modifiers managing the permissions to the functions within the contract - onlyOlympicsCoreTeam that you've seen above and onlyParticipant , and onlyPartner.

modifier onlyParticipant() {
    require(isParticipant[msg.sender], "Only participants can call this!");
    _;
}

modifier onlyPartner() {
    require(isPartner[msg.sender], "Only partner member can call this!");
    _;
}

Competition.sol implements the following interface:

interface ICompetition { event ParticipantAdded( address indexed _member, uint256 _skillWalletTokenId, uint256 competitionID );


/**
 * @title Olympics DAO Competition
 *
 * @dev ICompetition interface
 * @author SkillWallet
 */

interface ICompetition {
    event PartnerMemberAdded();
    event CheckpointCreated();
    event CheckpointPassed();
    event ParticipantAdded(address indexed _member);

    /** 
        @dev Adds a member of the Olympics DAO to the competition.
        access: public (will fail if the signer is not a part of the OlympicsDAO Community)
     */
    function join() external;


    function addPartnerMemberToCompetition(address member) external;

    /**
        @dev Creates a checkpoint for the competition. Assigns the off chain metadata to the checkpoint.
        @param metadata - off-chain metadata stored on IPFS as a JSON file
        access: only core team members 
     */
    function createCheckpoint(
        string memory metadata,
        uint256 startDate,
        uint256 endDate,
        uint256[3] calldata skills
    ) external;

    /**
        @dev Returns list of the addresses of the participants 
        @return address[] memory
        access: public 
     */
    function getParticipants() external returns (address[] memory);

    /**
        @dev Returns list of the addresses of the partners members 
        @return address[] memory
        access: public 
     */
    function getPartnerMembers() external returns (address[] memory);

    /**
        @dev Returns whether a competition is ongoing.
        @return bool is ongoing?
        access: public 
     */
    function isOngoing() external view returns (bool);


    /** 
        @dev 
        @return bool if the passed address is a participanting in the competition
        access: public 
     */
    function isParticipant(address member) external view returns (bool);

    /** 
        @dev 
        @return bool if the passed address is a partner member in the competition
        access: public 
     */
    function isPartner(address member) external view returns (bool);
}

Olympics DAO is implementing progressive decentralisation. In the beginning, the voting is done by core team members adding a ranking each participant of a competition. With the next Olympics DAO upgrade, there will be a voting mechanism introduced that will replace this. Before that the partners will be able to set the winners of the competition.

Checkpoint

In order for a participant to complete successfully a competition, they need to pass all the checkpoints. By passing checkpoints the participants build their skill level.

After a participant passes a checkpoint, one of the core team members should mark it as passed in order for the participant to get their skill level updated.


/**
 * @title Olympics DAO ICheckpoint
 *
 * @dev ICheckpoint interface
 * @author SkillWallet
 */
interface ICheckpoint {

    event CheckpointCreated(uint256 checkpointID, address competitionAddress);
    event CheckpointPassed(uint256 checkpointID, address userAddress);

    /** 
        @dev Creates a new checkpoint for a specific competition.
        @param metadata - off-chain metadata of the checkpoint stored on IPFS 
        access: only core team members 
     */
    function create(
        string calldata metadata,
        uint256 startDate,
        uint256 endDate,
        uint256[3] calldata skills,
        uint role
    ) external;

    /** 
        @dev Marks a checkpoint as passed by the participant.
        returns bool if the passed address is a participanting in the competition
        @param checkpointID - participant address
        @param user - participant address
        access: only core team members 
     */
    function pass(uint256 checkpointID, address user) external;

    /** 
        @dev Fetches all checkpoints per competition
        returns uint256[] memory checkpoints - checkpoint IDs
        @param competition The address of the competition
        access: public 
     */
    function getCheckpointsPerCompetition(address competition)
        external
        view
        returns (uint256[] memory checkpoints);

    function hasAParticipantPassedTheCheckpoint(
        uint256 checkpointID,
        address member
    ) external view returns (bool);

    function hasSkill(
        uint256 checkpointID,
        uint256 role,
        uint256 skill
    ) external view returns (bool);
}

CommunitySkill.sol

The CommunitySkill contract is responsible for calculating the skill level of a member of the Olympics DAO, depending on the checkpoints passed.

It implements the following interface:

/**
 * @title SkillWallet CommunitySkills
 *
 * @dev Implementation of the CommunitySkills concept in the scope of the SkillWallet project
 * @author SkillWallet
 */

interface ICommunitySkills {

    function calculateSkillLevel(
        address member,
        uint256 role,
        uint256 skill
    ) external;

    function getSkillLevel(
        address member,
        uint256 role,
        uint256 skill
    ) external view returns (uint256);
}

The skill level is calculated with the following formula:

where the checkpoints taken into consideration, are only the ones associated to the role <-> skill which is calculated.

Last updated