This contract represents a Tezos contract written in CameLIGO in which users can bet on events added by the Admin or an Oracle.
The current implementation of the contract is as follows :
- a
Betting
contract, the main contract - (optional) a
mock Oracle
contract - (optional) a
callback
contract for theBetting
- (optional) a
callback
contract for themock Oracle
type storage = {
manager : address;
oracle_address : address;
bet_config : bet_config_type;
events : (nat, event_type) map;
events_bets : (nat, event_bets) map;
events_index : nat;
metadata : (string, bytes) map;
}
manager
: Manager account of the Betting contractoracle_address
: Oracle contract allowed to add Events and update themevents
,events_bets
,events_index
: Events mapped to their info, their attached bets, and the latest index
type bet_config_type = {
is_betting_paused : bool;
is_event_creation_paused : bool;
min_bet_amount : tez;
retained_profit_quota : nat;
}
is_betting_paused
: is Betting on Events paused (true), or is it allowed (false)is_event_creation_paused
: is the creation of new Events paused (true), or is it allowed (false)min_bet_amount
: the minimum amount to Bet on an Event in a single transactionretainedProfit
: the quota to be retained from Betting profits (deduced as operating gains to the contract, shown as percentage, theorical max is 100)
- Deploy the Betting contract with an initial storage
- The
storage.bet_config.is_betting_paused
andstorage.bet_config.is_event_creation_paused
must have as valuefalse
- Add an Event using the
storage.manager
address - Add a Bet to the Event using an address that is not
storage.manager
norstorage.oracle_address
- (optional) Add more bets to the first team or second team on the Event
- Update the Bet to specify the outcome in
is_draw
, and the winning Team inis_team_one_win
if it is not a draw, usingstorage.manager
orstorage.oracle_address
- Finalize the Bet using
storage.manager
let init_bet_config : bet_config_type = {
is_betting_paused = false;
is_event_creation_paused = false;
min_bet_amount = 5tez;
retained_profit_quota = 10n;
} in
let init_storage : storage = {
manager = "tz1******************";
oracle_address = "KT1******************";
bet_config = init_bet_config;
events = (Map.empty : (nat, event_type) map);
events_bets = (Map.empty : (nat, event_bets) map);
events_index = 0n;
metadata = (Map.empty : (string, bytes) map);
} in
- To compile the Betting contract to Michelson code :
docker run --platform linux/amd64 --rm -v "$(PWD)":"$(PWD)" -w "$(PWD)" ligolang/ligo:stable compile contract src/contracts/cameligo/betting/main.mligo > src/compiled/betting.tz
- To compile the Betting contract to Michelson code in JSON format :
docker run --platform linux/amd64 --rm -v "$(PWD)":"$(PWD)" -w "$(PWD)" ligolang/ligo:stable compile contract src/contracts/cameligo/betting/main.mligo --michelson-format json > src/compiled/betting.json
- Using
tz1bdTsc3QdAj1935KiMxou6frwdm5RDdssT
as example forstorage.manager
- Using
KT1KMjSSDxTAUZAb7rgGYx3JF4Yz1cwQpwUi
as example forstorage.oracle_address
docker run --platform linux/amd64 --rm -v "$(PWD)":"$(PWD)" -w "$(PWD)" ligolang/ligo:stable compile storage ./contracts/cameligo/betting/main.mligo '{manager = ("tz1bdTsc3QdAj1935KiMxou6frwdm5RDdssT" : address); oracle_address = ("KT1KMjSSDxTAUZAb7rgGYx3JF4Yz1cwQpwUi" : address); bet_config = {is_betting_paused = false; is_event_creation_paused = false; min_bet_amount = 5tez; retained_profit_quota = 10n}; events = (Map.empty : (nat, TYPES.event_type) map); events_bets = (Map.empty : (nat, TYPES.event_bets) map); events_index = 0n; metadata = (Map.empty : (string, bytes) map)}' -e main
- For entrypoint SendValue
docker run --platform linux/amd64 --rm -v "$(PWD)":"$(PWD)" -w "$(PWD)" ligolang/ligo:stable run dry-run src/contracts/cameligo/betting/main.mligo 'SendValue(unit)' '37' -e main
- Compile the storage into Michelson expression :
- Using
tz1bdTsc3QdAj1935KiMxou6frwdm5RDdssT
as example forstorage.manager
- Using
KT1KMjSSDxTAUZAb7rgGYx3JF4Yz1cwQpwUi
as example forstorage.oracle_address
docker run --platform linux/amd64 --rm -v "$(PWD)":"$(PWD)" -w "$(PWD)" ligolang/ligo:stable compile storage ./contracts/cameligo/betting/main.mligo '{manager = ("tz1bdTsc3QdAj1935KiMxou6frwdm5RDdssT" : address); oracle_address = ("KT1KMjSSDxTAUZAb7rgGYx3JF4Yz1cwQpwUi" : address); bet_config = {is_betting_paused = false; is_event_creation_paused = false; min_bet_amount = 5tez; retained_profit_quota = 10n}; events = (Map.empty : (nat, TYPES.event_type) map); events_bets = (Map.empty : (nat, TYPES.event_bets) map); events_index = 0n; metadata = (Map.empty : (string, bytes) map)}' -e main
- This command produces the following Michelson storage :
(Pair (Pair (Pair (Pair (Pair False False) 5000000 10) {}) {} 0)
(Pair "tz1bdTsc3QdAj1935KiMxou6frwdm5RDdssT" {})
"KT1KMjSSDxTAUZAb7rgGYx3JF4Yz1cwQpwUi")
- Deploy with tezos-client CLI using the above Michelson code :
tezos-client originate contract betting transferring 1 from '$USER_ADDRESS' running 'src/compiled/betting.tz' --init '(Pair (Pair (Pair (Pair (Pair False False) 5000000 10) {}) {} 0)(Pair "tz1bdTsc3QdAj1935KiMxou6frwdm5RDdssT" {})"KT1KMjSSDxTAUZAb7rgGYx3JF4Yz1cwQpwUi")'
type storage = {
isPaused : bool;
manager : address;
signer : address;
events : (nat, event_type) map;
events_index : nat;
metadata : (string, bytes) map;
}
isPaused
: If the creation of events on the contract is pausedmanager
: Manager account of the Betting contractsigner
: Signer contract allowed to add Events and update them (usually a backend script)events
,events_index
: Events mapped to their info and the latest index
type event_type =
[@layout:comb] {
name : string;
videogame : string;
begin_at : timestamp;
end_at : timestamp;
modified_at : timestamp;
opponents : { team_one : string; team_two : string};
game_status : game_status;
}
The following entrypoints are available :
- ChangeManager
- ChangeSigner
- SwitchPause
- AddEvent
- GetEvent
- UpdateEvent
For full details, please consult the Oracle contracts in src/contracts/cameligo/oracle
let store : storage = {
isPaused: False;
manager: "tz1******************";
signer: "tz1******************";
events: (Map.empty : (nat, event_type) map);
events_index: 0n;
}
It is possible to use an external API to collect sample game data about eSports titles such as CS:GO, DOTA 2, and others.
Some sample requests to get data from a third-party API can be found in the Backend folder. We are using here the API provider : Pandascore.
The API access tokens can be requested by creating an account on Pandascore here
The API reference documentation can be viewed here
The scripts can be executed as follows :
node backend/matches_past.js
node backend/matches_running.js
node backend/matches_upcoming.js
The result of the queries will be a JSON file in the Backend folder, which will contain game info.
It is possible to inject this data to the Oracle after formatting manually, or automatically using a signer/broadcaster.