├── .gitignore ├── ridl_id ├── ridl_id.wasm ├── lib │ ├── types.h │ └── common.h ├── scripts │ ├── seed.sh │ ├── set.sh │ ├── perms.sh │ └── set_types.sh ├── models │ ├── balances.h │ ├── bond.h │ ├── identity.h │ ├── reputable.h │ └── reputation.h ├── tables.sh ├── actions │ ├── balance_actions.hpp │ ├── bond_actions.hpp │ ├── identity_actions.hpp │ └── reputation_actions.hpp ├── ridl_id.cpp └── ridl_id.abi ├── ridl_token ├── ridl_token.wasm ├── ridl_token-claim-rc.md ├── scripts │ ├── upload.sh │ └── set.sh ├── ridl_token-transfer-rc.md ├── LICENSE.md ├── ridl_token.hpp ├── ridl_token.abi └── ridl_token.cpp ├── helpers ├── system_account.sh ├── account.sh ├── genesis.json └── setup_nodeos.sh ├── setup.sh ├── test_data.sh └── ridl_ibc └── eosio └── ridl_ibc.cpp /.gitignore: -------------------------------------------------------------------------------- 1 | .idea 2 | cmake-build-debug -------------------------------------------------------------------------------- /ridl_id/ridl_id.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GetScatter/RIDL-Contracts/HEAD/ridl_id/ridl_id.wasm -------------------------------------------------------------------------------- /ridl_id/lib/types.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace types { 4 | 5 | typedef uint64_t uuid; 6 | } 7 | -------------------------------------------------------------------------------- /ridl_token/ridl_token.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/GetScatter/RIDL-Contracts/HEAD/ridl_token/ridl_token.wasm -------------------------------------------------------------------------------- /ridl_token/ridl_token-claim-rc.md: -------------------------------------------------------------------------------- 1 | ## Claim Terms & Conditions 2 | 3 | I, {{claimer}} am simply claiming my own row in this contract and assuming my own costs for RAM. -------------------------------------------------------------------------------- /ridl_token/scripts/upload.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | cleos -u https://nodes.get-scatter.com set contract ridlridlcoin ../ridl_token -p ridlridlcoin 4 | cleos -u https://nodes.get-scatter.com set abi ridlridlcoin ridl_token.abi -p ridlridlcoin 5 | -------------------------------------------------------------------------------- /ridl_id/scripts/seed.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | shopt -s expand_aliases 4 | source ~/.bash_aliases 5 | 6 | PUBLIC_KEY=${1:-EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV} 7 | 8 | cleos push action ridlridlridl seed '["optimusprime", "'$PUBLIC_KEY'"]' -p ridlridlridl 9 | -------------------------------------------------------------------------------- /helpers/system_account.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | shopt -s expand_aliases 3 | source ~/.bash_aliases 4 | 5 | name=${1:-test} 6 | key=${2:-EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV} 7 | 8 | cleos system newaccount eosio --transfer "$name" "$key" "$key" --stake-net "20.0000 EOS" --stake-cpu "1000.0000 EOS" --buy-ram-kbytes 100000 9 | -------------------------------------------------------------------------------- /ridl_id/scripts/set.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | shopt -s expand_aliases 4 | source ~/.bash_aliases 5 | 6 | eosio-cpp --abigen --contract=ridlridlridl ./ridl_id/ridl_id.cpp -o ~/contracts/ridl_id.wasm 7 | sed -i 's/1.1/1.0/g' ~/contracts/ridl_id.abi 8 | cleos set contract ridlridlridl ~/contracts/ ridl_id.wasm ridl_id.abi -p ridlridlridl@active -------------------------------------------------------------------------------- /ridl_id/models/balances.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | namespace balances { 4 | 5 | struct [[eosio::table, eosio::contract("ridlridlridl")]] balances { 6 | uint64_t symbol; 7 | asset balance; 8 | 9 | uint64_t primary_key() const { return symbol; } 10 | }; 11 | 12 | typedef eosio::multi_index<"balances"_n, balances> Balances; 13 | } 14 | -------------------------------------------------------------------------------- /helpers/account.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | shopt -s expand_aliases 3 | source ~/.bash_aliases 4 | 5 | name=${1:-test} 6 | key=${2:-EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV} 7 | 8 | cleos create account eosio "$name" "$key" 9 | 10 | # cleos system newaccount eosio --transfer "$name" "$key" --stake-net "1000.0000 SYS" --stake-cpu "1000.0000 SYS" --buy-ram-kbytes 100000 11 | -------------------------------------------------------------------------------- /ridl_id/scripts/perms.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | shopt -s expand_aliases 4 | source ~/.bash_aliases 5 | 6 | PKEY=EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV 7 | 8 | cleos set account permission ridlridlridl active \ 9 | '{"threshold": 1,"keys": [{"key": "'$PKEY'","weight": 1}],"accounts": [{"permission":{"actor":"ridlridlridl","permission":"eosio.code"},"weight":1}]}' owner 10 | -------------------------------------------------------------------------------- /ridl_token/scripts/set.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | shopt -s expand_aliases 4 | source ~/.bash_aliases 5 | 6 | # eosio-cpp --abigen --contract=token ridl_token.cpp -o ridl_token.wasm 7 | # cleos set contract ridlridlcoin . ridl_token.wasm ridl_token.abi -p ridlridlcoin@active 8 | 9 | eosio-cpp --abigen --contract=token ./ridl_token/ridl_token.cpp -o ~/contracts/ridl_token.wasm 10 | sed -i 's/1.1/1.0/g' ~/contracts/ridl_token.abi 11 | cleos set contract ridlridlcoin ~/contracts/ ridl_token.wasm ridl_token.abi -p ridlridlcoin@active 12 | 13 | -------------------------------------------------------------------------------- /ridl_id/tables.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | shopt -s expand_aliases 4 | source ~/.bash_aliases 5 | 6 | echo "-------------------" 7 | echo "RepTypes" 8 | cleos get table ridlridlridl ridlridlridl reptypes 9 | echo "" 10 | echo "" 11 | 12 | echo "Balances" 13 | cleos get table ridlridlridl eosio balances 14 | echo "" 15 | echo "" 16 | 17 | echo "Identities" 18 | cleos get table ridlridlridl ridlridlridl ids 19 | echo "" 20 | echo "" 21 | 22 | echo "Reputables" 23 | cleos get table ridlridlridl ridlridlridl reputables -l 500 24 | echo "" 25 | echo "" 26 | 27 | echo "Reputation" 28 | cleos get table ridlridlridl 2 reputations 29 | 30 | echo "Topups" 31 | cleos get table ridlridlridl ridlridlridl topups 32 | 33 | echo "Bonds" 34 | cleos get table ridlridlridl ridlridlridl bonds 35 | echo "-------------------" 36 | -------------------------------------------------------------------------------- /ridl_token/ridl_token-transfer-rc.md: -------------------------------------------------------------------------------- 1 | ## Transfer Terms & Conditions 2 | 3 | I, {{from}}, certify the following to be true to the best of my knowledge: 4 | 5 | 1. I certify that {{quantity}} is not the proceeds of fraudulent or violent activities. 6 | 2. I certify that, to the best of my knowledge, {{to}} is not supporting initiation of violence against others. 7 | 3. I have disclosed any contractual terms & conditions with respect to {{quantity}} to {{to}}. 8 | 9 | I understand that funds transfers are not reversible after the {{transaction.delay}} seconds or other delay as configured by {{from}}'s permissions. 10 | 11 | If this action fails to be irreversibly confirmed after receiving goods or services from '{{to}}', I agree to either return the goods or services or resend {{quantity}} in a timely manner. -------------------------------------------------------------------------------- /helpers/genesis.json: -------------------------------------------------------------------------------- 1 | { 2 | "initial_timestamp": "2018-03-02T12:00:00.000", 3 | "initial_key": "EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV", 4 | "initial_configuration": { 5 | "max_block_net_usage": 1048576, 6 | "target_block_net_usage_pct": 1000, 7 | "max_transaction_net_usage": 524288, 8 | "base_per_transaction_net_usage": 12, 9 | "net_usage_leeway": 500, 10 | "context_free_discount_net_usage_num": 20, 11 | "context_free_discount_net_usage_den": 100, 12 | "max_block_cpu_usage": 100000, 13 | "target_block_cpu_usage_pct": 500, 14 | "max_transaction_cpu_usage": 50000, 15 | "min_transaction_cpu_usage": 100, 16 | "max_transaction_lifetime": 3600, 17 | "deferred_trx_expiration_window": 600, 18 | "max_transaction_delay": 3888000, 19 | "max_inline_action_size": 4096, 20 | "max_inline_action_depth": 4, 21 | "max_authority_depth": 6 22 | }, 23 | "initial_chain_id": "6cbecff836a9fa60da53bf97a0a180103b2e76041d4414693d11bf39e2341547" 24 | } -------------------------------------------------------------------------------- /ridl_token/LICENSE.md: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2018 Scatter, Inc. http://get-scatter.com 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. -------------------------------------------------------------------------------- /ridl_id/scripts/set_types.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | shopt -s expand_aliases 4 | source ~/.bash_aliases 5 | 6 | cleos push action ridlridlridl forcetype '["security", 0, "Secure", "Insecure"]' -p ridlridlridl 7 | cleos push action ridlridlridl forcetype '["privacy", 0, "Discreet", "Indiscreet"]' -p ridlridlridl 8 | cleos push action ridlridlridl forcetype '["scam", 0, "Trusted", "Scam"]' -p ridlridlridl 9 | cleos push action ridlridlridl forcetype '["solvency", 0, "Solvent", "Insolvent"]' -p ridlridlridl 10 | cleos push action ridlridlridl forcetype '["social", 0, "", ""]' -p ridlridlridl 11 | cleos push action ridlridlridl forcetype '["dangerous", 0, "Safe", "Dangerous"]' -p ridlridlridl 12 | cleos push action ridlridlridl forcetype '["accuracy", 0, "Accurate", "Inaccurate"]' -p ridlridlridl 13 | cleos push action ridlridlridl forcetype '["rarity", 0, "Rare", "Common"]' -p ridlridlridl 14 | cleos push action ridlridlridl forcetype '["fees", 0, "Low/No Fees", "High Fees"]' -p ridlridlridl 15 | cleos push action ridlridlridl forcetype '["user experience", 0, "", ""]' -p ridlridlridl 16 | cleos push action ridlridlridl forcetype '["code standards", 0, "Open Source", "Closed Source"]' -p ridlridlridl 17 | -------------------------------------------------------------------------------- /helpers/setup_nodeos.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | shopt -s expand_aliases 4 | source ~/.bash_aliases 5 | 6 | # Sets up nodeos after blowing it away or from a fresh install. 7 | # Uses the standard EOSIO public key to initialize. 8 | # Defaults the the `eos` directory to `~/eosio.contracts` if no path is specified 9 | 10 | # !!!FAQ!!! You might need to run this twice. 11 | # It seems to time out on setting the eosio.system contract. 12 | 13 | # nodeos --delete-all-blocks --genesis-json ./genesis.json 14 | 15 | USE_SYSTEM=${1:-0} 16 | EOS_BASE_PATH=${2:-"$HOME/eosio.contracts"} 17 | 18 | 19 | 20 | PKEY=EOS6MRyAjQq8ud7hVNYcfnVPJqcVpscN5So8BhtHuGYqET5GDW5CV 21 | 22 | cleos create account eosio eosio.ram $PKEY $PKEY -p eosio 23 | cleos create account eosio eosio.ramfee $PKEY $PKEY -p eosio 24 | cleos create account eosio eosio.stake $PKEY $PKEY -p eosio 25 | cleos create account eosio eosio.token $PKEY $PKEY -p eosio 26 | 27 | cleos set contract eosio.token $EOS_BASE_PATH/eosio.token --abi eosio.token.abi -p eosio.token 28 | cleos push action eosio.token create '[ "eosio", "1000000000.0000 SYS"]' -p eosio.token 29 | cleos push action eosio.token issue '[ "eosio", "1000000000.0000 SYS", "init" ]' -p eosio 30 | cleos push action eosio.token create '[ "eosio", "1000000000.0000 EOS"]' -p eosio.token 31 | cleos push action eosio.token issue '[ "eosio", "1000000000.0000 EOS", "init" ]' -p eosio 32 | 33 | if [ $USE_SYSTEM -eq 1 ]; then 34 | echo "Loading system contract" 35 | cleos set contract eosio $EOS_BASE_PATH/eosio.system -p eosio 36 | cleos push action eosio init '["0", "4,EOS"]' -p eosio 37 | fi -------------------------------------------------------------------------------- /setup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # add to ~/.bash_aliases 4 | #alias "cleos=cleos -u http://ridlnet.get-scatter.com" 5 | shopt -s expand_aliases 6 | source ~/.bash_aliases 7 | 8 | # Pass in any argument to only rebuild RIDL contract. 9 | # Otherwise it will set up everything necessary on a clean EOSIO chain. 10 | 11 | USER_KEY=EOS8YQzaYLxT17fWAPueQBxRjHehTQYZEvgPAWPPH4mAuwTJi3mPN 12 | 13 | if [ "$#" -eq 0 ]; then 14 | # Basic Setup 15 | helpers/setup_nodeos.sh 1 16 | helpers/system_account.sh ridlridlcoin 17 | helpers/system_account.sh ridlridlridl 18 | helpers/system_account.sh ridlreserves 19 | helpers/system_account.sh test1account $USER_KEY 20 | helpers/system_account.sh test2account $USER_KEY 21 | 22 | 23 | # Token Setup 24 | ridl_token/scripts/set.sh 25 | cleos push action ridlridlcoin create '[]' -p ridlridlcoin 26 | cleos transfer eosio test1account "100000.0000 EOS" "" -p eosio 27 | cleos transfer eosio test2account "100000.0000 EOS" "" -p eosio 28 | 29 | # RIDL Contract Setup 30 | ridl_id/scripts/set.sh 31 | ridl_id/scripts/perms.sh 32 | ridl_id/scripts/set_types.sh 33 | 34 | # TEST IDENTITIES 35 | cleos transfer test1account ridlridlridl "10.0000 EOS" "" -p test1account 36 | cleos transfer test2account ridlridlridl "10.0000 EOS" "" -p test2account 37 | cleos push action ridlridlridl identify '["test1account", "HelloWorld", "'$USER_KEY'"]' -p test1account 38 | cleos push action ridlridlridl identify '["test2account", "HelloWorld2", "'$USER_KEY'"]' -p test2account 39 | cleos push action ridlridlridl identify '["test2account", "HelloWorld3", "'$USER_KEY'"]' -p test2account 40 | 41 | fi 42 | 43 | if [ "$#" -eq 1 ]; then 44 | ridl_id/scripts/set.sh 45 | fi 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /ridl_id/actions/balance_actions.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | 5 | #include "../models/balances.h" 6 | using namespace balances; 7 | 8 | class BalanceActions { 9 | public: 10 | name _self; 11 | BalanceActions(name self):_self(self){} 12 | 13 | void hasBalance(const name& account, const asset& quantity){ 14 | Balances balances(_self, account.value); 15 | auto iterator = balances.find(quantity.symbol.raw()); 16 | eosio_assert(iterator != balances.end(), "Could not find balance"); 17 | eosio_assert(iterator->balance.amount >= quantity.amount, "Not enough tokens."); 18 | } 19 | 20 | void addBalance(const name& account, const asset& quantity){ 21 | Balances balances(_self, account.value); 22 | auto iterator = balances.find(quantity.symbol.raw()); 23 | if(iterator == balances.end()) balances.emplace(_self, [&](auto& row){ 24 | row.symbol = quantity.symbol.raw(); 25 | row.balance = quantity; 26 | }); 27 | else balances.modify(iterator, same_payer, [&](auto& row){ 28 | row.balance += quantity; 29 | }); 30 | } 31 | 32 | void subBalance(const name& account, const asset& quantity){ 33 | Balances balances(_self, account.value); 34 | auto iterator = balances.find(quantity.symbol.raw()); 35 | 36 | eosio_assert(iterator != balances.end(), "No balance object"); 37 | eosio_assert(iterator->balance.amount >= quantity.amount, "overdrawn balance" ); 38 | 39 | if(iterator->balance.amount - quantity.amount <= 0){ 40 | balances.erase(iterator); 41 | } 42 | 43 | else balances.modify(iterator, same_payer, [&](auto& row){ 44 | row.balance -= quantity; 45 | }); 46 | } 47 | 48 | }; 49 | -------------------------------------------------------------------------------- /ridl_id/models/bond.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../lib/types.h" 4 | #include "../lib/common.h" 5 | using namespace types; 6 | using namespace common; 7 | 8 | using std::vector; 9 | using std::string; 10 | 11 | namespace bond { 12 | 13 | struct [[eosio::table, eosio::contract("ridlridlridl")]] Bond { 14 | uuid id; 15 | uuid identity; 16 | uuid fingerprint; 17 | string title; 18 | string details; 19 | uint64_t start_time; 20 | uint64_t expires; 21 | asset limit; 22 | asset votes; 23 | uuid fixed_party; 24 | uint8_t closed; 25 | 26 | uuid primary_key() const { return id; } 27 | uint64_t by_identity() const {return identity; } 28 | uint64_t by_fingerprint() const { return fingerprint; } 29 | 30 | static Bond create(uuid identity, string& title, string& details, uint64_t duration, uint64_t starts_in_seconds, asset& limit){ 31 | 32 | Bond bond; 33 | bond.identity = identity; 34 | bond.title = title; 35 | bond.details = details; 36 | bond.start_time = starts_in_seconds == 0 ? now() : now() + starts_in_seconds; 37 | bond.expires = now()+duration; 38 | bond.limit = limit; 39 | bond.votes = asset(0'0000, S_REP); 40 | bond.fixed_party = 0; 41 | bond.closed = 0; 42 | 43 | return bond; 44 | } 45 | 46 | bool isBusted() const { 47 | return votes.amount >= limit.amount; 48 | } 49 | 50 | bool hasFixedParty() const { 51 | return fixed_party > 0; 52 | } 53 | }; 54 | 55 | typedef eosio::multi_index<"bonds"_n, Bond, 56 | indexed_by<"identity"_n, const_mem_fun>, 57 | indexed_by<"fingerprint"_n, const_mem_fun> 58 | > Bonds; 59 | 60 | 61 | 62 | } -------------------------------------------------------------------------------- /ridl_token/ridl_token.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include 5 | 6 | namespace ridl { 7 | 8 | using namespace eosio; 9 | using std::string; 10 | 11 | static symbol SYMBOL = symbol("RIDL", 4); 12 | static int64_t MAX_SUPPLY = 1'500'000'000'0000; 13 | 14 | CONTRACT token : public contract { 15 | public: 16 | using contract::contract; 17 | 18 | ACTION create(); 19 | 20 | ACTION issue( name to, asset quantity, string memo ); 21 | 22 | ACTION transfer( name from, 23 | name to, 24 | asset quantity, 25 | string memo ); 26 | 27 | static asset get_supply( name token_contract_account, symbol_code sym_code ) 28 | { 29 | stats statstable( token_contract_account, sym_code.raw() ); 30 | const auto& st = statstable.get( sym_code.raw() ); 31 | return st.supply; 32 | } 33 | 34 | static asset get_balance( name token_contract_account, name owner, symbol_code sym_code ) 35 | { 36 | accounts accountstable( token_contract_account, owner.value ); 37 | const auto& ac = accountstable.get( sym_code.raw() ); 38 | return ac.balance; 39 | } 40 | 41 | 42 | private: 43 | TABLE account { 44 | asset balance; 45 | 46 | uint64_t primary_key()const { return balance.symbol.code().raw(); } 47 | }; 48 | 49 | TABLE currency_stats { 50 | asset supply; 51 | asset max_supply; 52 | name issuer; 53 | 54 | uint64_t primary_key()const { return supply.symbol.code().raw(); } 55 | }; 56 | 57 | typedef eosio::multi_index< "accounts"_n, account > accounts; 58 | typedef eosio::multi_index< "stat"_n, currency_stats > stats; 59 | 60 | void sub_balance( name owner, asset value ); 61 | void add_balance( name owner, asset value, name ram_payer ); 62 | 63 | public: 64 | 65 | }; 66 | 67 | } -------------------------------------------------------------------------------- /test_data.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # TEST KEY, NEVER USE ON MAINNETS 4 | # 5KNNCwxjTeCvhz5tZdcphA1RCEvSduCDkmQSVKkZTQunSD9Jfxw 5 | USER_KEY=EOS8YQzaYLxT17fWAPueQBxRjHehTQYZEvgPAWPPH4mAuwTJi3mPN 6 | ID=HelloWorld 7 | FRAG='[{"type":"social", "fingerprint":3425667939, "up":"1.0000 RIDL", "down":"0.0000 RIDL"}]' 8 | CHAIN="eos::cf057bbfb72640471fd910bcb67639c22df9f92470936cddc1ade0e2f2e7dc4f" 9 | 10 | #cleos push action ridlridlridl clean '["eosio"]' -p ridlridlridl 11 | #ridl_id/scripts/set_types.sh 12 | 13 | 14 | # TEST DATA 15 | #cleos transfer test1account ridlridlridl "1.0000 EOS" "" -p test1account 16 | #cleos transfer test1account ridlridlridl "1.0000 SYS" "" -p test1account 17 | #cleos push action ridlridlridl identify '["test1account", "HelloWorld", "'$USER_KEY'"]' -p test1account 18 | #cleos push action ridlridlridl identify '["test2account", "HelloWorld2", "'$USER_KEY'"]' -p test2account 19 | 20 | # REPUTES 21 | 22 | ################################################################## 23 | # username, id, entity, type, fragments, network, parent, details 24 | ################################################################## 25 | #cleos push action ridlridlridl repute '["'$ID'", 0, "eosio.system", "acc", '"$FRAG"', "'$CHAIN'", 0, ""]' -p test1account 26 | #cleos push action ridlridlridl repute '["'$ID'", 0, "updateauth", "act", [{"type":"dangerous", "fingerprint":118999305, "up":"0.0000 RIDL", "down":"1.0000 RIDL"}], "", 1, ""]' -p test1account 27 | #cleos push action ridlridlridl forcetype '["leadership", 1, "Born Leader", "Sheep"]' -p ridlridlridl 28 | 29 | #cleos push action ridlridlridl repute '["HelloWorld", "acc::eosio.token", [{"type":"social", "fingerprint":3425667939, "up":"1.0000 RIDL", "down":"0.0000 RIDL"}], "eos::aca376f206b8fc25a6ed44dbdc66547c36c6c33e3a119ffbeaef943642f0e906", 0, ""]' -p test1account 30 | 31 | 32 | #cleos push action ridlridlridl forcetyp`e '["leadership", "app::fortnite", "Born Leader", "Sheep"]' -p ridlridlridl 33 | #cleos push action ridlridlridl repute '["HelloWorld", "app::fortnite", [{"type":"leadership", "up":"1.0000 RIDL", "down":"0.0000 RIDL"}], ""]' -p test1account 34 | 35 | #cleos push action ridlridlcoin transfer '["test2account", "ridlridlridl", "50.0000 RIDL", ""]' -p test2account 36 | #cleos push action ridlridlridl loadtokens '["HelloWorld3", "10.0000 RIDL"]' -p test2account 37 | -------------------------------------------------------------------------------- /ridl_ibc/eosio/ridl_ibc.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | using namespace eosio; 5 | 6 | using std::string; 7 | 8 | /*** 9 | * This contract will provide decentralized user-aggregated 10 | * IBC for cross-chain RIDL reputations from the RIDL mainnet to 11 | * all other chains. 12 | * 13 | * IBC providers (anyone) will be able to gain REP by providing IBC services 14 | * to chains when running our RIDL IBC software/miner. 15 | */ 16 | 17 | CONTRACT ridlconnects : contract { 18 | public: 19 | using contract::contract; 20 | ridlconnects(name receiver, name code, datastream ds):contract(receiver, code, ds) {} 21 | 22 | ACTION clean(name scope){ 23 | require_auth(_self); 24 | 25 | print("Cleaning"); 26 | } 27 | 28 | ACTION linkprovider(name& account, asset& rep, name& custodian){ 29 | require_auth(custodian); 30 | eosio_assert(custodians.find(custodian) != custodians.end(), "This custodian is not registered with this contract."); 31 | } 32 | 33 | ACTION clonedata(name& account, string& type, vector& stringData, vector& intData64){ 34 | require_auth(account); 35 | } 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | /**********************************************/ 44 | /*** ***/ 45 | /*** Transfers ***/ 46 | /*** ***/ 47 | /**********************************************/ 48 | 49 | void transfer(const name& from, const name& to, const asset& quantity, const string& memo){ 50 | if(to != _self) return; 51 | BalanceActions(_self).addBalance(from, quantity); 52 | } 53 | 54 | }; 55 | 56 | extern "C" { 57 | void apply(uint64_t receiver, uint64_t code, uint64_t action) { 58 | auto self = receiver; 59 | 60 | if( code == self ) switch(action) { 61 | EOSIO_DISPATCH_HELPER( ridlconnects, (clean)(identify)(changekey)(changeacc)(seed)(claim)(loadtokens)(tokensloaded)(repute)(forcetype) ) 62 | } 63 | 64 | else { 65 | if(code == name("eosio.token").value && action == name("transfer").value){ 66 | execute_action(name(receiver), name(code), &ridlconnects::transfer); 67 | } 68 | 69 | if(code == name("ridlridlcoin").value && action == name("transfer").value){ 70 | execute_action(name(receiver), name(code), &ridlconnects::transfer); 71 | } 72 | } 73 | } 74 | }; -------------------------------------------------------------------------------- /ridl_id/models/identity.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../lib/types.h" 4 | #include "../lib/common.h" 5 | using namespace types; 6 | using namespace common; 7 | 8 | using std::vector; 9 | using std::string; 10 | 11 | namespace identity { 12 | 13 | struct [[eosio::table, eosio::contract("ridlridlridl")]] Identity { 14 | uuid id; 15 | uuid rep_id; 16 | uuid fingerprint; 17 | string username; 18 | public_key key; 19 | name account; 20 | uint64_t expires; 21 | asset tokens; 22 | asset expansion; 23 | asset total_rep; 24 | asset usable_rep; 25 | asset bonded; 26 | uint64_t created; 27 | uint64_t block; 28 | 29 | uuid primary_key() const { return id; } 30 | uint64_t by_account() const {return account.value; } 31 | uint64_t by_name() const {return fingerprint; } 32 | 33 | 34 | static Identity create(string& username, const public_key& key, const name& account){ 35 | lower(username); 36 | 37 | validateName(username); 38 | 39 | Identity id; 40 | id.fingerprint = toUUID(username); 41 | id.username = username; 42 | id.key = key; 43 | id.account = account; 44 | id.expires = now() + (SECONDS_PER_DAY * 365); 45 | id.expansion = asset(0'0000, S_EXP); 46 | id.total_rep = asset(0'0000, S_REP); 47 | id.usable_rep = asset(0'0000, S_REP); 48 | id.bonded = asset(0'0000, S_REP); 49 | id.created = now(); 50 | 51 | return id; 52 | } 53 | 54 | static void validateName(string& username){ 55 | string error = "Identity names must be between 3 and 20 characters, and contain only Letters, Numbers, - _ and no spaces."; 56 | eosio_assert(username.length() >= 3 && username.length() <= 20, error.c_str()); 57 | for ( char c : username ) eosio_assert(isalnum(c) || c == '-' || c == '_', error.c_str()); 58 | } 59 | 60 | void authenticate() const { 61 | require_auth(account); 62 | eosio_assert(expires > now(), "Your Identity has expired."); 63 | } 64 | }; 65 | 66 | struct [[eosio::table, eosio::contract("ridlridlridl")]] Topup { 67 | uuid fingerprint; 68 | asset tokens; 69 | uint64_t claimable; 70 | uuid primary_key() const { return fingerprint; } 71 | }; 72 | 73 | typedef eosio::multi_index<"topups"_n, Topup> Topups; 74 | 75 | 76 | typedef eosio::multi_index<"ids"_n, Identity, 77 | indexed_by<"account"_n, const_mem_fun>, 78 | indexed_by<"name"_n, const_mem_fun> 79 | > Identities; 80 | 81 | 82 | 83 | } -------------------------------------------------------------------------------- /ridl_id/lib/common.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | 4 | #include 5 | #include 6 | #include 7 | 8 | #include "types.h" 9 | using namespace types; 10 | 11 | using namespace eosio; 12 | using std::string; 13 | using std::vector; 14 | 15 | namespace common { 16 | 17 | // CONSTANTS 18 | static const symbol S_RIDL("RIDL", 4); 19 | static const symbol S_REP("REP", 4); 20 | static const symbol S_EOS("EOS", 4); 21 | static const symbol S_EXP("EXP", 4); 22 | static const checksum256 RIDL_HASH = sha256("ridl", 4); 23 | static const checksum256 NO_HASH = sha256("", 0); 24 | static const uint64_t SECONDS_PER_DAY(86400); 25 | static const uint64_t TOPUP_DELAY(600); // TODO: configure to 1 day 26 | static const uint64_t MIN_REQUIRED_REP_FOR_BONDS(500); 27 | 28 | static void prove( const signature& sig, const public_key& key ) { 29 | assert_recover_key(RIDL_HASH, sig, key); 30 | } 31 | 32 | inline static uuid toUUID(string username){ 33 | return std::hash{}(username); 34 | } 35 | 36 | void lower( string& anycase ){ 37 | std::transform(anycase.begin(), anycase.end(), anycase.begin(), ::tolower); 38 | } 39 | 40 | template 41 | void cleanTable(name self, uint64_t scope = 0){ 42 | uint64_t s = scope ? scope : self.value; 43 | T db(self, s); 44 | while(db.begin() != db.end()){ 45 | auto itr = --db.end(); 46 | db.erase(itr); 47 | } 48 | } 49 | 50 | vector splitString(const string& str, const string& delim){ 51 | vector parts; 52 | if(str.size() == 0) return parts; 53 | size_t prev = 0, pos = 0; 54 | do 55 | { 56 | pos = str.find(delim, prev); 57 | if (pos == string::npos) pos = str.length(); 58 | string token = str.substr(prev, pos-prev); 59 | if (!token.empty()) parts.push_back(token); 60 | prev = pos + delim.length(); 61 | } 62 | while (pos < str.length() && prev < str.length()); 63 | return parts; 64 | } 65 | 66 | asset ridlToRep( asset& a ){ 67 | return asset(a.amount, S_REP); 68 | } 69 | 70 | void sendRIDL(name& from, name to, asset quantity, string memo){ 71 | action( permission_level{ "ridlridlridl"_n, "active"_n }, 72 | name("ridlridlcoin"), 73 | name("transfer"), 74 | make_tuple(from, to, quantity, memo) 75 | ).send(); 76 | } 77 | 78 | void cancelDeferred(uint64_t unique_id){ 79 | // Temporary fix to cancel deferred transactions because cancelling them from the .send() 80 | // method throws an exception temporarily due to a patched but unapplied RAM exploit 81 | // https://github.com/EOSIO/eos/issues/6541 82 | cancel_deferred(unique_id); 83 | } 84 | 85 | void sendDeferred(name& _self, name action_name, uuid id, uint64_t delay_sec, uint64_t unique_id){ 86 | cancelDeferred(unique_id); 87 | 88 | transaction t; 89 | t.actions.emplace_back(action( permission_level{ _self, "active"_n }, _self, action_name, std::make_tuple(id))); 90 | t.delay_sec = delay_sec; 91 | t.send(unique_id, _self, true); 92 | } 93 | 94 | }; -------------------------------------------------------------------------------- /ridl_token/ridl_token.abi: -------------------------------------------------------------------------------- 1 | { 2 | "____comment": "This file was generated with eosio-abigen. DO NOT EDIT Wed Jan 16 11:40:08 2019", 3 | "version": "eosio::abi/1.1", 4 | "structs": [ 5 | { 6 | "name": "account", 7 | "base": "", 8 | "fields": [ 9 | { 10 | "name": "balance", 11 | "type": "asset" 12 | } 13 | ] 14 | }, 15 | { 16 | "name": "create", 17 | "base": "", 18 | "fields": [] 19 | }, 20 | { 21 | "name": "currency_stats", 22 | "base": "", 23 | "fields": [ 24 | { 25 | "name": "supply", 26 | "type": "asset" 27 | }, 28 | { 29 | "name": "max_supply", 30 | "type": "asset" 31 | }, 32 | { 33 | "name": "issuer", 34 | "type": "name" 35 | } 36 | ] 37 | }, 38 | { 39 | "name": "issue", 40 | "base": "", 41 | "fields": [ 42 | { 43 | "name": "to", 44 | "type": "name" 45 | }, 46 | { 47 | "name": "quantity", 48 | "type": "asset" 49 | }, 50 | { 51 | "name": "memo", 52 | "type": "string" 53 | } 54 | ] 55 | }, 56 | { 57 | "name": "transfer", 58 | "base": "", 59 | "fields": [ 60 | { 61 | "name": "from", 62 | "type": "name" 63 | }, 64 | { 65 | "name": "to", 66 | "type": "name" 67 | }, 68 | { 69 | "name": "quantity", 70 | "type": "asset" 71 | }, 72 | { 73 | "name": "memo", 74 | "type": "string" 75 | } 76 | ] 77 | } 78 | ], 79 | "types": [], 80 | "actions": [ 81 | { 82 | "name": "create", 83 | "type": "create", 84 | "ricardian_contract": "" 85 | }, 86 | { 87 | "name": "issue", 88 | "type": "issue", 89 | "ricardian_contract": "" 90 | }, 91 | { 92 | "name": "transfer", 93 | "type": "transfer", 94 | "ricardian_contract": "" 95 | } 96 | ], 97 | "tables": [ 98 | { 99 | "name": "accounts", 100 | "type": "account", 101 | "index_type": "i64", 102 | "key_names": [], 103 | "key_types": [] 104 | }, 105 | { 106 | "name": "stat", 107 | "type": "currency_stats", 108 | "index_type": "i64", 109 | "key_names": [], 110 | "key_types": [] 111 | } 112 | ], 113 | "ricardian_clauses": [], 114 | "variants": [], 115 | "abi_extensions": [] 116 | } -------------------------------------------------------------------------------- /ridl_token/ridl_token.cpp: -------------------------------------------------------------------------------- 1 | #include "ridl_token.hpp" 2 | 3 | namespace ridl { 4 | 5 | void token::create(){ 6 | require_auth( _self ); 7 | 8 | name issuer = _self; 9 | asset maximum_supply = asset(ridl::MAX_SUPPLY, ridl::SYMBOL); 10 | 11 | stats statstable( _self, maximum_supply.symbol.code().raw() ); 12 | auto existing = statstable.find( maximum_supply.symbol.code().raw() ); 13 | eosio_assert( existing == statstable.end(), "token with symbol already exists" ); 14 | 15 | statstable.emplace( _self, [&]( auto& s ) { 16 | s.supply.symbol = maximum_supply.symbol; 17 | s.max_supply = maximum_supply; 18 | s.issuer = issuer; 19 | }); 20 | 21 | SEND_INLINE_ACTION( *this, issue, {_self,"active"_n}, {"scatterfunds"_n, asset( 250'000'000'0000, ridl::SYMBOL ), "Development Fund"} ); 22 | SEND_INLINE_ACTION( *this, issue, {_self,"active"_n}, {"ridlridlridl"_n, asset( 500'000'000'0000, ridl::SYMBOL ), "RIDL Token Reserve"} ); 23 | } 24 | 25 | 26 | void token::issue( name to, asset quantity, string memo ) 27 | { 28 | auto sym = quantity.symbol; 29 | eosio_assert( sym.is_valid(), "invalid symbol name" ); 30 | eosio_assert( memo.size() <= 256, "memo has more than 256 bytes" ); 31 | 32 | stats statstable( _self, sym.code().raw() ); 33 | auto existing = statstable.find( sym.code().raw() ); 34 | eosio_assert( existing != statstable.end(), "token with symbol does not exist, create token before issue" ); 35 | const auto& st = *existing; 36 | 37 | require_auth( st.issuer ); 38 | eosio_assert( quantity.is_valid(), "invalid quantity" ); 39 | eosio_assert( quantity.amount > 0, "must issue positive quantity" ); 40 | 41 | eosio_assert( quantity.symbol == st.supply.symbol, "symbol precision mismatch" ); 42 | eosio_assert( quantity.amount <= st.max_supply.amount - st.supply.amount, "quantity exceeds available supply"); 43 | 44 | statstable.modify( st, same_payer, [&]( auto& s ) { 45 | s.supply += quantity; 46 | }); 47 | 48 | add_balance( st.issuer, quantity, st.issuer ); 49 | 50 | if( to != st.issuer ) { 51 | SEND_INLINE_ACTION( *this, transfer, { {st.issuer, "active"_n} }, 52 | { st.issuer, to, quantity, memo } 53 | ); 54 | } 55 | } 56 | 57 | void token::transfer( name from, 58 | name to, 59 | asset quantity, 60 | string memo ) 61 | { 62 | eosio_assert( from != to, "cannot transfer to self" ); 63 | require_auth( from ); 64 | eosio_assert( is_account( to ), "to account does not exist"); 65 | auto sym = quantity.symbol.code(); 66 | stats statstable( _self, sym.raw() ); 67 | const auto& st = statstable.get( sym.raw() ); 68 | 69 | require_recipient( from ); 70 | require_recipient( to ); 71 | 72 | eosio_assert( quantity.is_valid(), "invalid quantity" ); 73 | eosio_assert( quantity.amount > 0, "must transfer positive quantity" ); 74 | eosio_assert( quantity.symbol == st.supply.symbol, "symbol precision mismatch" ); 75 | eosio_assert( memo.size() <= 256, "memo has more than 256 bytes" ); 76 | 77 | auto payer = has_auth( to ) ? to : from; 78 | 79 | sub_balance( from, quantity ); 80 | add_balance( to, quantity, payer ); 81 | } 82 | 83 | void token::sub_balance( name owner, asset value ) { 84 | accounts from_acnts( _self, owner.value ); 85 | 86 | const auto& from = from_acnts.get( value.symbol.code().raw(), "no balance object found" ); 87 | eosio_assert( from.balance.amount >= value.amount, "overdrawn balance" ); 88 | 89 | from_acnts.modify( from, owner, [&]( auto& a ) { 90 | a.balance -= value; 91 | }); 92 | } 93 | 94 | void token::add_balance( name owner, asset value, name ram_payer ) 95 | { 96 | accounts to_acnts( _self, owner.value ); 97 | auto to = to_acnts.find( value.symbol.code().raw() ); 98 | if( to == to_acnts.end() ) { 99 | to_acnts.emplace( ram_payer, [&]( auto& a ){ 100 | a.balance = value; 101 | }); 102 | } else { 103 | to_acnts.modify( to, same_payer, [&]( auto& a ) { 104 | a.balance += value; 105 | }); 106 | } 107 | } 108 | 109 | 110 | } 111 | 112 | EOSIO_DISPATCH( ridl::token, (create)(issue)(transfer) ) -------------------------------------------------------------------------------- /ridl_id/models/reputable.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../lib/types.h" 4 | #include "../lib/common.h" 5 | #include "./identity.h" 6 | #include "./reputation.h" 7 | using namespace types; 8 | using namespace common; 9 | using namespace reputation; 10 | using namespace identity; 11 | 12 | using std::vector; 13 | using std::string; 14 | using std::optional; 15 | 16 | namespace reputable { 17 | 18 | /*********************************/ 19 | /* MINER FRAGS */ 20 | /*********************************/ 21 | struct [[eosio::table, eosio::contract("ridlridlridl")]] MinerFrag { 22 | uuid identity; 23 | uint64_t miner_til; 24 | uuid fingerprint; 25 | uint8_t positive; 26 | 27 | uuid primary_key() const { return fingerprint; } 28 | uuid by_identity() const { return identity; } 29 | 30 | bool expired() const { 31 | return miner_til <= now(); 32 | } 33 | 34 | static MinerFrag create(Identities::const_iterator& identity, ReputationFragment& frag){ 35 | MinerFrag m; 36 | m.identity = identity->id; 37 | m.miner_til = now() + (SECONDS_PER_DAY * 30); 38 | m.fingerprint = frag.fingerprint; 39 | m.positive = frag.isPositive(); 40 | return m; 41 | } 42 | }; 43 | 44 | typedef eosio::multi_index<"minerfrags"_n, MinerFrag, 45 | indexed_by<"identity"_n, const_mem_fun> 46 | > MinerFrags; 47 | 48 | 49 | 50 | /*********************************/ 51 | /* REPUTABLES */ 52 | /*********************************/ 53 | void validateEntity(string& type, string& entity){ 54 | vector entityTypes = vector{"app", "acc", "act", "id", "etc"}; 55 | 56 | eosio_assert(std::find(entityTypes.begin(), entityTypes.end(), type) != entityTypes.end(), "Invalid Entity Type"); 57 | eosio_assert(entity.size() > 0, "Invalid entity"); 58 | } 59 | 60 | void validateNetwork(string& network, string& type){ 61 | eosio_assert(network.size() == 0 || type == "acc", "Only accounts/addresses/contracts can have a network ID"); 62 | eosio_assert(network.size() == 0 || network.find("::", 0) != std::string::npos, "Invalid Network ID. Networks must be in the following format: [blockchain::chain_id]"); 63 | } 64 | 65 | struct [[eosio::table, eosio::contract("ridlridlridl")]] Reputable { 66 | uint64_t id; 67 | string type; 68 | string entity; 69 | uuid base; 70 | uuid fingerprint; 71 | 72 | name last_reputer; 73 | uint64_t last_repute_time; 74 | name owner; 75 | string network; 76 | 77 | uint64_t block; 78 | 79 | uuid primary_key() const { return id; } 80 | uuid by_name() const { return toUUID(entity); } 81 | uint64_t by_fingerprint() const { return fingerprint; } 82 | uint64_t by_base() const { return base; } 83 | uint64_t by_owner() const { return owner.value; } 84 | 85 | void merge( const Reputable& r ){ 86 | id = r.id; 87 | last_reputer = r.last_reputer; 88 | last_repute_time = r.last_repute_time; 89 | owner = r.owner; 90 | network = r.network; 91 | } 92 | 93 | static Reputable create(string& entity, string type, string network, uuid base){ 94 | lower(entity); 95 | 96 | Reputable r; 97 | r.type = type; 98 | r.entity = entity; 99 | r.network = network; 100 | r.base = base; 101 | r.fingerprint = toUUID(type+entity+network+std::to_string(base)); 102 | 103 | validateEntity(r.type, r.entity); 104 | validateNetwork(r.network, r.type); 105 | if(r.type == "id") eosio_assert(base == 0, "Identity reputes can not be tiered."); 106 | 107 | return r; 108 | } 109 | }; 110 | 111 | 112 | 113 | 114 | typedef eosio::multi_index<"reputables"_n, Reputable, 115 | indexed_by<"name"_n, const_mem_fun>, 116 | indexed_by<"fingerprint"_n, const_mem_fun>, 117 | indexed_by<"base"_n, const_mem_fun>, 118 | indexed_by<"owner"_n, const_mem_fun> 119 | // indexed_by<"miner"_n, const_mem_fun> 120 | > Reputables; 121 | 122 | 123 | 124 | }; -------------------------------------------------------------------------------- /ridl_id/models/reputation.h: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include "../lib/types.h" 4 | #include "../lib/common.h" 5 | 6 | using namespace types; 7 | using namespace common; 8 | 9 | using std::string; 10 | 11 | namespace reputation { 12 | 13 | 14 | 15 | struct ReputationFragment { 16 | uuid fingerprint; 17 | string type; 18 | asset up; 19 | asset down; 20 | 21 | void assertValid(){ 22 | eosio_assert(up.symbol == S_RIDL, "Reputes must be paid in RIDL"); 23 | eosio_assert(down.symbol == S_RIDL, "Reputes must be paid in RIDL"); 24 | eosio_assert(up.is_valid(), "Token asset is not valid"); 25 | eosio_assert(down.is_valid(), "Token asset is not valid"); 26 | eosio_assert(up.amount > 0 || down.amount > 0, "All reputation fragments must have either a positive or negative value"); 27 | eosio_assert(up.amount == 0 || down.amount == 0, "Reputation fragments cannot have both positive and negative values"); 28 | } 29 | 30 | bool isPositive(){ 31 | return up.amount > 0; 32 | } 33 | 34 | bool matches( bool& otherIsUp ){ 35 | return (isPositive() > 0 && otherIsUp) 36 | || (!isPositive() > 0 && !otherIsUp); 37 | } 38 | 39 | void toRepFrag(){ 40 | up = ridlToRep(up); 41 | down = ridlToRep(down); 42 | } 43 | }; 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | struct [[eosio::table, eosio::contract("ridlridlridl")]] RepType { 52 | uuid fingerprint; 53 | string type; 54 | uuid base; 55 | string upTag; 56 | string downTag; 57 | 58 | uuid primary_key() const { return fingerprint; } 59 | uuid by_base() const { return base; } 60 | 61 | static RepType create(string& type, string& upTag, string& downTag, uuid& base){ 62 | lower(type); 63 | lower(upTag); 64 | lower(downTag); 65 | 66 | RepType t; 67 | t.fingerprint = toUUID(base == 0 ? type : std::to_string(base)+type); 68 | t.type = type; 69 | t.base = base; 70 | t.upTag = upTag.size() == 0 ? "good" : upTag; 71 | t.downTag = downTag.size() == 0 ? "bad" : downTag; 72 | 73 | return t; 74 | } 75 | }; 76 | 77 | struct [[eosio::table, eosio::contract("ridlridlridl")]] VotableRepType { 78 | RepType repType; 79 | vector up; 80 | vector down; 81 | 82 | uuid primary_key() const { return repType.fingerprint; } 83 | uuid by_base() const { return repType.base; } 84 | }; 85 | 86 | struct [[eosio::table, eosio::contract("ridlridlridl")]] Reputation { 87 | uuid id; 88 | vector fragments; 89 | int64_t total_reputes; 90 | 91 | void mergeRepute( std::vector& frags ){ 92 | for( auto& frag : frags ){ 93 | string type = frag.type; 94 | frag.toRepFrag(); 95 | 96 | // Frag exists 97 | auto found = std::find_if( 98 | fragments.begin(), 99 | fragments.end(), 100 | [type](const ReputationFragment & f) -> bool 101 | { return f.type == type; } 102 | ); 103 | 104 | if(found != fragments.end()){ 105 | found->up += frag.up; 106 | found->down += frag.down; 107 | } 108 | 109 | // Frag does not exist 110 | else fragments.push_back(frag); 111 | } 112 | } 113 | }; 114 | 115 | struct [[eosio::table, eosio::contract("ridlridlridl")]] FragTotal { 116 | uuid fingerprint; 117 | string type; 118 | asset up; 119 | asset down; 120 | }; 121 | 122 | 123 | 124 | 125 | 126 | static Reputation createReputation(uuid id){ 127 | Reputation r; 128 | r.id = id; 129 | r.total_reputes = 0; 130 | return r; 131 | } 132 | 133 | static FragTotal createFragTotal(string& type){ 134 | lower(type); 135 | FragTotal f; 136 | f.fingerprint = toUUID(type); 137 | f.type = type; 138 | f.up = asset(0'0000, S_REP); 139 | f.down = asset(0'0000, S_REP); 140 | return f; 141 | } 142 | 143 | 144 | typedef eosio::multi_index<"votetypes"_n, VotableRepType, 145 | indexed_by<"base"_n, const_mem_fun>> 146 | VotableRepTypes; 147 | 148 | typedef eosio::multi_index<"reptypes"_n, RepType, 149 | indexed_by<"base"_n, const_mem_fun>> 150 | ReputationTypes; 151 | 152 | 153 | typedef eosio::singleton<"reputations"_n, Reputation> Reputations; 154 | typedef eosio::singleton<"fragtotal"_n, FragTotal> FragTotals; 155 | 156 | 157 | // Temp fix for issue with singletons not getting proper names 158 | typedef eosio::multi_index<"reputations"_n, Reputation> Reputations_alias; 159 | typedef eosio::multi_index<"fragtotal"_n, FragTotal> FragTotals_alias; 160 | } 161 | -------------------------------------------------------------------------------- /ridl_id/actions/bond_actions.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "../models/bond.h" 5 | #include "../models/identity.h" 6 | 7 | using namespace eosio; 8 | using namespace bond; 9 | using namespace identity; 10 | 11 | using std::string; 12 | using std::vector; 13 | using std::make_tuple; 14 | 15 | class BondActions { 16 | private: 17 | name _self; 18 | Bonds bonds; 19 | Identities identities; 20 | 21 | auto findIdentity(string& username){ 22 | lower(username); 23 | auto index = identities.get_index<"name"_n>(); 24 | auto found = index.find(toUUID(username)); 25 | eosio_assert(found != index.end(), ("Could not find username: "+username).c_str()); 26 | return identities.find(found->id); 27 | } 28 | 29 | public: 30 | BondActions(name self):_self(self), 31 | bonds(_self, _self.value), 32 | identities(_self, _self.value){} 33 | 34 | // TODO: Add specific collateral bonds with asset transfers in IBC contracts 35 | 36 | void create(string& username, string& title, string& details, uint64_t duration, uint64_t starts_in_seconds, asset& limit, uuid& fixed_party){ 37 | /////////////////////////////////// 38 | // Identity verification 39 | auto identity = findIdentity(username); 40 | eosio_assert(identity != identities.end(), "Identity does not exist"); 41 | identity->authenticate(); 42 | 43 | eosio_assert(limit.amount >= 1, "You must use at least 1.0000 REP to create a bond."); 44 | canUseBonds(identity, limit.amount); 45 | 46 | Bond bond = Bond::create(identity->id, title, details, duration, starts_in_seconds, limit); 47 | 48 | eosio_assert(bond.expires < identity->expires, "Bonds can not expire after your identity expires."); 49 | 50 | bond.id = bonds.available_primary_key(); 51 | if(fixed_party > 0) bond.fixed_party = fixed_party; 52 | bond.fingerprint = toUUID(title+details+username+limit.to_string()+std::to_string(fixed_party)); 53 | 54 | auto index = bonds.get_index<"fingerprint"_n>(); 55 | eosio_assert(index.find(bond.fingerprint) == index.end(), "There is already an identical bond for this identity."); 56 | 57 | bonds.emplace(identity->account, [&](auto& row){ row = bond; }); 58 | 59 | sendDeferred(_self, name("closebond"), bond.id, duration+1, bond.id); 60 | } 61 | 62 | void disputebond(string& username, uuid& bond_id, asset rep){ 63 | eosio_assert(rep.amount > 0, "You must use at least 0.0001 REP to dispute a bond."); 64 | /////////////////////////////////// 65 | // Identity verification 66 | auto identity = findIdentity(username); 67 | eosio_assert(identity != identities.end(), "Identity does not exist"); 68 | identity->authenticate(); 69 | 70 | auto bond = bonds.find(bond_id); 71 | eosio_assert(bond != bonds.end(), ("There is no bond with the ID: "+std::to_string(bond_id)).c_str()); 72 | eosio_assert(bond->closed == 0, "This bond has already closed."); 73 | eosio_assert(bond->start_time >= now(), "This bond has already expired."); 74 | eosio_assert(bond->expires >= now(), "This bond has already expired."); 75 | eosio_assert(bond->votes < bond->limit, "This bond has already reached max votes."); 76 | eosio_assert(bond->fixed_party == 0 || bond->fixed_party == identity->id, "You are not allowed to vote on this bond."); 77 | eosio_assert(bond->identity != identity->id, "You are not allowed to vote on your own bonds."); 78 | 79 | asset repNeeded = asset(bond->limit.amount - bond->votes.amount, S_REP); 80 | 81 | // Not using more than needed to close out bond. 82 | if(rep.amount > repNeeded.amount) rep.amount = repNeeded.amount; 83 | 84 | canUseBonds(identity, rep.amount); 85 | 86 | bonds.modify(bond, same_payer, [&](auto& row){ row.votes += rep; }); 87 | identities.modify(identity, same_payer, [&](auto& row){ row.usable_rep -= rep; }); 88 | 89 | // Closing out the bond if reached limit 90 | if(bond->votes.amount + rep.amount >= bond->votes.amount){ 91 | closebond(bond_id); 92 | cancelDeferred(bond->fingerprint); 93 | } 94 | } 95 | 96 | void closebond(uuid& bond_id){ 97 | auto bond = bonds.find(bond_id); 98 | eosio_assert(bond != bonds.end(), ("There is no bond with the ID: "+std::to_string(bond_id)).c_str()); 99 | eosio_assert(bond->expires <= now() || bond->votes >= bond->limit, "This bond has not expired or reached its limit yet."); 100 | eosio_assert(bond->closed == 0, "This bond is already closed."); 101 | 102 | auto identity = identities.find(bond->identity); 103 | eosio_assert(identity != identities.end(), "Identity no longer exists"); 104 | 105 | bonds.modify(bond, same_payer, [&](auto& row){ 106 | row.closed = 1; 107 | }); 108 | 109 | identities.modify(identity, same_payer, [&](auto& row){ 110 | row.bonded -= bond->limit; 111 | 112 | if (bond->isBusted()) { 113 | row.usable_rep -= bond->limit; 114 | 115 | if(bond->hasFixedParty()){ 116 | auto party = identities.find(bond->fixed_party); 117 | if(party != identities.end()){ 118 | identities.modify(party, same_payer, [&](auto& prow){ 119 | prow.usable_rep += bond->limit; 120 | }); 121 | } 122 | } 123 | } 124 | }); 125 | } 126 | 127 | void erasebond(uuid& bond_id){ 128 | auto bond = bonds.find(bond_id); 129 | eosio_assert(bond != bonds.end(), ("There is no bond with the ID: "+std::to_string(bond_id)).c_str()); 130 | eosio_assert(bond->closed == 1, "Bond must be closed first."); 131 | 132 | /////////////////////////////////// 133 | // Identity verification 134 | auto identity = identities.find(bond->identity); 135 | eosio_assert(identity != identities.end(), "Bond owning identity no longer exists"); 136 | identity->authenticate(); 137 | 138 | bonds.erase(bond); 139 | } 140 | 141 | void cancelbond(string& username, uuid& bond_id){ 142 | /////////////////////////////////// 143 | // Identity verification 144 | auto identity = findIdentity(username); 145 | eosio_assert(identity != identities.end(), "Identity does not exist"); 146 | identity->authenticate(); 147 | 148 | auto bond = bonds.find(bond_id); 149 | eosio_assert(bond != bonds.end(), ("There is no bond with the ID: "+std::to_string(bond_id)).c_str()); 150 | eosio_assert(bond->fixed_party == identity->id, "You are not the trustee of this bond."); 151 | 152 | auto bonder = identities.find(bond->identity); 153 | eosio_assert(bonder != identities.end(), "The bonded identity no longer exists"); 154 | 155 | identities.modify(bonder, same_payer, [&](auto& row){ 156 | row.bonded -= bond->limit; 157 | 158 | if(bond->votes.amount > 0){ 159 | identities.modify(identity, same_payer, [&](auto& prow){ 160 | prow.usable_rep += bond->votes; 161 | }); 162 | } 163 | }); 164 | 165 | bonds.erase(bond); 166 | } 167 | 168 | private: 169 | 170 | void canUseBonds(Identities::const_iterator& identity, uint64_t minimum){ 171 | eosio_assert(identity->created+(SECONDS_PER_DAY*30) <= now(), "Identities can only vote on bonds 30 days after registration."); 172 | eosio_assert(identity->usable_rep.amount >= MIN_REQUIRED_REP_FOR_BONDS, ("You need at least "+std::to_string(MIN_REQUIRED_REP_FOR_BONDS)+" available REP to create a bond.").c_str()); 173 | eosio_assert(identity->usable_rep.amount - identity->bonded.amount >= minimum, 174 | ("You do not have enough unbonded REP to vote on this bond. Only "+ 175 | std::to_string(identity->usable_rep.amount - identity->bonded.amount)+ 176 | " left but "+std::to_string(minimum)+" is needed.").c_str()); 177 | } 178 | 179 | }; 180 | -------------------------------------------------------------------------------- /ridl_id/ridl_id.cpp: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | 5 | #include "lib/common.h" 6 | #include "models/identity.h" 7 | #include "models/balances.h" 8 | #include "models/bond.h" 9 | #include "models/reputable.h" 10 | 11 | 12 | #include "actions/balance_actions.hpp" 13 | #include "actions/identity_actions.hpp" 14 | #include "actions/reputation_actions.hpp" 15 | #include "actions/bond_actions.hpp" 16 | 17 | 18 | using namespace eosio; 19 | using namespace identity; 20 | using namespace common; 21 | using namespace balances; 22 | using namespace bond; 23 | using namespace reputable; 24 | 25 | using std::string; 26 | 27 | CONTRACT ridlridlridl : contract { 28 | public: 29 | using contract::contract; 30 | ridlridlridl(name receiver, name code, datastream ds):contract(receiver, code, ds) {} 31 | 32 | /*** 33 | * // TODO: TESTING ONLY 34 | * ADMIN ONLY - Cleans all the tables 35 | */ 36 | ACTION clean(name scope){ 37 | require_auth(_self); 38 | 39 | print("Cleaning"); 40 | 41 | ReputationTypes reputationTypes(_self, _self.value); 42 | while(reputationTypes.begin() != reputationTypes.end()){ 43 | auto iter = --reputationTypes.end(); 44 | string type = iter->type; 45 | FragTotals(_self, toUUID(type)).remove(); 46 | reputationTypes.erase(iter); 47 | } 48 | 49 | Reputables reputables(_self,_self.value); 50 | while(reputables.begin() != reputables.end()){ 51 | auto iter = --reputables.end(); 52 | Reputations(_self, iter->id).remove(); 53 | cleanTable(_self, iter->id); 54 | cleanTable(_self, iter->id); 55 | 56 | reputables.erase(iter); 57 | } 58 | 59 | cleanTable(_self, _self.value); 60 | cleanTable(_self, _self.value); 61 | cleanTable(_self, scope.value); 62 | // cleanTable(_self); 63 | } 64 | 65 | 66 | 67 | 68 | 69 | 70 | /**********************************************/ 71 | /*** ***/ 72 | /*** Identities ***/ 73 | /*** ***/ 74 | /**********************************************/ 75 | 76 | /*** 77 | * Registers an identity for a given account and name 78 | * @param account 79 | * @param username 80 | * @param key 81 | * @return 82 | */ 83 | ACTION identify(const name& account, string& username, const public_key& key){ 84 | IdentityActions(_self).identify(account, username, key); 85 | } 86 | 87 | /*** 88 | * Changes the identity's public key 89 | * @param username 90 | * @param key 91 | * @return 92 | */ 93 | ACTION changekey(string& username, const public_key& key){ 94 | IdentityActions(_self).changekey(username, key); 95 | } 96 | 97 | /*** 98 | * Changes the identity's linked account 99 | * @param username 100 | * @param key 101 | * @return 102 | */ 103 | ACTION changeacc(string& username, name& account){ 104 | IdentityActions(_self).changeacc(username, account); 105 | } 106 | 107 | /*** 108 | * ADMIN ONLY - Adds a reserved identity to the table 109 | * @param username 110 | * @param key 111 | * @return 112 | */ 113 | ACTION seed(string& username, const public_key& key){ 114 | IdentityActions(_self).seed(username, key); 115 | } 116 | 117 | /*** 118 | * Claims a reserved identity 119 | * @param account 120 | * @param username 121 | * @param key 122 | * @param sig 123 | * @return 124 | */ 125 | ACTION claim(const name& account, string& username, const public_key& key, const signature& sig){ 126 | IdentityActions(_self).claim(account, username, key, sig); 127 | } 128 | 129 | /*** 130 | * Loads tokens into an identity 131 | * @param username 132 | * @param tokens 133 | * @return 134 | */ 135 | ACTION loadtokens(string& username, const asset& tokens){ 136 | IdentityActions(_self).loadtokens(username, tokens); 137 | } 138 | 139 | /*** 140 | * Fallback for claiming topup 141 | * @param username 142 | * @return 143 | */ 144 | ACTION tokensloaded(uuid& identity_id){ 145 | IdentityActions(_self).tokensloaded(identity_id); 146 | } 147 | 148 | 149 | 150 | 151 | /**********************************************/ 152 | /*** ***/ 153 | /*** Bonds ***/ 154 | /*** ***/ 155 | /**********************************************/ 156 | 157 | /*** 158 | * Creates a bond 159 | * @param username 160 | * @param title 161 | * @param details 162 | * @param duration 163 | * @param starts_in_seconds 164 | * @param limit 165 | * @param fixed_party 166 | * @return 167 | */ 168 | ACTION createbond(string& username, string& title, string& details, uint64_t duration, uint64_t starts_in_seconds, asset& limit, uuid& fixed_party){ 169 | BondActions(_self).create(username, title, details, duration, starts_in_seconds, limit, fixed_party); 170 | } 171 | 172 | /*** 173 | * Votes on a bond 174 | * @param username 175 | * @param bond_id 176 | * @param rep 177 | * @return 178 | */ 179 | ACTION disputebond(string& username, uuid& bond_id, asset rep){ 180 | BondActions(_self).disputebond(username, bond_id, rep); 181 | } 182 | 183 | /*** 184 | * Allows a fixed_party to cancel a bond for the bonder 185 | * @param username 186 | * @param bond_id 187 | * @return 188 | */ 189 | ACTION cancelbond(string& username, uuid& bond_id){ 190 | BondActions(_self).cancelbond(username, bond_id); 191 | } 192 | 193 | /*** 194 | * Closes a limit reached or expired bond 195 | * !! CALLED FROM DEFERRED OR FALLBACK !! 196 | * @param bond_id 197 | * @return 198 | */ 199 | ACTION closebond(uuid& bond_id){ 200 | BondActions(_self).closebond(bond_id); 201 | } 202 | 203 | /*** 204 | * Erases a closed bond 205 | * @param bond_id 206 | * @return 207 | */ 208 | ACTION erasebond(uuid& bond_id){ 209 | BondActions(_self).erasebond(bond_id); 210 | } 211 | 212 | 213 | 214 | /**********************************************/ 215 | /*** ***/ 216 | /*** Reputation ***/ 217 | /*** ***/ 218 | /**********************************************/ 219 | 220 | /*** 221 | * Reputes an entity from a registered identity 222 | * @param username 223 | * @param id 224 | * @param entity 225 | * @param type 226 | * @param fragments 227 | * @param network 228 | * @param parent 229 | * @param details 230 | * @return 231 | */ 232 | ACTION repute(string& username, uuid& id, string& entity, string& type, vector& fragments, string& network, string& parent, string& details){ 233 | ReputationActions(_self).repute(username, id, entity, type, fragments, network, parent); 234 | } 235 | 236 | /*** 237 | * Votes a RepType into the database. 238 | * @param username - Voter's identity name 239 | * @param type - Type name 240 | * @param parent (optional) - Entity fingerprint 241 | * @param upTag (optional) 242 | * @param downTag (optional) 243 | * @return 244 | */ 245 | // TODO: Need to implement decentralized voting on rep types 246 | // ACTION votetype(string& username, string& type, string& parent, string& upTag, string& downTag){ 247 | // ReputationActions(_self).votetype(username, type, parent, upTag, downTag); 248 | // } 249 | 250 | 251 | /*** 252 | * ADMIN ONLY - Forces rep types into the table 253 | * @param type - Type name 254 | * @param parent (optional) - Entity fingerprint 255 | * @param upTag (optional) 256 | * @param downTag (optional) 257 | * @return 258 | */ 259 | ACTION forcetype(string& type, uuid& parent, string& upTag, string& downTag){ 260 | ReputationActions(_self).forcetype(type,parent,upTag,downTag); 261 | } 262 | 263 | 264 | 265 | 266 | 267 | /**********************************************/ 268 | /*** ***/ 269 | /*** Transfers ***/ 270 | /*** ***/ 271 | /**********************************************/ 272 | 273 | void transfer(const name& from, const name& to, const asset& quantity, const string& memo){ 274 | if(to != _self) return; 275 | BalanceActions(_self).addBalance(from, quantity); 276 | } 277 | 278 | }; 279 | 280 | extern "C" { 281 | void apply(uint64_t receiver, uint64_t code, uint64_t action) { 282 | auto self = receiver; 283 | 284 | if( code == self ) switch(action) { 285 | EOSIO_DISPATCH_HELPER( ridlridlridl, (clean)(identify)(changekey)(changeacc)(seed)(claim)(loadtokens)(tokensloaded)(createbond)(disputebond)(cancelbond)(closebond)(erasebond)(repute)(forcetype) ) 286 | } 287 | 288 | else { 289 | if(code == name("eosio.token").value && action == name("transfer").value){ 290 | execute_action(name(receiver), name(code), &ridlridlridl::transfer); 291 | } 292 | 293 | if(code == name("ridlridlcoin").value && action == name("transfer").value){ 294 | execute_action(name(receiver), name(code), &ridlridlridl::transfer); 295 | } 296 | } 297 | } 298 | }; -------------------------------------------------------------------------------- /ridl_id/actions/identity_actions.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "../models/identity.h" 5 | #include "../models/reputation.h" 6 | #include "../models/reputable.h" 7 | #include "../models/bond.h" 8 | #include "../../ridl_token/ridl_token.hpp" 9 | 10 | #include "./balance_actions.hpp" 11 | 12 | using namespace eosio; 13 | using namespace identity; 14 | using namespace reputable; 15 | using namespace reputation; 16 | using namespace bond; 17 | 18 | class IdentityActions { 19 | 20 | private: 21 | name _self; 22 | Identities identities; 23 | Reputables reputables; 24 | Bonds bonds; 25 | Topups topups; 26 | 27 | auto findIdentity(string& username){ 28 | lower(username); 29 | auto index = identities.get_index<"name"_n>(); 30 | auto found = index.find(toUUID(username)); 31 | eosio_assert(found != index.end(), ("Could not find username: "+username).c_str()); 32 | return identities.find(found->id); 33 | } 34 | 35 | public: 36 | IdentityActions(name self):_self(self), 37 | identities(_self, _self.value), 38 | reputables(_self, _self.value), 39 | bonds(_self, _self.value), 40 | topups(_self, _self.value) {} 41 | 42 | // Identifies a new user or re-registers an existing user 43 | void identify(const name& account, string& username, const public_key& key){ 44 | require_auth(account); 45 | 46 | // TODO: calc price from oracle/configs 47 | asset price(1'0000, S_EOS); 48 | 49 | // Constructing new identity 50 | Identity identity = Identity::create(username, key, account); 51 | 52 | // Set Identity 53 | createOrUpdateIdentity(identity); 54 | 55 | BalanceActions(_self).subBalance(account, price); 56 | // 57 | // string f = "user::"+username; 58 | // uuid repFingerprint = toUUID(f); 59 | // 60 | // asset repTotal = RepTotal(_self, repFingerprint).get_or_default(asset(0'0000, S_REP)); 61 | // RepTotal(_self, repFingerprint).set(repTotal, account); 62 | 63 | 64 | } 65 | 66 | 67 | void changekey(string& username, const public_key& key){ 68 | auto identity = findIdentity(username); 69 | eosio_assert(identity != identities.end(), "Identity does not exist"); 70 | identity->authenticate(); 71 | 72 | identities.modify(identity, _self, [&](auto& record){ 73 | record.key = key; 74 | }); 75 | } 76 | 77 | 78 | void changeacc(string& username, name& account){ 79 | eosio_assert(account != _self, "Can't reset account to ridlridlridl"); 80 | auto identity = findIdentity(username); 81 | eosio_assert(identity != identities.end(), "Identity does not exist"); 82 | identity->authenticate(); 83 | 84 | identities.modify(identity, _self, [&](auto& record){ 85 | record.account = account; 86 | }); 87 | } 88 | 89 | 90 | void seed(string& username, const public_key& key){ 91 | require_auth(_self); 92 | 93 | Identity identity = Identity::create(username, key, _self); 94 | identity.expires = now() + ((SECONDS_PER_DAY * 365) * 100); 95 | 96 | auto index = identities.get_index<"name"_n>(); 97 | auto found = index.find(toUUID(username)); 98 | eosio_assert(found == index.end(), "This identity is already seeded."); 99 | 100 | createOrUpdateIdentity(identity, 100'0000); 101 | } 102 | 103 | 104 | void claim(const name& account, string& username, const public_key& key, const signature& sig){ 105 | require_auth(account); 106 | 107 | auto identity = findIdentity(username); 108 | eosio_assert(identity != identities.end(), "Identity not seeded."); 109 | eosio_assert(identity->account == _self, "Identity already owned."); 110 | 111 | // Proving ownership of public key 112 | common::prove(sig, key); 113 | 114 | identities.modify(identity, _self, [&](auto& record){ 115 | record.account = account; 116 | record.key = key; 117 | }); 118 | } 119 | 120 | void loadtokens(string& username, const asset& tokens){ 121 | eosio_assert(tokens.symbol == S_RIDL, "Can only load RIDL tokens into an identity."); 122 | 123 | auto identity = findIdentity(username); 124 | eosio_assert(identity != identities.end(), "Cannot transfer RIDL tokens to an Identity that does not exist"); 125 | identity->authenticate(); 126 | 127 | auto existing = topups.find(identity->fingerprint); 128 | 129 | asset maxCanHold = asset(100'0000 + (identity->usable_rep.amount > 0 ? identity->total_rep.amount : 0) + (identity->expansion.amount > 0 ? identity->expansion.amount : 0), S_RIDL); 130 | asset total = tokens + identity->tokens; 131 | if(existing != topups.end()) total += existing->tokens; 132 | asset remaining = tokens; 133 | 134 | // Too much was spent, sending the overage back 135 | if(total > maxCanHold){ 136 | asset refunded = total - maxCanHold; 137 | remaining = remaining - refunded; 138 | sendRIDL(_self, identity->account, refunded, "RIDL overload refund"); 139 | } 140 | 141 | eosio_assert(remaining.amount > 0, "Identity is already holding it's maximum RIDL capacity."); 142 | BalanceActions(_self).subBalance(identity->account, tokens); 143 | 144 | if(existing == topups.end()){ 145 | topups.emplace(_self, [&](auto& row){ 146 | row.fingerprint = identity->fingerprint; 147 | row.tokens = remaining; 148 | row.claimable = now() + TOPUP_DELAY; 149 | }); 150 | } else { 151 | topups.modify(existing, same_payer, [&](auto& row){ 152 | row.tokens += remaining; 153 | row.claimable = now() + TOPUP_DELAY; 154 | }); 155 | } 156 | 157 | sendDeferred(_self, name("tokensloaded"), identity->id, TOPUP_DELAY, identity->fingerprint); 158 | } 159 | 160 | void tokensloaded(uuid& identity_id){ 161 | auto identity = identities.find(identity_id); 162 | eosio_assert(identity != identities.end(), "An Identity with that name does not exist."); 163 | 164 | auto topup = topups.find(identity->fingerprint); 165 | eosio_assert(topup != topups.end(), "There is no pending topup for this Identity."); 166 | eosio_assert(topup->claimable >= now(), "This Identity's topup is not yet available for use."); 167 | 168 | identities.modify(identity, _self, [&](auto& record){ 169 | record.tokens += topup->tokens; 170 | }); 171 | 172 | topups.erase(topup); 173 | } 174 | 175 | private: 176 | 177 | 178 | void createOrUpdateIdentity(Identity& identity, int64_t tokens = 20'0000){ 179 | auto index = identities.get_index<"name"_n>(); 180 | auto existingIdentity = index.find(identity.fingerprint); 181 | 182 | /////////////////////////////////// 183 | // Repurchasing or new owner for existing identity 184 | if(existingIdentity != index.end()){ 185 | bool isExpired = now() > existingIdentity->expires; 186 | bool isSameOwner = existingIdentity->account == identity.account; 187 | uint64_t canRepurchase = now() > existingIdentity->expires - (SECONDS_PER_DAY * 90); 188 | 189 | eosio_assert(isExpired || isSameOwner, ("Identity "+identity.username+" is already taken.").c_str()); 190 | eosio_assert(isExpired || (isSameOwner && canRepurchase), "Can only re-purchase Identity for yourself within the last 90 days."); 191 | 192 | // TODO: This might not be the best idea. It would allow 193 | // identities to clear low reputations by expiring themselves. 194 | // perhaps instead it should halve the reputation or the next person 195 | // should assume the old reputation (as you would in real life if you took someone's name) 196 | // The downside of this would be someone could grab up a high-value name and ruin their reputation. 197 | auto rawIdentity = identities.find(existingIdentity->id); 198 | identities.modify(rawIdentity, _self, [&](auto& record){ 199 | // Only elongating expiration. 200 | if(isSameOwner){ 201 | record.expires = existingIdentity->expires + (SECONDS_PER_DAY * 365); 202 | } 203 | 204 | // New owner assuming control. 205 | else { 206 | record.expires = now() + (SECONDS_PER_DAY * 365); 207 | record.key = identity.key; 208 | record.account = identity.account; 209 | record.tokens = asset(tokens, S_RIDL); 210 | record.expansion = asset(0'0000, S_EXP); 211 | record.total_rep = asset(0'0000, S_REP); 212 | record.usable_rep = asset(0'0000, S_REP); 213 | record.bonded = asset(0'0000, S_REP); 214 | record.created = now(); 215 | record.block = tapos_block_num(); 216 | 217 | // auto bond_idx = bonds.get_index<"identity"_n>(); 218 | // auto bonds = bond_idx.find(identity.id); 219 | // for(auto bond : bonds){ 220 | //// BondActions(_self).erasebond(bond->id); 221 | // } 222 | 223 | // TODO: Need to remove all bonds. 224 | } 225 | }); 226 | } 227 | 228 | // Registering new identity 229 | else { 230 | identities.emplace(_self, [&](auto& record){ 231 | identity.id = identities.available_primary_key(); 232 | if(identity.id == 0) identity.id = 1; 233 | record = identity; 234 | record.tokens = asset(tokens, S_RIDL); 235 | record.block = tapos_block_num(); 236 | 237 | Reputable reputable = Reputable::create(identity.username, "id", "", 0); 238 | reputable.id = reputables.available_primary_key(); 239 | reputable.owner = identity.account; 240 | reputable.block = tapos_block_num(); 241 | 242 | record.rep_id = reputable.id; 243 | 244 | reputables.emplace(_self, [&](auto& r){ r = reputable; }); 245 | 246 | // TODO: Need to move tokens from reserves to this contract. 247 | }); 248 | } 249 | } 250 | 251 | }; 252 | -------------------------------------------------------------------------------- /ridl_id/actions/reputation_actions.hpp: -------------------------------------------------------------------------------- 1 | #pragma once 2 | 3 | #include 4 | #include "../models/reputable.h" 5 | #include "../models/reputation.h" 6 | #include "../models/identity.h" 7 | #include "../../ridl_token/ridl_token.hpp" 8 | 9 | using namespace eosio; 10 | using namespace reputable; 11 | using namespace reputation; 12 | using namespace identity; 13 | 14 | using std::string; 15 | using std::vector; 16 | using std::make_tuple; 17 | 18 | class ReputationActions { 19 | private: 20 | name _self; 21 | ReputationTypes reputationTypes; 22 | Reputables reputables; 23 | Identities identities; 24 | 25 | auto findIdentity(string& username){ 26 | lower(username); 27 | auto index = identities.get_index<"name"_n>(); 28 | auto found = index.find(toUUID(username)); 29 | eosio_assert(found != index.end(), ("Could not find username: "+username).c_str()); 30 | return identities.find(found->id); 31 | } 32 | 33 | public: 34 | ReputationActions(name self):_self(self), 35 | reputationTypes(_self, _self.value), 36 | reputables(_self, _self.value), 37 | identities(_self, _self.value){} 38 | 39 | void repute(string& username, uuid id, string& entity, string& type, vector& fragments, string& network, string& parentString){ 40 | /////////////////////////////////// 41 | // Assertions and formatting 42 | eosio_assert(entity.size() > 0, "Entity is invalid"); 43 | eosio_assert(fragments.size() <= 5 && fragments.size() > 0, "Only 1-5 reputation fragments are allowed"); 44 | 45 | lower(entity); 46 | lower(network); 47 | 48 | 49 | /////////////////////////////////// 50 | // Identity verification 51 | auto identity = findIdentity(username); 52 | eosio_assert(identity != identities.end(), "Identity does not exist"); 53 | identity->authenticate(); 54 | 55 | /////////////////////////////////// 56 | // Parent handling and parsing 57 | uuid parent = getReputableParentOrCreate(parentString, identity); 58 | 59 | /////////////////////////////////// 60 | // Get or create entity 61 | bool isNew = id == 0; 62 | 63 | // Checks if an entity with the same fingerprint exists and 64 | // just the ID wasn't sent 65 | if(isNew) { 66 | uint64_t fingerprint = toUUID(type+entity+network+std::to_string(parent)); 67 | auto index = reputables.get_index<"fingerprint"_n>(); 68 | auto existing = index.find(fingerprint); 69 | if(existing != index.end()){ 70 | id = existing->id; 71 | isNew = false; 72 | } 73 | } 74 | 75 | Reputable reputable = Reputable::create(entity, type, network, parent); 76 | auto existingReputable = reputables.find(id); 77 | 78 | if(!isNew) eosio_assert(existingReputable != reputables.end(), ("There is no reputable with the ID "+std::to_string(id)).c_str()); 79 | 80 | /////////////////////////////////// 81 | // Fragment validation 82 | for(auto& frag : fragments) { 83 | frag.assertValid(); 84 | auto existingFrag = reputationTypes.find(frag.fingerprint); 85 | eosio_assert(existingFrag != reputationTypes.end(), "Fragment type is not available"); 86 | eosio_assert(existingFrag->base == 0 || existingFrag->base == id, "Fragment does not belong to this entity"); 87 | eosio_assert(existingFrag->type == frag.type, "Fingerprint does not match type name"); 88 | } 89 | 90 | /////////////////////////////////// 91 | // Calculate total RIDL used 92 | asset ridlUsed = asset(0'0000, S_RIDL); 93 | for(auto& frag : fragments) ridlUsed += (frag.up + frag.down); 94 | eosio_assert(identity->tokens.amount >= ridlUsed.amount, "Not enough RIDL for repute."); 95 | 96 | 97 | // Contract actions must have a parent 98 | if(reputable.type == "act"){ 99 | eosio_assert(parent != 0, "Contract actions must be parented to a contract."); 100 | } 101 | 102 | // If a base is provided, then 103 | if(parent > 0){ 104 | // Base existence validation 105 | auto baseReputable = reputables.find(parent); 106 | eosio_assert(baseReputable != reputables.end(), "There is no such base reputable."); 107 | 108 | /////////////////////////////////// 109 | // Action reputing validation 110 | if(reputable.type == "act"){ 111 | eosio_assert(baseReputable->type == "acc", "The base reputable of an action must be a blockchain accounts/contract."); 112 | } 113 | } 114 | 115 | /////////////////////////////////// 116 | // Add or update reputable 117 | if(isNew) createNewEntity(reputable, identity, fragments); 118 | else updateExistingEntity(reputable, existingReputable, identity, fragments); 119 | 120 | /////////////////////////////////// 121 | // Identity reputing validation 122 | if(reputable.type == "id") { 123 | reputedIdentity(reputable, fragments); 124 | } 125 | 126 | /////////////////////////////////// 127 | // Getting the old reputation or creating a zeroed out reputation. 128 | Reputation reputation = Reputations(_self, reputable.id) 129 | .get_or_default(reputation::createReputation(reputable.id)); 130 | 131 | /////////////////////////////////// 132 | // Setting the new reputation 133 | reputation.mergeRepute(fragments); 134 | reputation.total_reputes += 1; 135 | Reputations(_self, reputable.id).set(reputation, _self); 136 | 137 | 138 | /////////////////////////////////// 139 | // Pay reputation taxes 140 | payTaxes(ridlUsed, reputable, identity, fragments, existingReputable->last_reputer); 141 | 142 | /////////////////////////////////// 143 | // Reducing the Identity's RIDL 144 | identities.modify(identity, same_payer, [&](auto& row){ 145 | row.expansion = asset(row.expansion.amount + (ridlUsed.amount * 0.01), S_EXP); 146 | row.tokens -= ridlUsed; 147 | }); 148 | } 149 | 150 | void forcetype(string& type, uuid& parent, string& upTag, string& downTag){ 151 | require_auth(_self); 152 | 153 | eosio_assert(parent == 0 || reputables.find(parent) != reputables.end(), ("There is no reputable with the ID: "+std::to_string(parent)).c_str()); 154 | 155 | RepType repType = RepType::create(type, upTag, downTag, parent); 156 | 157 | ReputationTypes reputationTypes(_self, _self.value); 158 | auto iter = reputationTypes.find(repType.fingerprint); 159 | eosio_assert(iter == reputationTypes.end(), "This rep type already exists."); 160 | 161 | reputationTypes.emplace(_self, [&](auto& r){ r = repType; }); 162 | } 163 | 164 | private: 165 | 166 | /*** 167 | * Creates a parent or returns an existing one. 168 | * @param parentString 169 | * @param identity 170 | * @return 171 | */ 172 | uuid getReputableParentOrCreate(string& parentString, Identities::const_iterator& identity){ 173 | if(parentString.find("::", 0) == std::string::npos) return 0; 174 | 175 | vector parts = splitString(parentString, "::"); 176 | if(parts[0] == "id") return std::stoull(parts[1]); 177 | 178 | eosio_assert(parts[0] == "fingerprint", "Parent must be either an ID or a Fingerprint."); 179 | 180 | string& entity = parts[1]; 181 | string& type = parts[2]; 182 | string network = parts.size() > 3 ? splitString(parentString, parts[2]+"::")[1] : ""; 183 | 184 | lower(entity); 185 | lower(type); 186 | lower(network); 187 | 188 | uuid p = 0; 189 | Reputable reputable = Reputable::create(entity, type, network, p); 190 | 191 | // Looking for existing parent based on fingerprinting 192 | auto index = reputables.get_index<"fingerprint"_n>(); 193 | auto existing = index.find(reputable.by_fingerprint()); 194 | if(existing != index.end()) return existing->id; 195 | 196 | // Creating new parent 197 | vector fragments; 198 | createNewEntity(reputable, identity, fragments); 199 | return reputable.id; 200 | } 201 | 202 | /*** 203 | * Updates or creates miner fragment references. 204 | * @param reputable 205 | * @param identity 206 | * @param fragments 207 | */ 208 | void updateOrCreateMinerFrags(Reputable& reputable, Identities::const_iterator& identity, vector& fragments){ 209 | MinerFrags minerFrags(_self, reputable.id); 210 | for(auto& frag : fragments) { 211 | auto minerFrag = minerFrags.find(frag.fingerprint); 212 | if(minerFrag != minerFrags.end()){ 213 | if(minerFrag->expired()) minerFrags.modify(minerFrag, identity->account, [&](auto& row){ 214 | row = MinerFrag::create(identity, frag); 215 | }); 216 | } 217 | else minerFrags.emplace(identity->account, [&](auto& row){ 218 | row = MinerFrag::create(identity, frag); 219 | }); 220 | } 221 | } 222 | 223 | void createNewEntity(Reputable& reputable, Identities::const_iterator& identity, vector& fragments){ 224 | reputable.last_repute_time = now(); 225 | reputable.id = reputables.available_primary_key(); 226 | if(reputable.id == 0) reputable.id = 1; 227 | reputable.block = tapos_block_num(); 228 | reputables.emplace(identity->account, [&](auto& row){ row = reputable; }); 229 | 230 | updateOrCreateMinerFrags(reputable, identity, fragments); 231 | } 232 | 233 | void updateExistingEntity(Reputable& reputable, Reputables::const_iterator& existingReputable, Identities::const_iterator& identity, vector& fragments){ 234 | reputable.merge(*existingReputable); 235 | 236 | updateOrCreateMinerFrags(reputable, identity, fragments); 237 | 238 | reputable.last_reputer = reputable.last_reputer != identity->account 239 | ? identity->account 240 | : name(""); 241 | 242 | reputable.last_repute_time = now(); 243 | reputables.modify(existingReputable, same_payer, [&](auto& row){ row = reputable; }); 244 | } 245 | 246 | void reputedIdentity(Reputable& reputable, vector& fragments){ 247 | auto reputingIdentity = findIdentity(reputable.entity); 248 | eosio_assert(reputingIdentity != identities.end(), "Identity does not exist"); 249 | 250 | asset totalRep = asset(0'0000, S_REP); 251 | for(auto& frag : fragments) totalRep += (ridlToRep(frag.up) - ridlToRep(frag.down)); 252 | 253 | identities.modify(reputingIdentity, same_payer, [&](auto& row){ 254 | row.total_rep += totalRep; 255 | row.usable_rep += asset(totalRep.amount * 0.5, S_REP); 256 | }); 257 | } 258 | 259 | void updateFragmentTotals( ReputationFragment& frag ){ 260 | FragTotal fragTotal = FragTotals(_self, frag.fingerprint).get_or_default(reputation::createFragTotal(frag.type)); 261 | fragTotal.up += ridlToRep(frag.up); 262 | fragTotal.down += ridlToRep(frag.down); 263 | FragTotals(_self, frag.fingerprint).set(fragTotal, _self); 264 | } 265 | 266 | void payTaxes(asset ridlUsed, Reputable& reputable, Identities::const_iterator& identity, vector& fragments, name last_reputer){ 267 | 268 | 269 | 270 | /////////////////////////////////// 271 | // Issuing Repute Taxes 272 | asset remainingRIDL = ridlUsed; 273 | asset fivePercent(((float)ridlUsed.amount * 0.05), S_RIDL); 274 | 275 | 276 | 277 | /////////////////////////////////// 278 | // Calculating Tax and adding globals 279 | MinerFrags minerFrags(_self, reputable.id); 280 | asset minerTax = asset(0'0000, S_RIDL); 281 | 282 | std::map minerTaxes = std::map(); 283 | 284 | for(auto& frag : fragments) { 285 | updateFragmentTotals(frag); 286 | 287 | MinerFrag minerFrag = minerFrags.get(frag.fingerprint, "Could not get miner frag"); 288 | Identity minerId = identities.get(minerFrag.identity, "Identity no longer exists"); 289 | 290 | if(minerFrag.identity != identity->id){ 291 | asset tax(((float)(frag.isPositive() ? frag.up : frag.down).amount) * 0.1, S_RIDL); 292 | 293 | if(minerTaxes.find(minerId.account) == minerTaxes.end()) { 294 | minerTaxes[minerId.account] = asset(0'0000, S_RIDL); 295 | } 296 | 297 | if(minerFrag.positive == frag.isPositive()) minerTaxes[minerId.account] += tax; 298 | else minerTaxes[minerId.account] -= tax; 299 | } 300 | } 301 | 302 | 303 | for(const auto& pair : minerTaxes){ 304 | if(pair.second.amount > 0) { 305 | sendRIDL(_self, pair.first, pair.second, (pair.second.to_string() + " Mined - " + reputable.entity)); 306 | remainingRIDL -= minerTax; 307 | } 308 | } 309 | 310 | 311 | 312 | 313 | /////////////////////////////////// 314 | // RIDL Reserves Tax 315 | sendRIDL(_self, "ridlreserves"_n, fivePercent, "RIDL Tax"); 316 | remainingRIDL -= fivePercent; 317 | 318 | /////////////////////////////////// 319 | // Last reputer mined 320 | if(last_reputer && last_reputer != identity->account && is_account(last_reputer)){ 321 | sendRIDL(_self, last_reputer, fivePercent, (fivePercent.to_string() + " Mined - " + reputable.entity)); 322 | remainingRIDL -= fivePercent; 323 | } 324 | 325 | /*** 326 | * If this reputable has an owner then 327 | * sending the remaining RIDL to the owner 328 | * otherwise sending to reserves 329 | */ 330 | if(reputable.owner) sendRIDL(_self, reputable.owner, remainingRIDL, "Reputed"); 331 | else sendRIDL(_self, "ridlreserves"_n, remainingRIDL, "Reputed unclaimed entity"); 332 | } 333 | 334 | 335 | }; 336 | -------------------------------------------------------------------------------- /ridl_id/ridl_id.abi: -------------------------------------------------------------------------------- 1 | { 2 | "____comment": "This file was generated with eosio-abigen. DO NOT EDIT Wed Dec 19 11:02:12 2018", 3 | "version": "eosio::abi/1.1", 4 | "structs": [ 5 | { 6 | "name": "FragTotal", 7 | "base": "", 8 | "fields": [ 9 | { 10 | "name": "fingerprint", 11 | "type": "uuid" 12 | }, 13 | { 14 | "name": "type", 15 | "type": "string" 16 | }, 17 | { 18 | "name": "up", 19 | "type": "asset" 20 | }, 21 | { 22 | "name": "down", 23 | "type": "asset" 24 | } 25 | ] 26 | }, 27 | { 28 | "name": "Identity", 29 | "base": "", 30 | "fields": [ 31 | { 32 | "name": "fingerprint", 33 | "type": "uuid" 34 | }, 35 | { 36 | "name": "username", 37 | "type": "string" 38 | }, 39 | { 40 | "name": "key", 41 | "type": "public_key" 42 | }, 43 | { 44 | "name": "account", 45 | "type": "name" 46 | }, 47 | { 48 | "name": "expires", 49 | "type": "uint64" 50 | }, 51 | { 52 | "name": "tokens", 53 | "type": "asset" 54 | }, 55 | { 56 | "name": "total_rep", 57 | "type": "asset" 58 | } 59 | ] 60 | }, 61 | { 62 | "name": "NewRepType", 63 | "base": "", 64 | "fields": [ 65 | { 66 | "name": "fingerprint", 67 | "type": "uuid" 68 | }, 69 | { 70 | "name": "type", 71 | "type": "string" 72 | }, 73 | { 74 | "name": "up", 75 | "type": "name[]" 76 | }, 77 | { 78 | "name": "down", 79 | "type": "name[]" 80 | } 81 | ] 82 | }, 83 | { 84 | "name": "Reputable", 85 | "base": "", 86 | "fields": [ 87 | { 88 | "name": "fingerprint", 89 | "type": "uuid" 90 | }, 91 | { 92 | "name": "type", 93 | "type": "string" 94 | }, 95 | { 96 | "name": "entity", 97 | "type": "string" 98 | }, 99 | { 100 | "name": "miner", 101 | "type": "name" 102 | }, 103 | { 104 | "name": "miner_til", 105 | "type": "uint64" 106 | }, 107 | { 108 | "name": "miner_frags", 109 | "type": "ReputationFragment[]" 110 | }, 111 | { 112 | "name": "last_reputer", 113 | "type": "name" 114 | }, 115 | { 116 | "name": "owner", 117 | "type": "name" 118 | }, 119 | { 120 | "name": "total_rep", 121 | "type": "asset" 122 | } 123 | ] 124 | }, 125 | { 126 | "name": "RepTypes", 127 | "base": "", 128 | "fields": [ 129 | { 130 | "name": "fingerprint", 131 | "type": "uuid" 132 | }, 133 | { 134 | "name": "type", 135 | "type": "string" 136 | } 137 | ] 138 | }, 139 | { 140 | "name": "Reputation", 141 | "base": "", 142 | "fields": [ 143 | { 144 | "name": "fingerprint", 145 | "type": "uuid" 146 | }, 147 | { 148 | "name": "fragments", 149 | "type": "ReputationFragment[]" 150 | }, 151 | { 152 | "name": "total_reputes", 153 | "type": "int64" 154 | } 155 | ] 156 | }, 157 | { 158 | "name": "ReputationFragment", 159 | "base": "", 160 | "fields": [ 161 | { 162 | "name": "type", 163 | "type": "string" 164 | }, 165 | { 166 | "name": "up", 167 | "type": "asset" 168 | }, 169 | { 170 | "name": "down", 171 | "type": "asset" 172 | } 173 | ] 174 | }, 175 | { 176 | "name": "balances", 177 | "base": "", 178 | "fields": [ 179 | { 180 | "name": "symbol", 181 | "type": "uint64" 182 | }, 183 | { 184 | "name": "balance", 185 | "type": "asset" 186 | } 187 | ] 188 | }, 189 | { 190 | "name": "claim", 191 | "base": "", 192 | "fields": [ 193 | { 194 | "name": "account", 195 | "type": "name" 196 | }, 197 | { 198 | "name": "username", 199 | "type": "string" 200 | }, 201 | { 202 | "name": "key", 203 | "type": "public_key" 204 | }, 205 | { 206 | "name": "sig", 207 | "type": "signature" 208 | } 209 | ] 210 | }, 211 | { 212 | "name": "clean", 213 | "base": "", 214 | "fields": [ 215 | { 216 | "name": "scope", 217 | "type": "name" 218 | } 219 | ] 220 | }, 221 | { 222 | "name": "configs", 223 | "base": "", 224 | "fields": [ 225 | { 226 | "name": "hash", 227 | "type": "checksum256" 228 | } 229 | ] 230 | }, 231 | { 232 | "name": "forcetype", 233 | "base": "", 234 | "fields": [ 235 | { 236 | "name": "type", 237 | "type": "string" 238 | } 239 | ] 240 | }, 241 | { 242 | "name": "identify", 243 | "base": "", 244 | "fields": [ 245 | { 246 | "name": "account", 247 | "type": "name" 248 | }, 249 | { 250 | "name": "username", 251 | "type": "string" 252 | }, 253 | { 254 | "name": "key", 255 | "type": "public_key" 256 | } 257 | ] 258 | }, 259 | { 260 | "name": "loadtokens", 261 | "base": "", 262 | "fields": [ 263 | { 264 | "name": "account", 265 | "type": "name" 266 | }, 267 | { 268 | "name": "username", 269 | "type": "string" 270 | }, 271 | { 272 | "name": "tokens", 273 | "type": "asset" 274 | } 275 | ] 276 | }, 277 | { 278 | "name": "rekey", 279 | "base": "", 280 | "fields": [ 281 | { 282 | "name": "username", 283 | "type": "string" 284 | }, 285 | { 286 | "name": "key", 287 | "type": "public_key" 288 | } 289 | ] 290 | }, 291 | { 292 | "name": "release", 293 | "base": "", 294 | "fields": [ 295 | { 296 | "name": "username", 297 | "type": "string" 298 | }, 299 | { 300 | "name": "sig", 301 | "type": "signature" 302 | } 303 | ] 304 | }, 305 | { 306 | "name": "repute", 307 | "base": "", 308 | "fields": [ 309 | { 310 | "name": "username", 311 | "type": "string" 312 | }, 313 | { 314 | "name": "entity", 315 | "type": "string" 316 | }, 317 | { 318 | "name": "fragments", 319 | "type": "ReputationFragment[]" 320 | }, 321 | { 322 | "name": "details", 323 | "type": "string" 324 | } 325 | ] 326 | }, 327 | { 328 | "name": "seed", 329 | "base": "", 330 | "fields": [ 331 | { 332 | "name": "username", 333 | "type": "string" 334 | }, 335 | { 336 | "name": "key", 337 | "type": "public_key" 338 | } 339 | ] 340 | }, 341 | { 342 | "name": "setaccacc", 343 | "base": "", 344 | "fields": [ 345 | { 346 | "name": "username", 347 | "type": "string" 348 | }, 349 | { 350 | "name": "new_account", 351 | "type": "name" 352 | } 353 | ] 354 | }, 355 | { 356 | "name": "setacckey", 357 | "base": "", 358 | "fields": [ 359 | { 360 | "name": "username", 361 | "type": "string" 362 | }, 363 | { 364 | "name": "new_account", 365 | "type": "name" 366 | }, 367 | { 368 | "name": "sig", 369 | "type": "signature" 370 | } 371 | ] 372 | }, 373 | { 374 | "name": "setconfig", 375 | "base": "", 376 | "fields": [ 377 | { 378 | "name": "config", 379 | "type": "configs" 380 | } 381 | ] 382 | } 383 | ], 384 | "types": [ 385 | { 386 | "new_type_name": "uuid", 387 | "type": "uint64" 388 | } 389 | ], 390 | "actions": [ 391 | { 392 | "name": "claim", 393 | "type": "claim", 394 | "ricardian_contract": "" 395 | }, 396 | { 397 | "name": "clean", 398 | "type": "clean", 399 | "ricardian_contract": "" 400 | }, 401 | { 402 | "name": "forcetype", 403 | "type": "forcetype", 404 | "ricardian_contract": "" 405 | }, 406 | { 407 | "name": "identify", 408 | "type": "identify", 409 | "ricardian_contract": "" 410 | }, 411 | { 412 | "name": "loadtokens", 413 | "type": "loadtokens", 414 | "ricardian_contract": "" 415 | }, 416 | { 417 | "name": "rekey", 418 | "type": "rekey", 419 | "ricardian_contract": "" 420 | }, 421 | { 422 | "name": "release", 423 | "type": "release", 424 | "ricardian_contract": "" 425 | }, 426 | { 427 | "name": "repute", 428 | "type": "repute", 429 | "ricardian_contract": "" 430 | }, 431 | { 432 | "name": "seed", 433 | "type": "seed", 434 | "ricardian_contract": "" 435 | }, 436 | { 437 | "name": "setaccacc", 438 | "type": "setaccacc", 439 | "ricardian_contract": "" 440 | }, 441 | { 442 | "name": "setacckey", 443 | "type": "setacckey", 444 | "ricardian_contract": "" 445 | }, 446 | { 447 | "name": "setconfig", 448 | "type": "setconfig", 449 | "ricardian_contract": "" 450 | } 451 | ], 452 | "tables": [ 453 | { 454 | "name": "balances", 455 | "type": "balances", 456 | "index_type": "i64", 457 | "key_names": [], 458 | "key_types": [] 459 | }, 460 | { 461 | "name": "configs", 462 | "type": "configs", 463 | "index_type": "i64", 464 | "key_names": [], 465 | "key_types": [] 466 | }, 467 | { 468 | "name": "fragtotal", 469 | "type": "FragTotal", 470 | "index_type": "i64", 471 | "key_names": [], 472 | "key_types": [] 473 | }, 474 | { 475 | "name": "ids", 476 | "type": "Identity", 477 | "index_type": "i64", 478 | "key_names": [], 479 | "key_types": [] 480 | }, 481 | { 482 | "name": "newreptypes", 483 | "type": "NewRepType", 484 | "index_type": "i64", 485 | "key_names": [], 486 | "key_types": [] 487 | }, 488 | { 489 | "name": "reptypes", 490 | "type": "RepTypes", 491 | "index_type": "i64", 492 | "key_names": [], 493 | "key_types": [] 494 | }, 495 | { 496 | "name": "reputables", 497 | "type": "Reputable", 498 | "index_type": "i64", 499 | "key_names": [], 500 | "key_types": [] 501 | }, 502 | { 503 | "name": "reputations", 504 | "type": "Reputation", 505 | "index_type": "i64", 506 | "key_names": [], 507 | "key_types": [] 508 | } 509 | ], 510 | "ricardian_clauses": [], 511 | "variants": [], 512 | "abi_extensions": [] 513 | } --------------------------------------------------------------------------------