O Sputnik-DAO adotou um modelo de design de fábrica criativa para implementar a criação e gestão unificada do (DAO) de organizações autônomas descentralizadas na plataforma.
Este artigo irá detalhar a implementação do design do modelo de fábrica da plataforma Sputnik-DAO ( sputnikdao-factory ).
O repositório de código-fonte correspondente ao contrato está localizado em:
2. Introdução às funcionalidades do módulo DAPP
A página DAPP da plataforma Sputnik DAO já tem várias organizações autônomas descentralizadas que criaram e personalizaram seus próprios objetos de instância DAO ( contrato Sputnikdaov2 ).
Até março de 2022, a DAO mais ativa criada na plataforma é a news.sputnik-dao.near, com 3051 propostas (proposals) atualmente em votação pública ou com status encerrado.
Através do NEAR Explorer, pode-se descobrir que os contratos de instância DAO da plataforma são implantados uniformemente pelo contrato sputnik-dao.near( e pelo contrato sputnikdao-factory).
Ou seja, todos os contratos de instância DAO criados na plataforma Sputnik DAO são implantados sob as subcontas da conta NEAR, por exemplo:
pcp.sputnik-dao.near
test-dao-bro.sputnik-dao.near
blaqkstereo.sputnik-dao.near
octopode-dao.sputnik-dao.near
As organizações descentralizadas podem iniciar transações publicamente na mainnet NEAR, chamando o método create() fornecido pelo contrato sputnikdao-factory, para criar novas instâncias de DAO.
3. Análise do código do contrato sputnikdao-factory
3.1 Criar DAO
O estado do contrato sputnikdao-factory é composto principalmente por duas partes:
factory_manager: A lógica interna principal do contrato é implementada, fornecendo uma série de métodos para criar/excluir/atualizar instâncias de DAO.
daos: utiliza uma estrutura de dados de conjunto, que registra todos os endereços de conta NEAR dos instâncias de DAO criadas na história desta plataforma.
O método create() do contrato sputnikdao-factory usado para criar instâncias de DAO é definido da seguinte forma:
implementação específica de factory_manager.create_contract:
ferrugem
pub fn create_contract(
&self,
code_hash: Base58CryptoHash,
account_id: AccountId,
new_method: &str,
args: [u8],
callback_method: &str,
callback_args: &[u8],
) {
let code_hash: CryptoHash = code_hash.into();
let attached_deposit = env::attached_deposit();
let factory_account_id = env::current_account_id().as_bytes().to_vec();
let account_id = account_id.as_bytes().to_vec();
inseguro {
// Verifique se tal contrato existe.
assert_eq!(
sys::storage_has_key(code_hash.len() como _, code_hash.as_ptr() como _),
1,
'Contrato não existe'
);
// Carregar o código wasm de entrada ( no registro 0.
sys::storage_read)code_hash.len(( as _, code_hash.as_ptr)( as _, 0);
// agendar uma tx Promise para account_id
let promise_id =
sys::promise_batch_create)account_id.len(( como _, account_id.as_ptr)( como _);
// crie a conta primeiro.
sys::promise_batch_action_create_account)promise_id(;
// transferir depósito anexado.
sys::promise_batch_action_transfer)promise_id, &attached_deposit as *const u128 as _(;
// implantar contrato )o código é retirado do registro 0(.
sys::promise_batch_action_deploy_contract)promise_id, u64::MAX como _, 0(;
// chamar novo com os argumentos dados.
sys::promise_batch_action_function_call)
promise_id,
new_method.len(( as _,
new_method.as_ptr)( as _,
args.len)( as _,
args.as_ptr)( como _,
&NO_DEPOSIT como *const u128 como _,
CREATE_CALL_GAS.0,
);
// anexar callback à fábrica.
let _ = sys::promise_then)
promise_id,
factory_account_id.len(( como _,
factory_account_id.as_ptr)( as _,
callback_method.len)( as _,
callback_method.as_ptr)( as _,
callback_args.len)( as _,
callback_args.as_ptr)( as _,
&NO_DEPOSIT as *const u128 as _,
ON_CREATE_CALL_GAS.0,
);
sys::promise_return)promise_id(;
}
}
A interface de contrato fornecida pelo contrato da fábrica update)###:
ferrugem
/// Tenta atualizar a conta dada criada por esta fábrica para o código especificado.
pub fn update(&self, account_id: AccountId, code_hash: Base58CryptoHash) {
let caller_id = env::predecessor_account_id();
assert!(
caller_id == self.get_owner)( || caller_id == account_id,
'Deve ser atualizado pelo proprietário da fábrica ou pelo próprio DAO'
(;
assert!)
self.daos.contains)&account_id(,
'Deve ser um contrato criado pela fábrica'
(;
self.factory_manager
.atualizar_contrato)id_conta, hash_codigo, 'atualizar');
}
factory_manager.update_contract() detalhes do processamento:
ferrugem
/// Força a atualização do contrato dado.
/// O contrato deve suportar atualização por fábrica para isso através de verificação de permissões.
pub fn update_contract(
&self,
account_id: AccountId,
code_hash: Base58CryptoHash,
method_name: &str,
) {
let code_hash: CryptoHash = code_hash.into();
let account_id = account_id.as_bytes().to_vec();
inseguro {
// Verifique se tal contrato existe.
assert!(env::storage_has_key)&code_hash(, 'O contrato não existe'(;
// Carregar o hash do armazenamento.
sys::storage_read)code_hash.len)( as _, code_hash.as_ptr() as _, 0(;
// Criar uma promessa em relação à conta dada.
let promise_id =
sys::promise_batch_create)account_id.len)( como _, account_id.as_ptr() como _(;
// Chamar o método de atualização, que também deve lidar com migrações.
sys::promise_batch_action_function_call)
promise_id,
method_name.len)( as _,
method_name.as_ptr() como _,
u64::MAX como _,
0,
&NO_DEPOSIT as *const u128 as _,
(env::prepaid_gas)( - env::used_gas() - GAS_UPDATE_LEFTOVER(.0,);
sys::promise_return)promise_id);
}
}
4. Análise de Segurança do Contrato Factory Sputnik-DAO
A segurança do contrato da Sputnik-DAO Factory é garantida principalmente pelos seguintes aspectos:
Controle de permissões: Métodos do tipo view abertos do contrato não devem modificar as variáveis de estado do contrato, ou seja, o primeiro parâmetro da definição do método deve ser definido como &self, e não &mut self.
Controle de permissões: funções privilegiadas abertas do contrato, essas funções só podem ser executadas pelo proprietário do contrato ( ou pela conta do contrato DAO ), e há uma assertion correspondente no método.
Tratamento de erros: O contrato do Sputnik-DAO Factory implementa mecanismos de tratamento de erros razoáveis para as possíveis situações de exceção que possam ocorrer. Por exemplo, quando um usuário utiliza o contrato Factory para criar uma nova instância de contrato DAO, será feita uma verificação final para garantir que todos os passos de criação foram executados de forma normal e completa, caso contrário, não deverá causar prejuízos ao usuário.
Esta página pode conter conteúdo de terceiros, que é fornecido apenas para fins informativos (não para representações/garantias) e não deve ser considerada como um endosso de suas opiniões pela Gate nem como aconselhamento financeiro ou profissional. Consulte a Isenção de responsabilidade para obter detalhes.
13 Curtidas
Recompensa
13
7
Repostar
Compartilhar
Comentário
0/400
GamefiEscapeArtist
· 07-26 22:26
O que há de interessante no modelo de fábrica entediante?
Análise do contrato da fábrica Sputnik DAO: Mecanismos centrais para criar e atualizar DAOs
Interpretação do contrato da fábrica Sputnik DAO
1. Contrato da fábrica Sputnik-DAO
O Sputnik-DAO adotou um modelo de design de fábrica criativa para implementar a criação e gestão unificada do (DAO) de organizações autônomas descentralizadas na plataforma.
Este artigo irá detalhar a implementação do design do modelo de fábrica da plataforma Sputnik-DAO ( sputnikdao-factory ).
O repositório de código-fonte correspondente ao contrato está localizado em:
2. Introdução às funcionalidades do módulo DAPP
A página DAPP da plataforma Sputnik DAO já tem várias organizações autônomas descentralizadas que criaram e personalizaram seus próprios objetos de instância DAO ( contrato Sputnikdaov2 ).
Até março de 2022, a DAO mais ativa criada na plataforma é a news.sputnik-dao.near, com 3051 propostas (proposals) atualmente em votação pública ou com status encerrado.
Através do NEAR Explorer, pode-se descobrir que os contratos de instância DAO da plataforma são implantados uniformemente pelo contrato sputnik-dao.near( e pelo contrato sputnikdao-factory).
Ou seja, todos os contratos de instância DAO criados na plataforma Sputnik DAO são implantados sob as subcontas da conta NEAR, por exemplo:
As organizações descentralizadas podem iniciar transações publicamente na mainnet NEAR, chamando o método create() fornecido pelo contrato sputnikdao-factory, para criar novas instâncias de DAO.
3. Análise do código do contrato sputnikdao-factory
3.1 Criar DAO
O estado do contrato sputnikdao-factory é composto principalmente por duas partes:
ferrugem pub struct SputnikDAOFactory { factory_manager: FactoryManager, daos: UnorderedSet\u003caccountid\u003e, }
factory_manager: A lógica interna principal do contrato é implementada, fornecendo uma série de métodos para criar/excluir/atualizar instâncias de DAO.
daos: utiliza uma estrutura de dados de conjunto, que registra todos os endereços de conta NEAR dos instâncias de DAO criadas na história desta plataforma.
O método create() do contrato sputnikdao-factory usado para criar instâncias de DAO é definido da seguinte forma:
ferrugem #[payable] pub fn create(&mut self, name: AccountId, args: Base64VecU8) { let account_id: AccountId = format!('{}.{}', name, env::current_account_id()) .parse() .unwrap(); let callback_args = serde_json::to_vec(&json!({ 'account_id': account_id, 'attached_deposit': U128(env::attached_deposit()), 'predecessor_account_id': env::predecessor_account_id() })) .expect('Falha ao serializar'); self.factory_manager.create_contract( self.get_default_code_hash(), account_id, 'novo', &args.0, 'on_create', &callback_args, ); }
implementação específica de factory_manager.create_contract:
ferrugem pub fn create_contract( &self, code_hash: Base58CryptoHash, account_id: AccountId, new_method: &str, args: [u8], callback_method: &str, callback_args: &[u8], ) { let code_hash: CryptoHash = code_hash.into(); let attached_deposit = env::attached_deposit(); let factory_account_id = env::current_account_id().as_bytes().to_vec(); let account_id = account_id.as_bytes().to_vec(); inseguro { // Verifique se tal contrato existe. assert_eq!( sys::storage_has_key(code_hash.len() como _, code_hash.as_ptr() como _), 1, 'Contrato não existe' ); // Carregar o código wasm de entrada ( no registro 0. sys::storage_read)code_hash.len(( as _, code_hash.as_ptr)( as _, 0); // agendar uma tx Promise para account_id let promise_id = sys::promise_batch_create)account_id.len(( como _, account_id.as_ptr)( como _); // crie a conta primeiro. sys::promise_batch_action_create_account)promise_id(; // transferir depósito anexado. sys::promise_batch_action_transfer)promise_id, &attached_deposit as *const u128 as _(; // implantar contrato )o código é retirado do registro 0(. sys::promise_batch_action_deploy_contract)promise_id, u64::MAX como _, 0(; // chamar novo com os argumentos dados. sys::promise_batch_action_function_call) promise_id, new_method.len(( as _, new_method.as_ptr)( as _, args.len)( as _, args.as_ptr)( como _, &NO_DEPOSIT como *const u128 como _, CREATE_CALL_GAS.0, ); // anexar callback à fábrica. let _ = sys::promise_then) promise_id, factory_account_id.len(( como _, factory_account_id.as_ptr)( as _, callback_method.len)( as _, callback_method.as_ptr)( as _, callback_args.len)( as _, callback_args.as_ptr)( as _, &NO_DEPOSIT as *const u128 as _, ON_CREATE_CALL_GAS.0, ); sys::promise_return)promise_id(; } }
![])https://img-cdn.gateio.im/webp-social/moments-373080ddb66a4cb83e0722b387056be0.webp(
Implementação do código interno da função de callback on_create:
ferrugem #) pub fn on_create[private] &mut self, account_id: AccountId, attached_deposit: U128, predecessor_account_id: AccountId, bool { se near_sdk::is_promise_success() { self.daos.insert(&account_id); verdadeiro } else { Promise::new(predecessor_account_id).transfer(attached_deposit.0); falso } }
( Atualização 3.2 DAO
A interface de contrato fornecida pelo contrato da fábrica update)###:
ferrugem /// Tenta atualizar a conta dada criada por esta fábrica para o código especificado. pub fn update(&self, account_id: AccountId, code_hash: Base58CryptoHash) { let caller_id = env::predecessor_account_id(); assert!( caller_id == self.get_owner)( || caller_id == account_id, 'Deve ser atualizado pelo proprietário da fábrica ou pelo próprio DAO' (; assert!) self.daos.contains)&account_id(, 'Deve ser um contrato criado pela fábrica' (; self.factory_manager .atualizar_contrato)id_conta, hash_codigo, 'atualizar'); }
factory_manager.update_contract() detalhes do processamento:
ferrugem /// Força a atualização do contrato dado. /// O contrato deve suportar atualização por fábrica para isso através de verificação de permissões. pub fn update_contract( &self, account_id: AccountId, code_hash: Base58CryptoHash, method_name: &str, ) { let code_hash: CryptoHash = code_hash.into(); let account_id = account_id.as_bytes().to_vec(); inseguro { // Verifique se tal contrato existe. assert!(env::storage_has_key)&code_hash(, 'O contrato não existe'(; // Carregar o hash do armazenamento. sys::storage_read)code_hash.len)( as _, code_hash.as_ptr() as _, 0(; // Criar uma promessa em relação à conta dada. let promise_id = sys::promise_batch_create)account_id.len)( como _, account_id.as_ptr() como _(; // Chamar o método de atualização, que também deve lidar com migrações. sys::promise_batch_action_function_call) promise_id, method_name.len)( as _, method_name.as_ptr() como _, u64::MAX como _, 0, &NO_DEPOSIT as *const u128 as _, (env::prepaid_gas)( - env::used_gas() - GAS_UPDATE_LEFTOVER(.0,); sys::promise_return)promise_id); } }
4. Análise de Segurança do Contrato Factory Sputnik-DAO
A segurança do contrato da Sputnik-DAO Factory é garantida principalmente pelos seguintes aspectos:
Controle de permissões: Métodos do tipo view abertos do contrato não devem modificar as variáveis de estado do contrato, ou seja, o primeiro parâmetro da definição do método deve ser definido como &self, e não &mut self.
Controle de permissões: funções privilegiadas abertas do contrato, essas funções só podem ser executadas pelo proprietário do contrato ( ou pela conta do contrato DAO ), e há uma assertion correspondente no método.
Tratamento de erros: O contrato do Sputnik-DAO Factory implementa mecanismos de tratamento de erros razoáveis para as possíveis situações de exceção que possam ocorrer. Por exemplo, quando um usuário utiliza o contrato Factory para criar uma nova instância de contrato DAO, será feita uma verificação final para garantir que todos os passos de criação foram executados de forma normal e completa, caso contrário, não deverá causar prejuízos ao usuário.