diff --git a/src/constants.ts b/src/constants.ts index 202ff3b0..e411f40e 100644 --- a/src/constants.ts +++ b/src/constants.ts @@ -24,7 +24,7 @@ export const ADDRESSES: NetworkAddressMap = { STXCITY_COMPLETE_FEE: "ST295MNE41DC74QYCPRS8N37YYMC06N6Q3VQDZ6G1", STXCITY_TOKEN_DEPLOYMENT_FEE: "ST295MNE41DC74QYCPRS8N37YYMC06N6Q3VQDZ6G1", STXCITY_DEX_DEPLOYMENT_FEE: "ST295MNE41DC74QYCPRS8N37YYMC06N6Q3VQDZ6G1", - BITFLOW_CORE: "ST6BBNM7Q8GKDG2FMKRBZJCJ3SE4BWVC1YSF2XKD.xyk-core-v-1-2", + BITFLOW_CORE: "STTWD9SPRQVD3P733V89SV0P8RZRZNQADG034F0A.xyk-core-v-1-2", BITFLOW_STX_TOKEN: "ST295MNE41DC74QYCPRS8N37YYMC06N6Q3VQDZ6G1.token-stx-v-1-2", BITFLOW_FEE: "ST295MNE41DC74QYCPRS8N37YYMC06N6Q3VQDZ6G1", @@ -59,74 +59,78 @@ export const TRAITS: NetworkTraitsMap = { "SP3FBR2AGK5H9QBDH3EEN6DF8EK8JY7RX8QJ5SVTE.sip-010-trait-ft-standard.sip-010-trait", SIP09: "SP2PABAF9FTAJYNFZH93XENAJ8FVY99RRM50D2JG9.nft-trait.nft-trait", DAO_BASE: - "SPTWD9SPRQVD3P733V89SV0P8RZRZNQADJHHPME1.aibtcdev-dao-v1.aibtcdev-base-dao", + "SP29CK9990DQGE9RGTT1VEQTTYH8KY4E3JE5XP4EC.aibtcdev-dao-v1.aibtcdev-base-dao", DAO_PROPOSAL: - "SPTWD9SPRQVD3P733V89SV0P8RZRZNQADJHHPME1.aibtcdev-dao-traits-v1.proposal", + "SP29CK9990DQGE9RGTT1VEQTTYH8KY4E3JE5XP4EC.aibtcdev-dao-traits-v1.proposal", DAO_EXTENSION: - "SPTWD9SPRQVD3P733V89SV0P8RZRZNQADJHHPME1.aibtcdev-dao-traits-v1.extension", + "SP29CK9990DQGE9RGTT1VEQTTYH8KY4E3JE5XP4EC.aibtcdev-dao-traits-v1.extension", DAO_ACTION_PROPOSALS: - "SPTWD9SPRQVD3P733V89SV0P8RZRZNQADJHHPME1.aibtcdev-dao-traits-v1.action-proposals", + "SP29CK9990DQGE9RGTT1VEQTTYH8KY4E3JE5XP4EC.aibtcdev-dao-traits-v1.action-proposals", DAO_CORE_PROPOSALS: - "SPTWD9SPRQVD3P733V89SV0P8RZRZNQADJHHPME1.aibtcdev-dao-traits-v1.core-proposals", + "SP29CK9990DQGE9RGTT1VEQTTYH8KY4E3JE5XP4EC.aibtcdev-dao-traits-v1.core-proposals", DAO_TREASURY: - "SPTWD9SPRQVD3P733V89SV0P8RZRZNQADJHHPME1.aibtcdev-dao-traits-v1.treasury", + "SP29CK9990DQGE9RGTT1VEQTTYH8KY4E3JE5XP4EC.aibtcdev-dao-traits-v1.treasury", DAO_MESSAGING: - "SPTWD9SPRQVD3P733V89SV0P8RZRZNQADJHHPME1.aibtcdev-dao-traits-v1.messaging", + "SP29CK9990DQGE9RGTT1VEQTTYH8KY4E3JE5XP4EC.aibtcdev-dao-traits-v1.messaging", DAO_BANK_ACCOUNT: - "SPTWD9SPRQVD3P733V89SV0P8RZRZNQADJHHPME1.aibtcdev-dao-traits-v1.bank-account", + "SP29CK9990DQGE9RGTT1VEQTTYH8KY4E3JE5XP4EC.aibtcdev-dao-traits-v1.bank-account", DAO_RESOURCES: - "SPTWD9SPRQVD3P733V89SV0P8RZRZNQADJHHPME1.aibtcdev-dao-traits-v1.resources", + "SP29CK9990DQGE9RGTT1VEQTTYH8KY4E3JE5XP4EC.aibtcdev-dao-traits-v1.resources", DAO_INVOICES: - "SPTWD9SPRQVD3P733V89SV0P8RZRZNQADJHHPME1.aibtcdev-dao-traits-v1.invoices", + "SP29CK9990DQGE9RGTT1VEQTTYH8KY4E3JE5XP4EC.aibtcdev-dao-traits-v1.invoices", DAO_ACTION: - "SPTWD9SPRQVD3P733V89SV0P8RZRZNQADJHHPME1.aibtcdev-dao-traits-v1.action", + "SP29CK9990DQGE9RGTT1VEQTTYH8KY4E3JE5XP4EC.aibtcdev-dao-traits-v1.action", DAO_TOKEN_DEX: - "SPTWD9SPRQVD3P733V89SV0P8RZRZNQADJHHPME1.aibtcdev-dao-traits-v1.token-dex", + "SP29CK9990DQGE9RGTT1VEQTTYH8KY4E3JE5XP4EC.aibtcdev-dao-traits-v1.token-dex", DAO_TOKEN_OWNER: - "SPTWD9SPRQVD3P733V89SV0P8RZRZNQADJHHPME1.aibtcdev-dao-traits-v1.token-owner", + "SP29CK9990DQGE9RGTT1VEQTTYH8KY4E3JE5XP4EC.aibtcdev-dao-traits-v1.token-owner", DAO_TOKEN: - "SPTWD9SPRQVD3P733V89SV0P8RZRZNQADJHHPME1.aibtcdev-dao-traits-v1.token", + "SP29CK9990DQGE9RGTT1VEQTTYH8KY4E3JE5XP4EC.aibtcdev-dao-traits-v1.token", DAO_BITFLOW_POOL: - "SPTWD9SPRQVD3P733V89SV0P8RZRZNQADJHHPME1.aibtcdev-dao-traits-v1.bitflow-pool", + "SP29CK9990DQGE9RGTT1VEQTTYH8KY4E3JE5XP4EC.aibtcdev-dao-traits-v1.bitflow-pool", BITFLOW_POOL: "SM1793C4R5PZ4NS4VQ4WMP7SKKYVH8JZEWSZ9HCCR.xyk-pool-trait-v-1-2.xyk-pool-trait", + BITFLOW_SIP010: + "SM1793C4R5PZ4NS4VQ4WMP7SKKYVH8JZEWSZ9HCCR.sip-010-trait-ft-standard-v-1-1.sip-010-trait", }, testnet: { SIP10: - "ST6BBNM7Q8GKDG2FMKRBZJCJ3SE4BWVC1YSF2XKD.sip-010-trait-ft-standard.sip-010-trait", - SIP09: "ST6BBNM7Q8GKDG2FMKRBZJCJ3SE4BWVC1YSF2XKD.nft-trait.nft-trait", + "STTWD9SPRQVD3P733V89SV0P8RZRZNQADG034F0A.sip-010-trait-ft-standard.sip-010-trait", + SIP09: "STTWD9SPRQVD3P733V89SV0P8RZRZNQADG034F0A.nft-trait.nft-trait", DAO_BASE: - "ST6BBNM7Q8GKDG2FMKRBZJCJ3SE4BWVC1YSF2XKD.aibtcdev-dao-v1.aibtcdev-base-dao", + "STTWD9SPRQVD3P733V89SV0P8RZRZNQADG034F0A.aibtcdev-dao-v1.aibtcdev-base-dao", DAO_PROPOSAL: - "ST6BBNM7Q8GKDG2FMKRBZJCJ3SE4BWVC1YSF2XKD.aibtcdev-dao-traits-v1.proposal", + "STTWD9SPRQVD3P733V89SV0P8RZRZNQADG034F0A.aibtcdev-dao-traits-v1.proposal", DAO_EXTENSION: - "ST6BBNM7Q8GKDG2FMKRBZJCJ3SE4BWVC1YSF2XKD.aibtcdev-dao-traits-v1.extension", + "STTWD9SPRQVD3P733V89SV0P8RZRZNQADG034F0A.aibtcdev-dao-traits-v1.extension", DAO_ACTION_PROPOSALS: - "ST6BBNM7Q8GKDG2FMKRBZJCJ3SE4BWVC1YSF2XKD.aibtcdev-dao-traits-v1.action-proposals", + "STTWD9SPRQVD3P733V89SV0P8RZRZNQADG034F0A.aibtcdev-dao-traits-v1.action-proposals", DAO_CORE_PROPOSALS: - "ST6BBNM7Q8GKDG2FMKRBZJCJ3SE4BWVC1YSF2XKD.aibtcdev-dao-traits-v1.core-proposals", + "STTWD9SPRQVD3P733V89SV0P8RZRZNQADG034F0A.aibtcdev-dao-traits-v1.core-proposals", DAO_TREASURY: - "ST6BBNM7Q8GKDG2FMKRBZJCJ3SE4BWVC1YSF2XKD.aibtcdev-dao-traits-v1.treasury", + "STTWD9SPRQVD3P733V89SV0P8RZRZNQADG034F0A.aibtcdev-dao-traits-v1.treasury", DAO_MESSAGING: - "ST6BBNM7Q8GKDG2FMKRBZJCJ3SE4BWVC1YSF2XKD.aibtcdev-dao-traits-v1.messaging", + "STTWD9SPRQVD3P733V89SV0P8RZRZNQADG034F0A.aibtcdev-dao-traits-v1.messaging", DAO_BANK_ACCOUNT: - "ST6BBNM7Q8GKDG2FMKRBZJCJ3SE4BWVC1YSF2XKD.aibtcdev-dao-traits-v1.bank-account", + "STTWD9SPRQVD3P733V89SV0P8RZRZNQADG034F0A.aibtcdev-dao-traits-v1.bank-account", DAO_RESOURCES: - "ST6BBNM7Q8GKDG2FMKRBZJCJ3SE4BWVC1YSF2XKD.aibtcdev-dao-traits-v1.resources", + "STTWD9SPRQVD3P733V89SV0P8RZRZNQADG034F0A.aibtcdev-dao-traits-v1.resources", DAO_INVOICES: - "ST6BBNM7Q8GKDG2FMKRBZJCJ3SE4BWVC1YSF2XKD.aibtcdev-dao-traits-v1.invoices", + "STTWD9SPRQVD3P733V89SV0P8RZRZNQADG034F0A.aibtcdev-dao-traits-v1.invoices", DAO_ACTION: - "ST6BBNM7Q8GKDG2FMKRBZJCJ3SE4BWVC1YSF2XKD.aibtcdev-dao-traits-v1.action", + "STTWD9SPRQVD3P733V89SV0P8RZRZNQADG034F0A.aibtcdev-dao-traits-v1.action", DAO_TOKEN_DEX: - "ST6BBNM7Q8GKDG2FMKRBZJCJ3SE4BWVC1YSF2XKD.aibtcdev-dao-traits-v1.token-dex", + "STTWD9SPRQVD3P733V89SV0P8RZRZNQADG034F0A.aibtcdev-dao-traits-v1.token-dex", DAO_TOKEN_OWNER: - "ST6BBNM7Q8GKDG2FMKRBZJCJ3SE4BWVC1YSF2XKD.aibtcdev-dao-traits-v1.token-owner", + "STTWD9SPRQVD3P733V89SV0P8RZRZNQADG034F0A.aibtcdev-dao-traits-v1.token-owner", DAO_TOKEN: - "ST6BBNM7Q8GKDG2FMKRBZJCJ3SE4BWVC1YSF2XKD.aibtcdev-dao-traits-v1.token", + "STTWD9SPRQVD3P733V89SV0P8RZRZNQADG034F0A.aibtcdev-dao-traits-v1.token", DAO_BITFLOW_POOL: - "ST6BBNM7Q8GKDG2FMKRBZJCJ3SE4BWVC1YSF2XKD.aibtcdev-dao-traits-v1.bitflow-pool", + "STTWD9SPRQVD3P733V89SV0P8RZRZNQADG034F0A.aibtcdev-dao-traits-v1.bitflow-pool", BITFLOW_POOL: - "ST6BBNM7Q8GKDG2FMKRBZJCJ3SE4BWVC1YSF2XKD.xyk-pool-trait-v-1-2.xyk-pool-trait", + "STTWD9SPRQVD3P733V89SV0P8RZRZNQADG034F0A.xyk-pool-trait-v-1-2.xyk-pool-trait", + BITFLOW_SIP010: + "STTWD9SPRQVD3P733V89SV0P8RZRZNQADG034F0A.sip-010-trait-ft-standard.sip-010-trait", }, devnet: { SIP10: "", @@ -147,6 +151,7 @@ export const TRAITS: NetworkTraitsMap = { DAO_TOKEN: "", DAO_BITFLOW_POOL: "", BITFLOW_POOL: "", + BITFLOW_SIP010: "", }, mocknet: { SIP10: "", @@ -167,5 +172,6 @@ export const TRAITS: NetworkTraitsMap = { DAO_TOKEN: "", DAO_BITFLOW_POOL: "", BITFLOW_POOL: "", + BITFLOW_SIP010: "", }, }; diff --git a/src/stacks-contracts/deploy-dao.ts b/src/stacks-contracts/deploy-dao.ts index 056211d2..1a0103b3 100644 --- a/src/stacks-contracts/deploy-dao.ts +++ b/src/stacks-contracts/deploy-dao.ts @@ -114,9 +114,14 @@ async function main() { // Step 2 - generate remaining dao contracts + // set dao manifest, passed to proposal for dao construction + const daoManifest = + "This is where the DAO can put it's mission, purpose, and goals."; + const contracts = contractGenerator.generateDaoContracts( senderAddress, - tokenSymbol + tokenSymbol, + daoManifest ); // Sort contracts to ensure DAO_PROPOSAL_BOOTSTRAP is last diff --git a/src/stacks-contracts/services/contract-deployer.ts b/src/stacks-contracts/services/contract-deployer.ts index 64f6a0d7..6fae4499 100644 --- a/src/stacks-contracts/services/contract-deployer.ts +++ b/src/stacks-contracts/services/contract-deployer.ts @@ -45,7 +45,7 @@ export class ContractDeployer { anchorMode: AnchorMode.Any, postConditionMode: PostConditionMode.Allow, nonce: nonce !== undefined ? nonce : undefined, - fee: BigInt(100_000), // 0.1 STX + fee: BigInt(500_000), // 0.5 STX }; const transaction = await makeContractDeploy(deployOptions); diff --git a/src/stacks-contracts/services/contract-generator.ts b/src/stacks-contracts/services/contract-generator.ts index 2de1b778..d4993813 100644 --- a/src/stacks-contracts/services/contract-generator.ts +++ b/src/stacks-contracts/services/contract-generator.ts @@ -36,9 +36,19 @@ export class ContractGenerator { } // extension: aibtc-action-proposals - private generateActionProposalsContract(daoContractAddress: string): string { + private generateActionProposalsContract( + daoContractAddress: string, + tokenContractAddress: string, + tokenDexContractAddress: string, + tokenPoolContractAddress: string, + treasuryContractAddress: string + ): string { const data = { dao_contract_address: daoContractAddress, + token_contract_address: tokenContractAddress, + token_dex_contract_address: tokenDexContractAddress, + token_pool_contract_address: tokenPoolContractAddress, + treasury_contract_address: treasuryContractAddress, extension_trait: getTraitReference(this.network, "DAO_EXTENSION"), action_proposals_trait: getTraitReference( this.network, @@ -74,7 +84,7 @@ export class ContractGenerator { "DAO_BITFLOW_POOL" ), bitflow_pool_trait: getTraitReference(this.network, "BITFLOW_POOL"), - sip10_trait: getTraitReference(this.network, "SIP10"), + sip10_trait: getTraitReference(this.network, "BITFLOW_SIP010"), bitflow_xyk_core_address: getAddressReference( this.network, "BITFLOW_CORE" @@ -86,9 +96,19 @@ export class ContractGenerator { } // extension: aibtc-core-proposals - private generateCorePropasalsContract(daoContractAddress: string): string { + private generateCorePropasalsContract( + daoContractAddress: string, + tokenContractAddress: string, + tokenDexContractAddress: string, + tokenPoolContractAddress: string, + treasuryContractAddress: string + ): string { const data = { dao_contract_address: daoContractAddress, + token_contract_address: tokenContractAddress, + token_dex_contract_address: tokenDexContractAddress, + token_pool_contract_address: tokenPoolContractAddress, + treasury_contract_address: treasuryContractAddress, extension_trait: getTraitReference(this.network, "DAO_EXTENSION"), core_proposal_trait: getTraitReference( this.network, @@ -158,7 +178,7 @@ export class ContractGenerator { bitflow_core_contract: getAddressReference(this.network, "BITFLOW_CORE"), sip10_trait: getTraitReference(this.network, "SIP10"), token_dex_trait: getTraitReference(this.network, "DAO_TOKEN_DEX"), - token_contract: tokenContract, + token_contract_address: tokenContract, pool_contract: poolContract, bitflow_fee_address: getAddressReference(this.network, "BITFLOW_FEE"), bitflow_stx_token_address: getAddressReference( @@ -184,14 +204,11 @@ export class ContractGenerator { // extension: aibtc-token-owner private generateTokenOwnerContract( daoContractAddress: string, - tokenSymbol: string + tokenContractAddress: string ): string { - const tokenContract = `${ - this.senderAddress - }.${tokenSymbol.toLowerCase()}-stxcity`; const data = { dao_contract_address: daoContractAddress, - token_contract: tokenContract, + token_contract_address: tokenContractAddress, extension_trait: getTraitReference(this.network, "DAO_EXTENSION"), token_owner_trait: getTraitReference(this.network, "DAO_TOKEN_OWNER"), creator: this.senderAddress, @@ -432,11 +449,9 @@ export class ContractGenerator { // generated at runtime based on script parameters generateDaoContracts( senderAddress: string, - tokenSymbol: string + tokenSymbol: string, + daoManifest: string ): GeneratedDaoContracts { - // set dao manifest, passed to proposal for dao construction - const daoManifest = "This is where the dao manifest would go"; - // get contract names using token symbol const contractNames = generateContractNames(tokenSymbol); @@ -444,10 +459,16 @@ export class ContractGenerator { contractType: ContractType | ContractActionType ) => `${senderAddress}.${contractNames[contractType]}`; - // construct token contract address + // construct token related contract addresses const tokenContractAddress = generateContractPrincipal( ContractType.DAO_TOKEN ); + const tokenDexContractAddress = generateContractPrincipal( + ContractType.DAO_TOKEN_DEX + ); + const tokenPoolContractAddress = generateContractPrincipal( + ContractType.DAO_BITFLOW_POOL + ); // construct base dao contract address const baseDaoContractAddress = generateContractPrincipal( @@ -521,14 +542,22 @@ export class ContractGenerator { baseDaoContractAddress ); const coreProposalsContract = this.generateCorePropasalsContract( - baseDaoContractAddress + baseDaoContractAddress, + tokenContractAddress, + tokenDexContractAddress, + tokenPoolContractAddress, + treasuryContractAddress ); const actionProposalsContract = this.generateActionProposalsContract( - baseDaoContractAddress + baseDaoContractAddress, + tokenContractAddress, + tokenDexContractAddress, + tokenPoolContractAddress, + treasuryContractAddress ); const tokenOwnerContract = this.generateTokenOwnerContract( baseDaoContractAddress, - tokenSymbol + tokenContractAddress ); // generate action extension contract code diff --git a/src/stacks-contracts/templates/dao/extensions/actions/aibtc-action-add-resource.clar b/src/stacks-contracts/templates/dao/extensions/actions/aibtc-action-add-resource.clar index 6366e871..4c01df6c 100644 --- a/src/stacks-contracts/templates/dao/extensions/actions/aibtc-action-add-resource.clar +++ b/src/stacks-contracts/templates/dao/extensions/actions/aibtc-action-add-resource.clar @@ -21,6 +21,6 @@ (define-private (is-dao-or-extension) (ok (asserts! (or (is-eq tx-sender '<%= it.dao_contract_address %>) - (contract-call? '<%= it.dao_contract_address %> is-extension contract-caller)) ERR_NOT_DAO_OR_EXTENSION + (contract-call? '<%= it.dao_contract_address %> is-extension contract-caller)) ERR_UNAUTHORIZED )) ) diff --git a/src/stacks-contracts/templates/dao/extensions/actions/aibtc-action-allow-asset.clar b/src/stacks-contracts/templates/dao/extensions/actions/aibtc-action-allow-asset.clar index fcac65fe..880c7c69 100644 --- a/src/stacks-contracts/templates/dao/extensions/actions/aibtc-action-allow-asset.clar +++ b/src/stacks-contracts/templates/dao/extensions/actions/aibtc-action-allow-asset.clar @@ -18,6 +18,6 @@ (define-private (is-dao-or-extension) (ok (asserts! (or (is-eq tx-sender '<%= it.dao_contract_address %>) - (contract-call? '<%= it.dao_contract_address %> is-extension contract-caller)) ERR_NOT_DAO_OR_EXTENSION + (contract-call? '<%= it.dao_contract_address %> is-extension contract-caller)) ERR_UNAUTHORIZED )) ) diff --git a/src/stacks-contracts/templates/dao/extensions/actions/aibtc-action-send-message.clar b/src/stacks-contracts/templates/dao/extensions/actions/aibtc-action-send-message.clar index 1dfad744..0b87b91c 100644 --- a/src/stacks-contracts/templates/dao/extensions/actions/aibtc-action-send-message.clar +++ b/src/stacks-contracts/templates/dao/extensions/actions/aibtc-action-send-message.clar @@ -7,14 +7,17 @@ (define-public (callback (sender principal) (memo (buff 34))) (ok true)) (define-public (run (parameters (buff 2048))) - (begin + (let + ( + (message (unwrap! (from-consensus-buff? (string-ascii 2043) parameters) ERR_INVALID_PARAMS)) + ) (try! (is-dao-or-extension)) - (contract-call? '<%= it.messaging_contract_address %> send (unwrap! (from-consensus-buff? (string-ascii 2043) parameters) ERR_INVALID_PARAMS) true) + (contract-call? '<%= it.messaging_contract_address %> send message true) ) ) (define-private (is-dao-or-extension) (ok (asserts! (or (is-eq tx-sender '<%= it.dao_contract_address %>) - (contract-call? '<%= it.dao_contract_address %> is-extension contract-caller)) ERR_NOT_DAO_OR_EXTENSION + (contract-call? '<%= it.dao_contract_address %> is-extension contract-caller)) ERR_UNAUTHORIZED )) ) diff --git a/src/stacks-contracts/templates/dao/extensions/actions/aibtc-action-set-account-holder.clar b/src/stacks-contracts/templates/dao/extensions/actions/aibtc-action-set-account-holder.clar index cf3d43a0..660f0138 100644 --- a/src/stacks-contracts/templates/dao/extensions/actions/aibtc-action-set-account-holder.clar +++ b/src/stacks-contracts/templates/dao/extensions/actions/aibtc-action-set-account-holder.clar @@ -7,14 +7,17 @@ (define-public (callback (sender principal) (memo (buff 34))) (ok true)) (define-public (run (parameters (buff 2048))) - (begin + (let + ( + (accountHolder (unwrap! (from-consensus-buff? principal parameters) ERR_INVALID_PARAMS)) + ) (try! (is-dao-or-extension)) - (contract-call? .aibtc-bank-account set-account-holder (unwrap! (from-consensus-buff? principal parameters) ERR_INVALID_PARAMS)) + (contract-call? '<%= it.bank_account_contract_address %> set-account-holder accountHolder) ) ) (define-private (is-dao-or-extension) (ok (asserts! (or (is-eq tx-sender '<%= it.dao_contract_address %>) - (contract-call? '<%= it.dao_contract_address %> is-extension contract-caller)) ERR_NOT_DAO_OR_EXTENSION + (contract-call? '<%= it.dao_contract_address %> is-extension contract-caller)) ERR_UNAUTHORIZED )) ) \ No newline at end of file diff --git a/src/stacks-contracts/templates/dao/extensions/actions/aibtc-action-set-withdrawal-amount.clar b/src/stacks-contracts/templates/dao/extensions/actions/aibtc-action-set-withdrawal-amount.clar index 984acd86..93219c0d 100644 --- a/src/stacks-contracts/templates/dao/extensions/actions/aibtc-action-set-withdrawal-amount.clar +++ b/src/stacks-contracts/templates/dao/extensions/actions/aibtc-action-set-withdrawal-amount.clar @@ -22,6 +22,6 @@ (define-private (is-dao-or-extension) (ok (asserts! (or (is-eq tx-sender '<%= it.dao_contract_address %>) - (contract-call? '<%= it.dao_contract_address %> is-extension contract-caller)) ERR_NOT_DAO_OR_EXTENSION + (contract-call? '<%= it.dao_contract_address %> is-extension contract-caller)) ERR_UNAUTHORIZED )) ) diff --git a/src/stacks-contracts/templates/dao/extensions/actions/aibtc-action-set-withdrawal-period.clar b/src/stacks-contracts/templates/dao/extensions/actions/aibtc-action-set-withdrawal-period.clar index 0677916e..3c59bf5c 100644 --- a/src/stacks-contracts/templates/dao/extensions/actions/aibtc-action-set-withdrawal-period.clar +++ b/src/stacks-contracts/templates/dao/extensions/actions/aibtc-action-set-withdrawal-period.clar @@ -22,6 +22,6 @@ (define-private (is-dao-or-extension) (ok (asserts! (or (is-eq tx-sender '<%= it.dao_contract_address %>) - (contract-call? '<%= it.dao_contract_address %> is-extension contract-caller)) ERR_NOT_DAO_OR_EXTENSION + (contract-call? '<%= it.dao_contract_address %> is-extension contract-caller)) ERR_UNAUTHORIZED )) ) diff --git a/src/stacks-contracts/templates/dao/extensions/actions/aibtc-action-toggle-resource.clar b/src/stacks-contracts/templates/dao/extensions/actions/aibtc-action-toggle-resource.clar index d2271ee4..0d5381e9 100644 --- a/src/stacks-contracts/templates/dao/extensions/actions/aibtc-action-toggle-resource.clar +++ b/src/stacks-contracts/templates/dao/extensions/actions/aibtc-action-toggle-resource.clar @@ -18,6 +18,6 @@ (define-private (is-dao-or-extension) (ok (asserts! (or (is-eq tx-sender '<%= it.dao_contract_address %>) - (contract-call? '<%= it.dao_contract_address %> is-extension contract-caller)) ERR_NOT_DAO_OR_EXTENSION + (contract-call? '<%= it.dao_contract_address %> is-extension contract-caller)) ERR_UNAUTHORIZED )) ) diff --git a/src/stacks-contracts/templates/dao/extensions/aibtc-action-proposals.clar b/src/stacks-contracts/templates/dao/extensions/aibtc-action-proposals.clar index 047c2da6..611870ea 100644 --- a/src/stacks-contracts/templates/dao/extensions/aibtc-action-proposals.clar +++ b/src/stacks-contracts/templates/dao/extensions/aibtc-action-proposals.clar @@ -16,46 +16,29 @@ ;; (define-constant SELF (as-contract tx-sender)) (define-constant VOTING_PERIOD u144) ;; 144 Bitcoin blocks, ~1 day -(define-constant VOTING_QUORUM u66) ;; 66% of liquid supply (total supply - treasury) +(define-constant VOTING_QUORUM u66) ;; 66% of liquid supply -;; error messages - authorization +;; error messages (define-constant ERR_NOT_DAO_OR_EXTENSION (err u1000)) - -;; error messages - initialization -(define-constant ERR_NOT_INITIALIZED (err u1100)) - -;; error messages - treasury -(define-constant ERR_TREASURY_CANNOT_BE_SELF (err u1200)) -(define-constant ERR_TREASURY_MISMATCH (err u1201)) -(define-constant ERR_TREASURY_CANNOT_BE_SAME (err u1202)) - -;; error messages - voting token -(define-constant ERR_TOKEN_ALREADY_INITIALIZED (err u1300)) -(define-constant ERR_TOKEN_MISMATCH (err u1301)) -(define-constant ERR_INSUFFICIENT_BALANCE (err u1302)) -(define-constant ERR_TOKEN_CANNOT_BE_SELF (err u1303)) -(define-constant ERR_TOKEN_CANNOT_BE_SAME (err u1304)) - -;; error messages - proposals -(define-constant ERR_PROPOSAL_NOT_FOUND (err u1400)) -(define-constant ERR_PROPOSAL_STILL_ACTIVE (err u1401)) -(define-constant ERR_SAVING_PROPOSAL (err u1402)) -(define-constant ERR_PROPOSAL_ALREADY_CONCLUDED (err u1403)) - -;; error messages - voting -(define-constant ERR_VOTE_TOO_SOON (err u1500)) -(define-constant ERR_VOTE_TOO_LATE (err u1501)) -(define-constant ERR_ALREADY_VOTED (err u1502)) -(define-constant ERR_ZERO_VOTING_POWER (err u1503)) -(define-constant ERR_QUORUM_NOT_REACHED (err u1504)) - -;; error messages - actions -(define-constant ERR_INVALID_ACTION (err u1600)) +(define-constant ERR_INSUFFICIENT_BALANCE (err u1001)) +(define-constant ERR_FETCHING_TOKEN_DATA (err u1002)) +(define-constant ERR_PROPOSAL_NOT_FOUND (err u1003)) +(define-constant ERR_PROPOSAL_STILL_ACTIVE (err u1004)) +(define-constant ERR_SAVING_PROPOSAL (err u1005)) +(define-constant ERR_PROPOSAL_ALREADY_CONCLUDED (err u1006)) +(define-constant ERR_RETRIEVING_START_BLOCK_HASH (err u1007)) +(define-constant ERR_VOTE_TOO_SOON (err u1008)) +(define-constant ERR_VOTE_TOO_LATE (err u1009)) +(define-constant ERR_ALREADY_VOTED (err u1010)) +(define-constant ERR_INVALID_ACTION (err u1011)) + +;; contracts used for voting calculations +(define-constant VOTING_TOKEN_DEX '<%= it.token_dex_contract_address %>) +(define-constant VOTING_TOKEN_POOL '<%= it.token_pool_contract_address %>) +(define-constant VOTING_TREASURY '<%= it.treasury_contract_address %>) ;; data vars ;; -(define-data-var protocolTreasury principal SELF) ;; the treasury contract for protocol funds -(define-data-var votingToken principal SELF) ;; the FT contract used for voting (define-data-var proposalCount uint u0) ;; total number of proposals ;; data maps @@ -68,10 +51,12 @@ createdAt: uint, ;; block height caller: principal, ;; contract caller creator: principal, ;; proposal creator (tx-sender) - startBlock: uint, ;; block height - endBlock: uint, ;; block height + startBlockStx: uint, ;; block height for at-block calls + startBlock: uint, ;; burn block height + endBlock: uint, ;; burn block height votesFor: uint, ;; total votes for votesAgainst: uint, ;; total votes against + liquidTokens: uint, ;; liquid tokens concluded: bool, ;; has the proposal concluded passed: bool, ;; did the proposal pass } @@ -92,60 +77,15 @@ (ok true) ) -(define-public (set-protocol-treasury (treasury )) - (let - ( - (treasuryContract (contract-of treasury)) - ) - (try! (is-dao-or-extension)) - ;; cannot set treasury to self - (asserts! (not (is-eq treasuryContract SELF)) ERR_TREASURY_CANNOT_BE_SELF) - ;; cannot set treasury to same value - (asserts! (not (is-eq treasuryContract (var-get protocolTreasury))) ERR_TREASURY_CANNOT_BE_SAME) - (print { - notification: "set-protocol-treasury", - payload: { - treasury: treasuryContract - } - }) - (ok (var-set protocolTreasury treasuryContract)) - ) -) - -(define-public (set-voting-token (token )) - (let - ( - (tokenContract (contract-of token)) - ) - (try! (is-dao-or-extension)) - ;; cannot set token to self - (asserts! (not (is-eq tokenContract SELF)) ERR_TOKEN_CANNOT_BE_SELF) - ;; cannot set token to same value - (asserts! (not (is-eq tokenContract (var-get votingToken))) ERR_TOKEN_CANNOT_BE_SAME) - ;; cannot set token if already set once - (asserts! (is-eq (var-get votingToken) SELF) ERR_TOKEN_ALREADY_INITIALIZED) - (print { - notification: "set-voting-token", - payload: { - token: tokenContract - } - }) - (ok (var-set votingToken tokenContract)) - ) -) - -(define-public (propose-action (action ) (parameters (buff 2048)) (token )) +(define-public (propose-action (action ) (parameters (buff 2048))) (let ( - (tokenContract (contract-of token)) (newId (+ (var-get proposalCount) u1)) + (voterBalance (unwrap! (contract-call? '<%= it.token_contract_address %> get-balance tx-sender) ERR_FETCHING_TOKEN_DATA)) + (liquidTokens (try! (get-liquid-supply block-height))) ) - ;; required variables must be set - (asserts! (is-initialized) ERR_NOT_INITIALIZED) - ;; token matches set voting token - (asserts! (is-eq tokenContract (var-get votingToken)) ERR_TOKEN_MISMATCH) ;; caller has the required balance - (asserts! (> (try! (contract-call? token get-balance tx-sender)) u0) ERR_INSUFFICIENT_BALANCE) + (asserts! (> voterBalance u0) ERR_INSUFFICIENT_BALANCE) ;; print proposal creation event (print { notification: "propose-action", @@ -154,6 +94,8 @@ action: action, parameters: parameters, creator: tx-sender, + liquidTokens: liquidTokens, + startBlockStx: block-height, startBlock: burn-block-height, endBlock: (+ burn-block-height VOTING_PERIOD) } @@ -165,10 +107,12 @@ createdAt: burn-block-height, caller: contract-caller, creator: tx-sender, + startBlockStx: block-height, startBlock: burn-block-height, endBlock: (+ burn-block-height VOTING_PERIOD), votesFor: u0, votesAgainst: u0, + liquidTokens: liquidTokens, concluded: false, passed: false, }) ERR_SAVING_PROPOSAL) @@ -177,66 +121,53 @@ ) ) -(define-public (vote-on-proposal (proposalId uint) (token ) (vote bool)) +(define-public (vote-on-proposal (proposalId uint) (vote bool)) (let ( - (tokenContract (contract-of token)) - (senderBalance (try! (contract-call? token get-balance tx-sender))) + (proposalRecord (unwrap! (map-get? Proposals proposalId) ERR_PROPOSAL_NOT_FOUND)) + (proposalBlock (get startBlockStx proposalRecord)) + (proposalBlockHash (unwrap! (get-block-hash proposalBlock) ERR_RETRIEVING_START_BLOCK_HASH)) + (senderBalance (unwrap! (at-block proposalBlockHash (contract-call? '<%= it.token_contract_address %> get-balance tx-sender)) ERR_FETCHING_TOKEN_DATA)) ) - ;; required variables must be set - (asserts! (is-initialized) ERR_NOT_INITIALIZED) - ;; token matches set voting token - (asserts! (is-eq tokenContract (var-get votingToken)) ERR_TOKEN_MISMATCH) ;; caller has the required balance (asserts! (> senderBalance u0) ERR_INSUFFICIENT_BALANCE) - ;; get proposal record - (let - ( - (proposalRecord (unwrap! (map-get? Proposals proposalId) ERR_PROPOSAL_NOT_FOUND)) - ) - ;; proposal is still active - (asserts! (>= burn-block-height (get startBlock proposalRecord)) ERR_VOTE_TOO_SOON) - (asserts! (< burn-block-height (get endBlock proposalRecord)) ERR_VOTE_TOO_LATE) - ;; proposal not already concluded - (asserts! (not (get concluded proposalRecord)) ERR_PROPOSAL_ALREADY_CONCLUDED) - ;; vote not already cast - (asserts! (is-none (map-get? VotingRecords {proposalId: proposalId, voter: tx-sender})) ERR_ALREADY_VOTED) - ;; print vote event - (print { - notification: "vote-on-proposal", - payload: { - proposalId: proposalId, - voter: tx-sender, - amount: senderBalance - } - }) - ;; update the proposal record - (map-set Proposals proposalId - (if vote - (merge proposalRecord {votesFor: (+ (get votesFor proposalRecord) senderBalance)}) - (merge proposalRecord {votesAgainst: (+ (get votesAgainst proposalRecord) senderBalance)}) - ) + ;; proposal not still active + (asserts! (>= burn-block-height (get startBlock proposalRecord)) ERR_VOTE_TOO_SOON) + (asserts! (< burn-block-height (get endBlock proposalRecord)) ERR_VOTE_TOO_LATE) + ;; proposal not already concluded + (asserts! (not (get concluded proposalRecord)) ERR_PROPOSAL_ALREADY_CONCLUDED) + ;; vote not already cast + (asserts! (is-none (map-get? VotingRecords {proposalId: proposalId, voter: tx-sender})) ERR_ALREADY_VOTED) + ;; print vote event + (print { + notification: "vote-on-proposal", + payload: { + proposalId: proposalId, + voter: tx-sender, + amount: senderBalance + } + }) + ;; update the proposal record + (map-set Proposals proposalId + (if vote + (merge proposalRecord {votesFor: (+ (get votesFor proposalRecord) senderBalance)}) + (merge proposalRecord {votesAgainst: (+ (get votesAgainst proposalRecord) senderBalance)}) ) - ;; record the vote for the sender - (ok (map-set VotingRecords {proposalId: proposalId, voter: tx-sender} senderBalance)) ) + ;; record the vote for the sender + (ok (map-set VotingRecords {proposalId: proposalId, voter: tx-sender} senderBalance)) ) ) -(define-public (conclude-proposal (proposalId uint) (action ) (treasury ) (token )) +(define-public (conclude-proposal (proposalId uint) (action )) (let ( (proposalRecord (unwrap! (map-get? Proposals proposalId) ERR_PROPOSAL_NOT_FOUND)) - (tokenContract (contract-of token)) - (tokenTotalSupply (try! (contract-call? token get-total-supply))) - (treasuryContract (contract-of treasury)) - (treasuryBalance (try! (contract-call? token get-balance treasuryContract))) - (votePassed (> (get votesFor proposalRecord) (* tokenTotalSupply (- u100 treasuryBalance) VOTING_QUORUM))) + ;; if VOTING_QUORUM <= ((votesFor * 100) / liquidTokens) + (votePassed (<= VOTING_QUORUM (/ (* (get votesFor proposalRecord) u100) (get liquidTokens proposalRecord)))) ) - ;; required variables must be set - (asserts! (is-initialized) ERR_NOT_INITIALIZED) - ;; verify treasury matches protocol treasury - (asserts! (is-eq treasuryContract (var-get protocolTreasury)) ERR_TREASURY_MISMATCH) + ;; verify extension still active in dao + (try! (as-contract (is-dao-or-extension))) ;; proposal past end block height (asserts! (>= burn-block-height (get endBlock proposalRecord)) ERR_PROPOSAL_STILL_ACTIVE) ;; proposal not already concluded @@ -269,18 +200,22 @@ ;; read only functions ;; -(define-read-only (get-protocol-treasury) - (if (is-eq (var-get protocolTreasury) SELF) - none - (some (var-get protocolTreasury)) +(define-read-only (get-voting-power (who principal) (proposalId uint)) + (let + ( + (proposalRecord (unwrap! (map-get? Proposals proposalId) ERR_PROPOSAL_NOT_FOUND)) + (proposalBlockHash (unwrap! (get-block-hash (get startBlockStx proposalRecord)) ERR_RETRIEVING_START_BLOCK_HASH)) + ) + (at-block proposalBlockHash (contract-call? '<%= it.token_contract_address %> get-balance who)) ) ) -(define-read-only (get-voting-token) - (if (is-eq (var-get votingToken) SELF) - none - (some (var-get votingToken)) - ) +(define-read-only (get-linked-voting-contracts) + { + treasury: VOTING_TREASURY, + token-dex: VOTING_TOKEN_DEX, + token-pool: VOTING_TOKEN_POOL + } ) (define-read-only (get-proposal (proposalId uint)) @@ -291,14 +226,6 @@ (default-to u0 (map-get? VotingRecords {proposalId: proposalId, voter: voter})) ) -(define-read-only (is-initialized) - ;; check if the required variables are set - (not (or - (is-eq (var-get votingToken) SELF) - (is-eq (var-get protocolTreasury) SELF) - )) -) - (define-read-only (get-voting-period) VOTING_PERIOD ) @@ -320,3 +247,20 @@ )) ) +(define-private (get-block-hash (blockHeight uint)) + (get-block-info? id-header-hash blockHeight) +) + +(define-private (get-liquid-supply (blockHeight uint)) + (let + ( + (blockHash (unwrap! (get-block-hash blockHeight) ERR_RETRIEVING_START_BLOCK_HASH)) + (totalSupply (unwrap! (at-block blockHash (contract-call? '<%= it.token_contract_address %> get-total-supply)) ERR_FETCHING_TOKEN_DATA)) + (dexBalance (unwrap! (at-block blockHash (contract-call? '<%= it.token_contract_address %> get-balance VOTING_TOKEN_DEX)) ERR_FETCHING_TOKEN_DATA)) + (poolBalance (unwrap! (at-block blockHash (contract-call? '<%= it.token_contract_address %> get-balance VOTING_TOKEN_POOL)) ERR_FETCHING_TOKEN_DATA)) + (treasuryBalance (unwrap! (at-block blockHash (contract-call? '<%= it.token_contract_address %> get-balance VOTING_TREASURY)) ERR_FETCHING_TOKEN_DATA)) + ) + (ok (- totalSupply (+ dexBalance poolBalance treasuryBalance))) + ) +) + diff --git a/src/stacks-contracts/templates/dao/extensions/aibtc-core-proposals.clar b/src/stacks-contracts/templates/dao/extensions/aibtc-core-proposals.clar index 99fc8f20..e17164ff 100644 --- a/src/stacks-contracts/templates/dao/extensions/aibtc-core-proposals.clar +++ b/src/stacks-contracts/templates/dao/extensions/aibtc-core-proposals.clar @@ -17,43 +17,28 @@ (define-constant SELF (as-contract tx-sender)) (define-constant VOTING_PERIOD u144) ;; 144 Bitcoin blocks, ~1 day -(define-constant VOTING_QUORUM u95) ;; 95% of liquid supply (total supply - treasury) +(define-constant VOTING_QUORUM u95) ;; 95% of liquid supply +(define-constant DEPLOYED_AT burn-block-height) -;; error messages - authorization +;; error messages (define-constant ERR_NOT_DAO_OR_EXTENSION (err u3000)) - -;; error messages - initialization -(define-constant ERR_NOT_INITIALIZED (err u3100)) - -;; error messages - treasury -(define-constant ERR_TREASURY_CANNOT_BE_SELF (err u3200)) -(define-constant ERR_TREASURY_MISMATCH (err u3201)) -(define-constant ERR_TREASURY_CANNOT_BE_SAME (err u3202)) - -;; error messages - voting token -(define-constant ERR_TOKEN_ALREADY_INITIALIZED (err u3300)) -(define-constant ERR_TOKEN_MISMATCH (err u3301)) -(define-constant ERR_INSUFFICIENT_BALANCE (err u3302)) -(define-constant ERR_TOKEN_CANNOT_BE_SELF (err u3303)) -(define-constant ERR_TOKEN_CANNOT_BE_SAME (err u3304)) - -;; error messages - proposals -(define-constant ERR_PROPOSAL_NOT_FOUND (err u3400)) -(define-constant ERR_PROPOSAL_ALREADY_EXECUTED (err u3401)) -(define-constant ERR_PROPOSAL_STILL_ACTIVE (err u3402)) -(define-constant ERR_SAVING_PROPOSAL (err u3403)) -(define-constant ERR_PROPOSAL_ALREADY_CONCLUDED (err u3404)) - -;; error messages - voting -(define-constant ERR_VOTE_TOO_SOON (err u3500)) -(define-constant ERR_VOTE_TOO_LATE (err u3501)) -(define-constant ERR_ALREADY_VOTED (err u3502)) -(define-constant ERR_QUORUM_NOT_REACHED (err u3504)) - -;; data vars -;; -(define-data-var protocolTreasury principal SELF) ;; the treasury contract for protocol funds -(define-data-var votingToken principal SELF) ;; the FT contract used for voting +(define-constant ERR_FETCHING_TOKEN_DATA (err u3001)) +(define-constant ERR_INSUFFICIENT_BALANCE (err u3002)) +(define-constant ERR_PROPOSAL_NOT_FOUND (err u3003)) +(define-constant ERR_PROPOSAL_ALREADY_EXECUTED (err u3004)) +(define-constant ERR_PROPOSAL_STILL_ACTIVE (err u3005)) +(define-constant ERR_SAVING_PROPOSAL (err u3006)) +(define-constant ERR_PROPOSAL_ALREADY_CONCLUDED (err u3007)) +(define-constant ERR_RETRIEVING_START_BLOCK_HASH (err u3008)) +(define-constant ERR_VOTE_TOO_SOON (err u3009)) +(define-constant ERR_VOTE_TOO_LATE (err u3010)) +(define-constant ERR_ALREADY_VOTED (err u3011)) +(define-constant ERR_FIRST_VOTING_PERIOD (err u3012)) + +;; contracts used for voting calculations +(define-constant VOTING_TOKEN_DEX '<%= it.token_dex_contract_address %>) +(define-constant VOTING_TOKEN_POOL '<%= it.token_pool_contract_address %>) +(define-constant VOTING_TREASURY '<%= it.treasury_contract_address %>) ;; data maps ;; @@ -63,10 +48,12 @@ createdAt: uint, ;; block height caller: principal, ;; contract caller creator: principal, ;; proposal creator (tx-sender) - startBlock: uint, ;; block height - endBlock: uint, ;; block height + startBlockStx: uint, ;; block height for at-block calls + startBlock: uint, ;; burn block height + endBlock: uint, ;; burn block height votesFor: uint, ;; total votes for votesAgainst: uint, ;; total votes against + liquidTokens: uint, ;; liquid tokens concluded: bool, ;; has the proposal concluded passed: bool, ;; did the proposal pass } @@ -87,60 +74,16 @@ (ok true) ) -(define-public (set-protocol-treasury (treasury )) - (let - ( - (treasuryContract (contract-of treasury)) - ) - (try! (is-dao-or-extension)) - ;; cannot set treasury to self - (asserts! (not (is-eq treasuryContract SELF)) ERR_TREASURY_CANNOT_BE_SELF) - ;; cannot set treasury to same value - (asserts! (not (is-eq treasuryContract (var-get protocolTreasury))) ERR_TREASURY_CANNOT_BE_SAME) - (print { - notification: "set-protocol-treasury", - payload: { - treasury: treasuryContract - } - }) - (ok (var-set protocolTreasury treasuryContract)) - ) -) - -(define-public (set-voting-token (token )) - (let - ( - (tokenContract (contract-of token)) - ) - (try! (is-dao-or-extension)) - ;; cannot set token to self - (asserts! (not (is-eq tokenContract SELF)) ERR_TOKEN_CANNOT_BE_SELF) - ;; cannot set token to same value - (asserts! (not (is-eq tokenContract (var-get votingToken))) ERR_TOKEN_CANNOT_BE_SAME) - ;; cannot set token if already set once - (asserts! (is-eq (var-get votingToken) SELF) ERR_TOKEN_ALREADY_INITIALIZED) - (print { - notification: "set-voting-token", - payload: { - token: tokenContract - } - }) - (ok (var-set votingToken tokenContract)) - ) -) - -(define-public (create-proposal (proposal ) (token )) +(define-public (create-proposal (proposal )) (let ( (proposalContract (contract-of proposal)) - (tokenContract (contract-of token)) + (liquidTokens (try! (get-liquid-supply block-height))) ) - ;; required variables must be set - (asserts! (is-initialized) ERR_NOT_INITIALIZED) - ;; token matches set voting token - (asserts! (is-eq tokenContract (var-get votingToken)) ERR_TOKEN_MISMATCH) + ;; at least one voting period passed + (asserts! (>= burn-block-height (+ DEPLOYED_AT VOTING_PERIOD)) ERR_FIRST_VOTING_PERIOD) ;; caller has the required balance - (asserts! (> (try! (contract-call? token get-balance tx-sender)) u0) ERR_INSUFFICIENT_BALANCE) + (asserts! (> (unwrap! (contract-call? '<%= it.token_contract_address %> get-balance tx-sender) ERR_FETCHING_TOKEN_DATA) u0) ERR_INSUFFICIENT_BALANCE) ;; proposal was not already executed (asserts! (is-none (contract-call? '<%= it.dao_contract_address %> executed-at proposal)) ERR_PROPOSAL_ALREADY_EXECUTED) ;; print proposal creation event @@ -149,6 +92,8 @@ payload: { proposal: proposalContract, creator: tx-sender, + liquidTokens: liquidTokens, + startBlockStx: block-height, startBlock: burn-block-height, endBlock: (+ burn-block-height VOTING_PERIOD) } @@ -158,27 +103,26 @@ createdAt: burn-block-height, caller: contract-caller, creator: tx-sender, + startBlockStx: block-height, startBlock: burn-block-height, endBlock: (+ burn-block-height VOTING_PERIOD), votesFor: u0, votesAgainst: u0, + liquidTokens: liquidTokens, concluded: false, passed: false, }) ERR_SAVING_PROPOSAL)) )) -(define-public (vote-on-proposal (proposal ) (token ) (vote bool)) +(define-public (vote-on-proposal (proposal ) (vote bool)) (let ( (proposalContract (contract-of proposal)) (proposalRecord (unwrap! (map-get? Proposals proposalContract) ERR_PROPOSAL_NOT_FOUND)) - (tokenContract (contract-of token)) - (senderBalance (try! (contract-call? token get-balance tx-sender))) + (proposalBlock (get startBlockStx proposalRecord)) + (proposalBlockHash (unwrap! (get-block-hash proposalBlock) ERR_RETRIEVING_START_BLOCK_HASH)) + (senderBalance (unwrap! (at-block proposalBlockHash (contract-call? '<%= it.token_contract_address %> get-balance tx-sender)) ERR_FETCHING_TOKEN_DATA)) ) - ;; required variables must be set - (asserts! (is-initialized) ERR_NOT_INITIALIZED) - ;; token matches set voting token - (asserts! (is-eq tokenContract (var-get votingToken)) ERR_TOKEN_MISMATCH) ;; caller has the required balance (asserts! (> senderBalance u0) ERR_INSUFFICIENT_BALANCE) ;; proposal was not already executed @@ -211,21 +155,14 @@ ) ) -(define-public (conclude-proposal (proposal ) (treasury ) (token )) +(define-public (conclude-proposal (proposal )) (let ( (proposalContract (contract-of proposal)) (proposalRecord (unwrap! (map-get? Proposals proposalContract) ERR_PROPOSAL_NOT_FOUND)) - (tokenContract (contract-of token)) - (tokenTotalSupply (try! (contract-call? token get-total-supply))) - (treasuryContract (contract-of treasury)) - (treasuryBalance (try! (contract-call? token get-balance treasuryContract))) - (votePassed (> (get votesFor proposalRecord) (* tokenTotalSupply (- u100 treasuryBalance) VOTING_QUORUM))) + ;; if VOTING_QUORUM <= ((votesFor * 100) / liquidTokens) + (votePassed (<= VOTING_QUORUM (/ (* (get votesFor proposalRecord) u100) (get liquidTokens proposalRecord)))) ) - ;; required variables must be set - (asserts! (is-initialized) ERR_NOT_INITIALIZED) - ;; verify treasury matches protocol treasury - (asserts! (is-eq treasuryContract (var-get protocolTreasury)) ERR_TREASURY_MISMATCH) ;; proposal was not already executed (asserts! (is-none (contract-call? '<%= it.dao_contract_address %> executed-at proposal)) ERR_PROPOSAL_ALREADY_EXECUTED) ;; proposal past end block height @@ -257,18 +194,22 @@ ;; read only functions ;; -(define-read-only (get-protocol-treasury) - (if (is-eq (var-get protocolTreasury) SELF) - none - (some (var-get protocolTreasury)) +(define-read-only (get-voting-power (who principal) (proposal )) + (let + ( + (proposalRecord (unwrap! (map-get? Proposals (contract-of proposal)) ERR_PROPOSAL_NOT_FOUND)) + (proposalBlockHash (unwrap! (get-block-hash (get startBlockStx proposalRecord)) ERR_RETRIEVING_START_BLOCK_HASH)) + ) + (at-block proposalBlockHash (contract-call? '<%= it.token_contract_address %> get-balance who)) ) ) -(define-read-only (get-voting-token) - (if (is-eq (var-get votingToken) SELF) - none - (some (var-get votingToken)) - ) +(define-read-only (get-linked-voting-contracts) + { + treasury: VOTING_TREASURY, + token-dex: VOTING_TOKEN_DEX, + token-pool: VOTING_TOKEN_POOL + } ) (define-read-only (get-proposal (proposal principal)) @@ -279,14 +220,6 @@ (default-to u0 (map-get? VotingRecords {proposal: proposal, voter: voter})) ) -(define-read-only (is-initialized) - ;; check if the required variables are set - (not (or - (is-eq (var-get votingToken) SELF) - (is-eq (var-get protocolTreasury) SELF) - )) -) - (define-read-only (get-voting-period) VOTING_PERIOD ) @@ -303,3 +236,20 @@ (contract-call? '<%= it.dao_contract_address %> is-extension contract-caller)) ERR_NOT_DAO_OR_EXTENSION )) ) + +(define-private (get-block-hash (blockHeight uint)) + (get-block-info? id-header-hash blockHeight) +) + +(define-private (get-liquid-supply (blockHeight uint)) + (let + ( + (blockHash (unwrap! (get-block-hash blockHeight) ERR_RETRIEVING_START_BLOCK_HASH)) + (totalSupply (unwrap! (at-block blockHash (contract-call? '<%= it.token_contract_address %> get-total-supply)) ERR_FETCHING_TOKEN_DATA)) + (dexBalance (unwrap! (at-block blockHash (contract-call? '<%= it.token_contract_address %> get-balance VOTING_TOKEN_DEX)) ERR_FETCHING_TOKEN_DATA)) + (poolBalance (unwrap! (at-block blockHash (contract-call? '<%= it.token_contract_address %> get-balance VOTING_TOKEN_POOL)) ERR_FETCHING_TOKEN_DATA)) + (treasuryBalance (unwrap! (at-block blockHash (contract-call? '<%= it.token_contract_address %> get-balance VOTING_TREASURY)) ERR_FETCHING_TOKEN_DATA)) + ) + (ok (- totalSupply (+ dexBalance poolBalance treasuryBalance))) + ) +) diff --git a/src/stacks-contracts/templates/dao/extensions/aibtc-token-dex.clar b/src/stacks-contracts/templates/dao/extensions/aibtc-token-dex.clar index 44eb27e2..01b2a1cf 100644 --- a/src/stacks-contracts/templates/dao/extensions/aibtc-token-dex.clar +++ b/src/stacks-contracts/templates/dao/extensions/aibtc-token-dex.clar @@ -33,7 +33,7 @@ (define-constant STX_CITY_COMPLETE_FEE_WALLET '<%= it.stxcity_complete_fee %>) (define-constant BURN_ADDRESS '<%= it.burn %>) ;; burn mainnet -(define-constant allow-token '<%= it.token_contract %>) +(define-constant allow-token '<%= it.token_contract_address %>) ;; data vars (define-data-var tradable bool false) diff --git a/src/stacks-contracts/templates/dao/extensions/aibtc-token-owner.clar b/src/stacks-contracts/templates/dao/extensions/aibtc-token-owner.clar index 729985d0..c9e27326 100644 --- a/src/stacks-contracts/templates/dao/extensions/aibtc-token-owner.clar +++ b/src/stacks-contracts/templates/dao/extensions/aibtc-token-owner.clar @@ -10,7 +10,7 @@ ;; constants ;; -(define-constant ERR_UNAUTHORIZED (err u401)) +(define-constant ERR_UNAUTHORIZED (err u7000)) ;; public functions ;; @@ -24,7 +24,7 @@ ;; check if caller is authorized (try! (is-dao-or-extension)) ;; update token uri - (try! (as-contract (contract-call? '<%= it.token_contract %> set-token-uri value))) + (try! (as-contract (contract-call? '<%= it.token_contract_address %> set-token-uri value))) (ok true) ) ) @@ -34,7 +34,7 @@ ;; check if caller is authorized (try! (is-dao-or-extension)) ;; transfer ownership - (try! (as-contract (contract-call? '<%= it.token_contract %> transfer-ownership new-owner))) + (try! (as-contract (contract-call? '<%= it.token_contract_address %> transfer-ownership new-owner))) (ok true) ) ) diff --git a/src/stacks-contracts/templates/dao/proposals/aibtc-base-bootstrap-initialization.clar b/src/stacks-contracts/templates/dao/proposals/aibtc-base-bootstrap-initialization.clar index ca207fcf..c589678b 100644 --- a/src/stacks-contracts/templates/dao/proposals/aibtc-base-bootstrap-initialization.clar +++ b/src/stacks-contracts/templates/dao/proposals/aibtc-base-bootstrap-initialization.clar @@ -17,7 +17,7 @@ ) )) ;; set initial action proposals list - (try! (contract-call? .aibtcdev-base-dao set-extensions + (try! (contract-call? '<%= it.dao_contract_address %> set-extensions (list {extension: '<%= it.action_add_resource_contract_address %>, enabled: true} {extension: '<%= it.action_allow_asset_contract_address %>, enabled: true} @@ -28,10 +28,6 @@ {extension: '<%= it.action_toggle_resource_by_name_contract_address %>, enabled: true} ) )) - ;; initialize action proposals - (try! (contract-call? '<%= it.action_proposals_contract_address %> set-protocol-treasury '<%= it.treasury_contract_address %>)) - ;; initialize core proposals - (try! (contract-call? '<%= it.core_proposals_contract_address %> set-protocol-treasury '<%= it.treasury_contract_address %>)) ;; send DAO manifest as onchain message (try! (contract-call? '<%= it.messaging_contract_address %> send DAO_MANIFEST true)) ;; allow assets in treasury diff --git a/src/stacks-contracts/templates/dao/traits/aibtcdev-dao-traits-v1.clar b/src/stacks-contracts/templates/dao/traits/aibtcdev-dao-traits-v1.clar index 82febe83..03a9ac0e 100644 --- a/src/stacks-contracts/templates/dao/traits/aibtcdev-dao-traits-v1.clar +++ b/src/stacks-contracts/templates/dao/traits/aibtcdev-dao-traits-v1.clar @@ -4,8 +4,8 @@ ;; IMPORTS -(use-trait ft-trait .sip-010-trait-ft-standard.sip-010-trait) -(use-trait nft-trait .nft-trait.nft-trait) +(use-trait ft-trait <%= it.sip10_trait %>) +(use-trait nft-trait <%= it.sip09_trait %>) ;; CORE DAO TRAITS @@ -26,33 +26,21 @@ )) (define-trait action-proposals ( - ;; set the protocol treasury contract - ;; @param treasury the treasury contract principal - ;; @returns (response bool uint) - (set-protocol-treasury () (response bool uint)) - ;; set the voting token contract - ;; @param token the token contract principal - ;; @returns (response bool uint) - (set-voting-token () (response bool uint)) ;; propose a new action ;; @param action the action contract ;; @param parameters encoded action parameters - ;; @param token the voting token contract ;; @returns (response bool uint) - (propose-action ( (buff 2048) ) (response bool uint)) + (propose-action ( (buff 2048)) (response bool uint)) ;; vote on an existing proposal ;; @param proposal the proposal id - ;; @param token the voting token contract ;; @param vote true for yes, false for no ;; @returns (response bool uint) - (vote-on-proposal (uint bool) (response bool uint)) + (vote-on-proposal (uint bool) (response bool uint)) ;; conclude a proposal after voting period ;; @param proposal the proposal id ;; @param action the action contract - ;; @param treasury the treasury contract - ;; @param token the voting token contract ;; @returns (response bool uint) - (conclude-proposal (uint ) (response bool uint)) + (conclude-proposal (uint ) (response bool uint)) )) (define-trait bank-account ( @@ -88,31 +76,19 @@ )) (define-trait core-proposals ( - ;; set the protocol treasury contract - ;; @param treasury the treasury contract principal - ;; @returns (response bool uint) - (set-protocol-treasury () (response bool uint)) - ;; set the voting token contract - ;; @param token the token contract principal - ;; @returns (response bool uint) - (set-voting-token () (response bool uint)) ;; create a new proposal ;; @param proposal the proposal contract - ;; @param token the voting token contract ;; @returns (response bool uint) - (create-proposal ( ) (response bool uint)) + (create-proposal () (response bool uint)) ;; vote on an existing proposal ;; @param proposal the proposal contract - ;; @param token the voting token contract ;; @param vote true for yes, false for no ;; @returns (response bool uint) - (vote-on-proposal ( bool) (response bool uint)) + (vote-on-proposal ( bool) (response bool uint)) ;; conclude a proposal after voting period ;; @param proposal the proposal contract - ;; @param treasury the treasury contract - ;; @param token the voting token contract ;; @returns (response bool uint) - (conclude-proposal ( ) (response bool uint)) + (conclude-proposal () (response bool uint)) )) (define-trait messaging ( diff --git a/src/types/index.ts b/src/types/index.ts index 83a8ed20..da79aa30 100644 --- a/src/types/index.ts +++ b/src/types/index.ts @@ -22,6 +22,7 @@ export type NetworkTraits = { DAO_TOKEN: string; DAO_BITFLOW_POOL: string; BITFLOW_POOL: string; + BITFLOW_SIP010: string; }; export type NetworkTraitsMap = {