Adding custom ICRC tokens to SNS DAO treasury

It would be great if SNSs could hold multiple tokens in their treasury and manage them using TreansferTreasury proposals.

SNSs could add ckBTC or nICP to their treasury balance sheet.

3 Likes

Origyn’s pending governance app canister has this basic functionality baked in. It is getting closer to release, so hopefully it will be open-sourced soon. It also has functions for the DAO to approve tokens that it can manage some basic functionality for building in hard-coded DAO accounts that can be managed via a generic proposal call.

1 Like

+1, that would be nice.

2 Likes

Even if you add this functionality with a canister it still won’t be supported by proposals. You could add a proposal but it would be nicer to support ICRC tokens natively.

2 Likes

Well…you’re going to have to add something somewhere because the TransferSNSTreasury Type uses an ambiguous int to point at a treasury:

type TransferSnsTreasuryFunds = record {
  from_treasury : int32;
  to_principal : opt principal;
  to_subaccount : opt Subaccount;
  memo : opt nat64;
  amount_e8s : nat64;
};

…so you’re going to have to add a bunch of treasury management functions like ‘AddTreasury’ into the core SNS which is going to necessitate relying on DFINITY to build it, test it, audit it, deploy it, etc.

If we move to a plug-in system where we add dapp canisters to SNS with easily configurable features and easily addable generic functions we’ll be able to experiment with a lot more DAO infrastructure.

You just need to add an app canister your SNS controls and approve a generic function:

//add the generic function
(
  record {
    subaccount = blob "\ca\0c\08\39\1b\89\77\84\56\42\e1\49\32\a7\63\b5\31\ad\2d\0b\90\b2\cb\93\64\51\40\ac\68\5c\74\67";
    command = opt variant {
      MakeProposal = record {
        url = "https://proposals.com";
        title = "Give register the SNS governance dapp canister";
        action = opt variant {
          AddGenericNervousSystemFunction = record {
            id = 1_000 : nat64;
            name = "ogy_governance";
            description = opt "Govern OGY Network functions";
            function_type = opt variant {
              GenericNervousSystemFunction = record {
                validator_canister_id = opt principal "a3shf-5eaaa-aaaaa-qaafa-cai";
                target_canister_id = opt principal "a3shf-5eaaa-aaaaa-qaafa-cai";
                validator_method_name = opt "validate_ogy_governance";
                target_method_name = opt "ogy_governance";
              }
            };
          }
        };
        summary = "ogy_governance function";
      }
    };
  },
)

Then that generic function can be submitted and voted on.

didc encode --format blob '(vec {variant { SendSysFunds = record {
canister = principal "bw4dl-smaaa-aaaaa-qaacq-cai";
request = variant {ICRC1 = record { 
 from_subaccount = opt blob "\9d\37\b7\68\19\9f\f7\90\54\7d\1d\06\bd\fa\b5\e3\d0\14\73\53\67\25\b6\b9\e3\d1\a7\86\7f\5c\80\3e";
 to = record {
    owner = principal "7jv5o-gfzdg-axu56-hsh7g-ocldj-5w76l-niqwc-y4wk4-b2tbh-wxxgf-xae";
    subaccount = null;
  };
  amount = 1_0000_0000 : nat;
  fee = null;
  memo = null;
  created_at_time = null;
} }}}})'

blob "DIDL\08m\01k\01\c9\c5\f9\c6\0f\02l\02\cf\be\93\a4\04\03\a7\c4\d2\e6\09hk\01\c6\af\a0\a6\03\04l\06\fb\ca\01\05\c6\fc\b6\02\7f\ba\89\e5\c2\04\7f\a2\de\94\eb\06\06\82\f3\f3\91\0c\7f\d8\a3\8c\a8\0d}l\02\b3\b0\da\c3\03h\ad\86\ca\83\05\7fn\07m{\01\00\01\00\00\01\1d\b9\19\81zw\c7\91\feg\09cOm\ff-\a8\85\85\8eY\5c\0e\a6\13\da\f71n\02\01 \9d7\b7h\19\9f\f7\90T}\1d\06\bd\fa\b5\e3\d0\14sSg%\b6\b9\e3\d1\a7\86\7f\5c\80>\80\c2\d7/\01\0a\80\00\00\00\00\10\00\05\01\01"

dfx canister call br5f7-7uaaa-aaaaa-qaaca-cai manage_neuron '(
  record {
    subaccount = blob "\ca\0c\08\39\1b\89\77\84\56\42\e1\49\32\a7\63\b5\31\ad\2d\0b\90\b2\cb\93\64\51\40\ac\68\5c\74\67";
    command = opt variant {
      MakeProposal = record {
        url = "https://proposals.com";
        title = "Sent 1 ogy to user";
        action = opt variant {
          ExecuteGenericNervousSystemFunction = record {
            function_id = 1_000 : nat64;
            payload = blob "DIDL\08m\01k\01\c9\c5\f9\c6\0f\02l\02\cf\be\93\a4\04\03\a7\c4\d2\e6\09hk\01\c6\af\a0\a6\03\04l\06\fb\ca\01\05\c6\fc\b6\02\7f\ba\89\e5\c2\04\7f\a2\de\94\eb\06\06\82\f3\f3\91\0c\7f\d8\a3\8c\a8\0d}l\02\b3\b0\da\c3\03h\ad\86\ca\83\05\7fn\07m{\01\00\01\00\00\01\1d\b9\19\81zw\c7\91\feg\09cOm\ff-\a8\85\85\8eY\5c\0e\a6\13\da\f71n\02\01 \9d7\b7h\19\9f\f7\90T}\1d\06\bd\fa\b5\e3\d0\14sSg%\b6\b9\e3\d1\a7\86\7f\5c\80>\80\c2\d7/\01\0a\80\00\00\00\00\10\00\05\01\01"
          }
        };
        summary = "Send OGY token to user";
      }
    };
  },
)'

The nice thing with variants is that you can add a bunch of variants by upgrading your SNS-controlled DAPP canister and you don’t have to add any more generic functions.

If you hold treasury funds in one of these canisters you can also customize your withdrawal limits which are currently standardized across SNS that makes DAOs have to do silly things like withdraw their treasures over the course of weeks to something.

Check this out

https://suemn-5aaaa-aaaap-qb62q-cai.icp0.io/sneed-lock

Sneed dao already have some functjons for handling icrc1 tokens and lp pools via its registered dapp canister

https://dashboard.internetcomputer.org/canister/ok64y-uiaaa-aaaag-qdcbq-cai