diff --git a/tools/deployment/README.md b/tools/deployment/README.md index d820586..530955e 100644 --- a/tools/deployment/README.md +++ b/tools/deployment/README.md @@ -8,4 +8,7 @@ These scripts are used in two places: ### Shell scripts - `store_instantiate.sh` sends transactions to store the codes from the `artifacts` directory to the specified blockchain. Then it uses stored codes to instantiate Hydro and Tribute smart contracts. It relies on a JSON configuration file that is passed to it. It populates and exports two environment variables: `HYDRO_CONTRACT_ADDRESS` and `TRIBUTE_CONTRACT_ADDRESS`. - `populate_contracts.sh` sends transactions to create proposals in the Hydro smart contract, and to add tributes for those proposals in the Tribute smart contract. It relies on `HYDRO_CONTRACT_ADDRESS` and `TRIBUTE_CONTRACT_ADDRESS` being previously set by the `store_instantiate.sh` script. -- `setup_on_mainnet.sh` executes previous two scripts by providing `config_mainnet.json` configuration that will result in smart contracts being set up on the Neutron mainnet. Prerequisite for running this script is to have the `neutrond` binary in your `PATH` and to import mnemonic that has enough NTRN tokens on the Neutron mainnet. If this mnemonic is for a different address than the one in `config_mainnet.json` file, then the configuration file needs to be adjusted as well. \ No newline at end of file +- `setup_on_mainnet.sh` executes previous two scripts by providing `config_mainnet.json` configuration that will result in smart contracts being set up on the Neutron mainnet. Prerequisite for running this script is to have the `neutrond` binary in your `PATH` and to import mnemonic that has enough NTRN tokens on the Neutron mainnet. If this mnemonic is for a different address than the one in `config_mainnet.json` file, then the configuration file needs to be adjusted as well. +- `setup_on_testnet.sh` does the same as `setup_on_mainnet.sh`, just on Neutron pion-1 testnet. +- `daodao_hydro_setup.sh` will instantiate DAO DAO set of contracts on Neutron mainnet. Instantiated DAO will use the specified Hydro contract as its voting power module. Make sure to adjust the configuration file `tools/deployment/config_daodao_mainnet.json` before running the script. Usage example: +`bash tools/deployment/daodao_hydro_setup.sh "tools/deployment/config_daodao_mainnet.json"` \ No newline at end of file diff --git a/tools/deployment/config_daodao_mainnet.json b/tools/deployment/config_daodao_mainnet.json new file mode 100644 index 0000000..878fe2d --- /dev/null +++ b/tools/deployment/config_daodao_mainnet.json @@ -0,0 +1,14 @@ +{ + "dao_name": "Hydro Governance", + "dao_description": "Hydro governance is a decentralized decision-making system that allows Hydro participants to take part in the management & evolution of the protocol. It operates through on-chain voting, where Hydro-locked ATOM holders vote on governance proposals that impact the protocol's parameters, upgrades, and treasury management.", + "dao_voting_adapter_code_id": "3144", + "hydro_contract_address": "neutron13w6sagl4clacx4c8drhuwfl20cesn3pnllhf37e65ls8zwf6gcgq93t2lp", + "proposal_submission_approver": "neutron1w7f40hgfc505a2wnjsl5pg35yl8qpawv48w5yekax4xj2m43j09s5fa44f", + "allowed_proposal_submitter": "", + "uusdc_deposit_amount": "50000000", + "max_voting_period": "345600", + "quorum_percent": "0.1", + "only_members_execute": "false", + "image_url": "ipfs://QmNsj6WYt3WpyWT6jMG71uhZNj2UwnZn7S3B595RYZ1qyd", + "banner": "ipfs://QmScf4q2hADFBcTPBsGsuhvCUmFnVrz6DXdZUXB45KkYBu" +} \ No newline at end of file diff --git a/tools/deployment/daodao_hydro_setup.sh b/tools/deployment/daodao_hydro_setup.sh new file mode 100644 index 0000000..6ff9137 --- /dev/null +++ b/tools/deployment/daodao_hydro_setup.sh @@ -0,0 +1,97 @@ +#!/bin/bash + +if [ "$#" -ne 1 ]; then + echo "Usage: $0 DAO_DEPLOYMENT_CONFIG_PATH" + exit 1 +fi + +NEUTRON_BINARY="neutrond" +CONFIG_FILE="tools/deployment/config_mainnet.json" + +NEUTRON_CHAIN_ID=$(jq -r '.chain_id' $CONFIG_FILE) +NEUTRON_NODE=$(jq -r '.neutron_rpc_node' $CONFIG_FILE) +TX_SENDER_WALLET=$(jq -r '.tx_sender_wallet' $CONFIG_FILE) +TX_SENDER_ADDRESS=$($NEUTRON_BINARY keys show $TX_SENDER_WALLET --keyring-backend test | grep "address:" | sed 's/.*address: //') + +NEUTRON_CHAIN_ID_FLAG="--chain-id $NEUTRON_CHAIN_ID" +KEYRING_TEST_FLAG="--keyring-backend test" +TX_FLAG="--gas auto --gas-adjustment 1.3" +NEUTRON_NODE_FLAG="--node $NEUTRON_NODE" +NEUTRON_TX_FLAGS="$TX_FLAG --gas-prices 0.0053untrn --chain-id $NEUTRON_CHAIN_ID $NEUTRON_NODE_FLAG $KEYRING_TEST_FLAG -y" + +DAO_DEPLOYMENT_CONFIG_PATH="$1" +DAO_NAME=$(jq -r '.dao_name' $DAO_DEPLOYMENT_CONFIG_PATH) +DAO_DESCRIPTION=$(jq -r '.dao_description' $DAO_DEPLOYMENT_CONFIG_PATH) +DAO_VOTING_ADAPTER_CODE_ID=$(jq -r '.dao_voting_adapter_code_id' $DAO_DEPLOYMENT_CONFIG_PATH) +HYDRO_CONTRACT_ADDRESS=$(jq -r '.hydro_contract_address' $DAO_DEPLOYMENT_CONFIG_PATH) +PROPOSAL_SUBMISSION_APPROVER=$(jq -r '.proposal_submission_approver' $DAO_DEPLOYMENT_CONFIG_PATH) +ALLOWED_PROPOSAL_SUBMITTER=$(jq -r '.allowed_proposal_submitter' $DAO_DEPLOYMENT_CONFIG_PATH) +UUSDC_DEPOSIT_AMOUNT=$(jq -r '.uusdc_deposit_amount' $DAO_DEPLOYMENT_CONFIG_PATH) +MAX_VOTING_PERIOD=$(jq -r '.max_voting_period' $DAO_DEPLOYMENT_CONFIG_PATH) +QUORUM_PERCENT=$(jq -r '.quorum_percent' $DAO_DEPLOYMENT_CONFIG_PATH) +ONLY_MEMBERS_EXECUTE=$(jq -r '.only_members_execute' $DAO_DEPLOYMENT_CONFIG_PATH) +IMAGE_URL=$(jq -r '.image_url' $DAO_DEPLOYMENT_CONFIG_PATH) +BANNER=$(jq -r '.banner' $DAO_DEPLOYMENT_CONFIG_PATH) + +# https://github.com/DA0-DA0/dao-dao-ui/blob/development/packages/utils/constants/codeIds.json +DAO_CORE_CODE_ID="2346" +DAO_PROPOSAL_SINGLE_CODE_ID="2353" +DAO_PREPROPOSE_APPROVAL_SINGLE_CODE_ID="2348" + +DAO_VOTING_ADAPTER_INIT_MSG='{"hydro_contract":"'$HYDRO_CONTRACT_ADDRESS'"}' +echo 'DAO Voting Adapter init msg:' $DAO_VOTING_ADAPTER_INIT_MSG +echo "" +DAO_VOTING_ADAPTER_INIT_MSG=$(echo -n $DAO_VOTING_ADAPTER_INIT_MSG | base64 | tr -d '[:space:]') + +VOTING_MODULE_INSTANTIATE_INFO='{"code_id":'$DAO_VOTING_ADAPTER_CODE_ID',"funds":[],"label":"Hydro DAO Voting Adapter","msg":"'$DAO_VOTING_ADAPTER_INIT_MSG'"}' + +if [ -z "$ALLOWED_PROPOSAL_SUBMITTER" ]; then + SUBMISSION_POLICY='{"anyone": {"denylist": []}}' +else + SUBMISSION_POLICY='{"specific": {"dao_members": false,"allowlist": ["'$ALLOWED_PROPOSAL_SUBMITTER'"],"denylist": []}}' +fi + +if [ -z "$UUSDC_DEPOSIT_AMOUNT" ]; then + DEPOSIT_INFO='null' +else + DEPOSIT_INFO='{"denom": {"token": {"denom": {"native": "ibc/B559A80D62249C8AA07A380E2A2BEA6E5CA9A6F079C912C3A9E9B494105E4F81"}}}, "amount": "'$UUSDC_DEPOSIT_AMOUNT'", "refund_policy": "only_passed"}' +fi + +if [ -z "$IMAGE_URL" ]; then + IMAGE_URL='null' +else + IMAGE_URL='"'$IMAGE_URL'"' +fi + +if [ -z "$BANNER" ]; then + INITIAL_ITEMS='null' +else + INITIAL_ITEMS='[{"key": "banner", "value": "'$BANNER'"}]' +fi + +PRE_PROPOSE_APPROVAL_INIT_MSG='{"deposit_info": '$DEPOSIT_INFO',"submission_policy": '$SUBMISSION_POLICY', "extension": { "approver": "'$PROPOSAL_SUBMISSION_APPROVER'"}}' +echo "DAO Pre-propose approval init msg:" $PRE_PROPOSE_APPROVAL_INIT_MSG +echo "" +PRE_PROPOSE_APPROVAL_INIT_MSG=$(echo -n $PRE_PROPOSE_APPROVAL_INIT_MSG | base64 | tr -d '[:space:]') + +PRE_PROPOSE_MODULE_INSTANTIATE_INFO='{"module_may_propose": {"info": {"admin": {"core_module": {}}, "code_id": '$DAO_PREPROPOSE_APPROVAL_SINGLE_CODE_ID', "label": "Hydro pre-propose-single with Approver", "msg": "'$PRE_PROPOSE_APPROVAL_INIT_MSG'", "funds": []}}}' +DAO_PROPOSAL_SINGLE_INIT_MSG='{"threshold": {"threshold_quorum": {"quorum": {"percent": "'$QUORUM_PERCENT'"}, "threshold": {"majority": {}}}}, "max_voting_period":{"time":'$MAX_VOTING_PERIOD'}, "only_members_execute": '$ONLY_MEMBERS_EXECUTE', "allow_revoting":false, "close_proposal_on_execution_failure":true, "pre_propose_info":'$PRE_PROPOSE_MODULE_INSTANTIATE_INFO'}' +echo 'DAO Proposal Single init msg:' $DAO_PROPOSAL_SINGLE_INIT_MSG +echo "" +DAO_PROPOSAL_SINGLE_INIT_MSG=$(echo -n $DAO_PROPOSAL_SINGLE_INIT_MSG | base64 | tr -d '[:space:]') + +PROPOSAL_MODULE_INSTANTIATE_INFO='{"code_id":'$DAO_PROPOSAL_SINGLE_CODE_ID', "funds":[], "label":"Hydro DAO proposal-single", "msg":"'$DAO_PROPOSAL_SINGLE_INIT_MSG'"}' + +INIT_DAODAO='{"name":"'$DAO_NAME'", "description":"'$DAO_DESCRIPTION'", "image_url": '$IMAGE_URL', "initial_items": '$INITIAL_ITEMS', "automatically_add_cw20s":false, "automatically_add_cw721s":false, "voting_module_instantiate_info":'$VOTING_MODULE_INSTANTIATE_INFO',"proposal_modules_instantiate_info":['$PROPOSAL_MODULE_INSTANTIATE_INFO']}' +echo 'DAO Core init msg:' $INIT_DAODAO +echo "" + +echo 'Instantiating Hydro DAO...' +$NEUTRON_BINARY tx wasm instantiate $DAO_CORE_CODE_ID "$INIT_DAODAO" --admin $TX_SENDER_ADDRESS --label "'$DAO_NAME'" --from $TX_SENDER_WALLET $NEUTRON_TX_FLAGS --output json &> ./instantiate_hydro_dao_res.json +sleep 10 + +INSTANTIATE_HYDRO_DAO_TX_HASH=$(grep -o '{.*}' ./instantiate_hydro_dao_res.json | jq -r '.txhash') +$NEUTRON_BINARY q tx $INSTANTIATE_HYDRO_DAO_TX_HASH $NEUTRON_NODE_FLAG --output json &> ./instantiate_hydro_dao_tx.json +HYDRO_DAO_CONTRACT_ADDRESS=$(jq -r '[.events[] | select(.type == "instantiate") | .attributes[] | select(.key == "_contract_address") | .value] | .[0]' ./instantiate_hydro_dao_tx.json) + +echo 'Hydro DAO successfully instantiated: https://daodao.zone/dao/'$HYDRO_DAO_CONTRACT_ADDRESS'/home' diff --git a/tools/deployment/store_instantiate.sh b/tools/deployment/store_instantiate.sh index c811da1..067f438 100644 --- a/tools/deployment/store_instantiate.sh +++ b/tools/deployment/store_instantiate.sh @@ -39,9 +39,11 @@ IS_IN_PILOT_MODE=true MAX_DEPLOYMENT_DURATION=3 HYDRO_WASM_PATH="./artifacts/hydro.wasm" TRIBUTE_WASM_PATH="./artifacts/tribute.wasm" +DAO_VOTING_ADAPTER_WASM_PATH="./artifacts/dao_voting_adapter.wasm" HYDRO_CODE_ID="" TRIBUTE_CODE_ID="" +DAO_VOTING_ADAPTER_CODE_ID="" HYDRO_SC_LABEL="Hydro" TRIBUTE_SC_LABEL="Tribute" @@ -80,6 +82,23 @@ store_tribute() { TRIBUTE_CODE_ID=$(jq -r '.events[] | select(.type == "store_code") | .attributes[] | select(.key == "code_id") | .value' ./store_tribute_tx.json) } +store_dao_voting_adapter() { + error_handler() { + echo "Content of store_dao_voting_adapter_res.json:" + cat ./store_dao_voting_adapter_res.json + } + trap error_handler ERR + + echo 'Storing dao_voting_adapter wasm...' + + $NEUTRON_BINARY tx wasm store $DAO_VOTING_ADAPTER_WASM_PATH --from $TX_SENDER_WALLET $NEUTRON_TX_FLAGS --output json &> ./store_dao_voting_adapter_res.json + sleep 10 + + STORE_DAO_VOTING_ADAPTER_TX_HASH=$(grep -o '{.*}' ./store_dao_voting_adapter_res.json | jq -r '.txhash') + $NEUTRON_BINARY q tx $STORE_DAO_VOTING_ADAPTER_TX_HASH $NEUTRON_NODE_FLAG --output json &> ./store_dao_voting_adapter_tx.json + DAO_VOTING_ADAPTER_CODE_ID=$(jq -r '.events[] | select(.type == "store_code") | .attributes[] | select(.key == "code_id") | .value' ./store_dao_voting_adapter_tx.json) +} + instantiate_hydro() { error_handler() { echo "Content of instantiate_hydro_res.json:" @@ -127,9 +146,11 @@ instantiate_tribute() { store_hydro store_tribute +store_dao_voting_adapter echo 'Hydro code ID:' $HYDRO_CODE_ID echo 'Tribute code ID:' $TRIBUTE_CODE_ID +echo 'DAO Voting Adapter code ID:' $DAO_VOTING_ADAPTER_CODE_ID instantiate_hydro instantiate_tribute