Hoje vamos ver duas das plataformas de contratos inteligentes mais promissoras do mundo – NEAR Protocol e Solana. Embora o Ethereum ainda domine esse mercado, o fato é que sua falta de escalabilidade e altas taxas forçaram a maioria dos desenvolvedores a procurar alternativas viáveis. Near e Solana emergiram como os dois primeiros colocados.
O que é Solana?
A solana foi fundada em 2017 por Anatoly Yakovenko, que já havia trabalhado na DropBox. Yakovenko, junto com Eric Williams e CTO Greg Fritzgerald, criou Solana para resolver os problemas existentes em Bitcoin e Ethereum. O projeto atraiu investimentos da Multicoin Capital, Foundation Capital, SLOW Capital, CMCC Global, Abstract Ventures e muito mais.
Características da blockchain Solana
- 50.000 transações por segundo e tempo de criação de bloco de 0,4 segundos
- O sistema pode fornecer 28,4 milhões de transações por segundo em uma rede de 40 gigabits.
- Solana usa o algoritmo de consenso Proof-of-History.
Como funciona a Prova de Histórico (PoH)?
Em uma rede descentralizada que se espalha por uma grande área, o consenso é essencial. O Bitcoin usa o consenso de prova de trabalho (PoW – Proof of Work) para cuidar do consenso. Embora o método seja altamente seguro, é difícil não ignorar seu problema mais significativo – a falta de escalabilidade. Não se esqueça que o Bitcoin só pode fazer 7 transações por segundo.
Solana usa prova de história (PoH – Proof of History), em que cria registros históricos para provar que um evento ocorre durante um momento específico no tempo. Aqui estão alguns pontos que você precisa ter em mente:
- O algoritmo usa uma função de atraso verificável de alta frequência que requer um certo número de etapas sequenciais para terminar.
- As transações ou eventos cronometrados na rede serão designados como uma contagem única de hash a, que pode ser verificada publicamente.
- A contagem permite que a rede saiba exatamente quando a transação ou o evento aconteceu.
- Cada nó possui um relógio criptográfico que ajuda a rastrear o tempo da rede e a ordem dos eventos.
Devido ao PoH, a rede Solana suporta 50.000 transações por segundo durante a execução com GPUs.
O que é um Cluster Solana?
Um cluster é um conjunto de computadores de propriedade independente trabalhando juntos e pode ser visto como um sistema singular. As principais características do Cluster são as seguintes:
- Eles ajudam a verificar a saída de programas não confiáveis enviados pelo usuário.
- Mantém um registro de qualquer transação ou evento que um usuário faz.
- Ele rastreia quais computadores fizeram um trabalho significativo para manter a rede funcionando.
- Ele rastreia a posse de ativos do mundo real.
Qual dos seguintes utiliza sharding?
Programação em Solana
Os contratos inteligentes em Solana são escritos em Rust ou C e compilados para bytecode Berkeley Packet Filter (BPF). Como existem mais ferramentas disponíveis, é recomendável que você codifique em Rust. Iniciantes devem codificar seus programas usando o framework Anchor, que simplifica a execução.
Solana tem um modelo de conta exclusivo que é semelhante aos arquivos do sistema operacional Linux. Eles podem conter quaisquer dados arbitrários e também conter metadados sobre como podem ser acessados. Tenha em mente, porém, que as contas têm um tamanho fixo e não podem ser redimensionadas.
O modelo de programação atual da Solana pode forçá-lo a mover a lógica do aplicativo para fora da cadeia ou modificar a funcionalidade para ser ineficiente e limitada pelo tamanho fixo da conta.
Qual das opções a seguir é parte integrante de Solana?
Exemplo de contrato
#![feature(proc_macro_hygiene)]
use anchor_lang::prelude::*;
use anchor_spl::token::{self, TokenAccount, Transfer};
#[program]
pub mod plutocratic_hosting {
use super::*;
/// Initialize a new contract with initialized content.
#[access_control(Initialize::validate(&ctx, nonce))]
pub fn initialize(
ctx: Context<Initialize>,
price: u64,
content: String,
nonce: u8,
) -> ProgramResult {
// Transfer funds to the contract vault.
let cpi_accounts = Transfer {
from: ctx.accounts.from.to_account_info().clone(),
to: ctx.accounts.vault.to_account_info().clone(),
authority: ctx.accounts.owner.clone(),
};
let cpi_program = ctx.accounts.token_program.clone();
let cpi_ctx = CpiContext::new(cpi_program, cpi_accounts);
token::transfer(cpi_ctx, price)?;
// Initialize the content data.
let content_record = &mut ctx.accounts.content;
content_record.price = price;
content_record.content = content;
content_record.nonce = nonce;
content_record.owner = *ctx.accounts.owner.to_account_info().key;
content_record.vault = *ctx.accounts.vault.to_account_info().key;
Ok(())
}
/// Purchase content address for new price, if transferring more tokens.
#[access_control(check_funds(&ctx.accounts.content, price))]
pub fn purchase(ctx: Context<Purchase>, price: u64, content: String) -> ProgramResult {
// Transfer funds from contract back to owner.
let seeds = &[
ctx.accounts.content.to_account_info().key.as_ref(),
&[ctx.accounts.content.nonce],
];
let signer = &[&seeds[..]];
let cpi_accounts = Transfer {
from: ctx.accounts.vault.to_account_info().clone(),
to: ctx.accounts.owner_token.to_account_info().clone(),
authority: ctx.accounts.contract_signer.clone(),
};
let cpi_program = ctx.accounts.token_program.clone();
let cpi_ctx = CpiContext::new_with_signer(cpi_program, cpi_accounts, signer);
token::transfer(cpi_ctx, ctx.accounts.content.price)?;
// Transfer funds from new owner to contract.
let cpi_accounts = Transfer {
from: ctx.accounts.new_owner_token.to_account_info().clone(),
to: ctx.accounts.vault.to_account_info().clone(),
authority: ctx.accounts.new_owner.clone(),
};
let cpi_program = ctx.accounts.token_program.clone();
let cpi_ctx = CpiContext::new(cpi_program, cpi_accounts);
token::transfer(cpi_ctx, price)?;
// Overwrite content
let content_record = &mut ctx.accounts.content;
content_record.price = price;
content_record.content = content;
content_record.owner = *ctx.accounts.new_owner.to_account_info().key;
Ok(())
}
}
#[account]
pub struct ContentRecord {
/// Price at which the current content is owned.
pub price: u64,
/// Content Data.
pub content: String,
/// Public key of current owner of the content.
pub owner: Pubkey,
/// Address for token program of funds locked in contract.
pub vault: Pubkey,
/// Nonce for the content, to create valid program derived addresses.
pub nonce: u8,
}
#[derive(Accounts)]
pub struct Initialize<'info> {
#[account(init)]
content: ProgramAccount<'info, ContentRecord>,
#[account(mut, "&vault.owner == contract_signer.key")]
vault: CpiAccount<'info, TokenAccount>,
/// Program derived address for the contract.
contract_signer: AccountInfo<'info>,
/// Token account the contract is made from.
#[account(mut, has_one = owner)]
from: CpiAccount<'info, TokenAccount>,
/// Owner of the `from` token account.
owner: AccountInfo<'info>,
token_program: AccountInfo<'info>,
rent: Sysvar<'info, Rent>,
}
impl<'info> Initialize<'info> {
pub fn validate(ctx: &Context<Self>, nonce: u8) -> Result<()> {
let signer = Pubkey::create_program_address(
&[
ctx.accounts.content.to_account_info().key.as_ref(),
&[nonce],
],
ctx.program_id,
)
.map_err(|_| ErrorCode::InvalidNonce)?;
if &signer != ctx.accounts.contract_signer.to_account_info().key {
return Err(ErrorCode::InvalidSigner.into());
}
Ok(())
}
}
#[derive(Accounts)]
pub struct Purchase<'info> {
#[account(mut, has_one = vault)]
content: ProgramAccount<'info, ContentRecord>,
#[account(mut)]
vault: CpiAccount<'info, TokenAccount>,
#[account(seeds = [
content.to_account_info().key.as_ref(),
&[content.nonce],
])]
contract_signer: AccountInfo<'info>,
#[account(mut, has_one = owner)]
owner_token: CpiAccount<'info, TokenAccount>,
#[account(mut)]
new_owner_token: CpiAccount<'info, TokenAccount>,
#[account(signer)]
new_owner: AccountInfo<'info>,
owner: AccountInfo<'info>,
token_program: AccountInfo<'info>,
}
fn check_funds(check: &ContentRecord, new_price: u64) -> Result<()> {
if check.price >= new_price {
return Err(ErrorCode::InsufficientFunds.into());
}
Ok(())
}
#[error]
pub enum ErrorCode {
#[msg("The given nonce does not create a valid program derived address.")]
InvalidNonce,
#[msg("The derived signer does not match that which was given.")]
InvalidSigner,
#[msg("Insufficient funds provided to purchase route.")]
InsufficientFunds,
}
O que está acontecendo no contrato?
- Todas as contas a serem acessadas são anotadas na estrutura para cada chamada com #[derive(Accounts)].
- As funções ajudam a inicializar os dados da conta do proprietário inicial e da Compra. Isso permite que qualquer pessoa compre por mais tokens.
- Os dados temporários são passados para os parâmetros da função. Esses parâmetros estão dentro das funções de inicialização e compra. Isso também inclui o Contexto que mantém as contas necessárias para a transação.
- O estado do contrato está localizado na estrutura ContentRecord. Isso é anotado com #[account] para indicar que representa o layout de dados de uma conta.
O que é NEAR Protocol?
Entrando em vigor no verão de 2018, o protocolo foi projetado para criar o ambiente perfeito para aplicativos descentralizados, fornecendo velocidades mais altas, maior rendimento e melhor compatibilidade com outras blockchains. A NEAR possui uma técnica única de Sharding e apresenta um mecanismo de geração de blocos chamado “Doomslug” proposto em 2019. Doomslug permite finalidade prática ou “Doomslug”, garantindo que os blocos sejam finalizados em segundos.
O protocolo NEAR é desenvolvido pelo NEAR Collective, uma comunidade de desenvolvedores e pesquisadores que colaboram na construção do projeto. Alguns recursos importantes da NEAR são:
- NEAR é um sistema fragmentado que permite escalabilidade infinita.
- Um protocolo fácil de usar, a NEAR permite que os desenvolvedores criem aplicativos com facilidade e rapidez.
- NEAR não é uma rede secundária (side chain), mas um protocolo de camada 1.
- Os dApps criados usando a NEAR são executados no topo da camada NEAR subjacente.
O que é o coletivo NEAR (NEAR Collective)?
O Coletivo NEAR inclui organizações individuais e outros colaboradores que trabalham continuamente para melhorar o Protocolo NEAR. O Coletivo trabalha em projetos como escrever o código inicial e implementação para a Rede NEAR. A NEAR é totalmente descentralizada, operando de forma independente e não pode ser desligada ou manipulada, mesmo por quem a construiu.
É uma organização sem fins lucrativos focada na criação de um ecossistema vibrante em torno da blockchain NEAR. Auxilia na coordenação das atividades de governança e desenvolvimento. O NEAR Collective tem vários projetos, sendo a NEAR blockchain apenas um dos vários projetos sob o teto do Coletivo.
Mecanismo de Consenso NEAR
O mecanismo de consenso implementado no NEAR é chamado de Nightshade. Nightshade modela o sistema como uma única blockchain. A lista de todas as transações em cada bloco é dividida em blocos físicos, um bloco por fragmento. Todos os pedaços (chunks) se acumulam em um bloco. Observe que os chunks só podem ser validados por nós que mantêm o estado desse shard.
Falando em validação, um componente chave de NEAR são os validadores. Esses validadores são responsáveis por manter o consenso dentro do protocolo. Os validadores são nós especializados que precisam manter seus servidores online 100% do tempo, mantendo seus sistemas continuamente atualizados.
Aqui estão alguns pontos que você deve ter em mente sobre os validadores de rede.
- A NEAR determina seus validadores de rede a cada nova época, elegendo-os com base em sua participação.
- Os validadores já eleitos são reinscritos por meio de uma nova aposta automática de seus tokens mais as recompensas acumuladas.
- Os validadores potenciais devem ter sua participação acima de um nível determinado dinamicamente.
- Existem dois métodos que um validador pode usar para fortalecer seu staking – comprar os tokens por conta própria ou pedir emprestado por delegação de participação.
- A recompensa que você recebe é diretamente proporcional à sua aposta – quanto maior a quantidade de tokens em staking, mais recompensas.
O consenso é baseado no consenso da cadeia mais pesada. Ou seja, uma vez que um produtor de bloco publica um bloco, ele coleta as assinaturas dos nós validadores. O peso de um bloco é então a aposta cumulativa de todos os signatários cujas assinaturas estão incluídas no bloco. O peso de uma cadeia é a soma dos pesos dos blocos. Além disso, o consenso utiliza um dispositivo de finalidade que introduz condições de corte adicionais para maior segurança da cadeia.
Doomslug” é um mecanismo de geração de blocos de qual protocolo?
Aurora e NEAR Protocol
A Aurora também foi lançada no NEAR Protocol, fornecendo uma Experiência da camada 2 Ethereum. Algumas das maneiras pelas quais a Aurora melhora a NEAR são:
- Ele ajuda a aumentar a taxa de transferência para milhares de transações por segundo.
- Um tempo de finalização de bloco de 2 segundos.
- Crescimento do ecossistema à prova de futuro
- Baixas taxas de transação, que são 1000 vezes mais baixas que o Ethereum.
- Compatibilidade intransigente com Ethereum.
Exemplo de Contrato
use near_sdk::borsh::{self, BorshDeserialize, BorshSerialize};
use near_sdk::collections::LookupMap;
use near_sdk::{env, near_bindgen, AccountId, Balance, Promise};
#[global_allocator]
static ALLOC: near_sdk::wee_alloc::WeeAlloc = near_sdk::wee_alloc::WeeAlloc::INIT;
#[derive(BorshDeserialize, BorshSerialize)]
pub struct ContentRecord {
pub price: Balance,
pub content: String,
pub owner: AccountId,
}
#[near_bindgen]
#[derive(BorshDeserialize, BorshSerialize)]
pub struct ContentTracker {
values: LookupMap<String, ContentRecord>,
contract_owner: AccountId,
}
impl Default for ContentTracker {
fn default() -> Self {
let contract_owner = env::predecessor_account_id();
Self {
values: LookupMap::new(b"v".to_vec()),
contract_owner,
}
}
}
#[near_bindgen]
impl ContentTracker {
/// Gets content at a given route.
pub fn get_route(&self, route: String) -> Option<String> {
self.values.get(&route).map(|v| v.content)
}
/// Purchases a route based on funds sent to the contract.
#[payable]
pub fn purchase(&mut self, route: String, content: String) {
let deposit = env::attached_deposit();
assert!(deposit > 0);
if let Some(entry) = self.values.get(&route) {
assert!(
deposit > entry.price,
"Not enough deposit to purchase route, price: {} deposit: {}",
entry.price,
deposit
);
// Refund purchase to existing owner
Promise::new(entry.owner).transfer(entry.price);
}
// Update record for the contract state.
self.values.insert(
&route,
&ContentRecord {
price: deposit,
content,
owner: env::predecessor_account_id(),
},
);
}
/// Allows owner of the contract withdraw funds.
pub fn withdraw(&mut self) {
assert_eq!(env::predecessor_account_id(), self.contract_owner);
// Send the contract funds to the contract owner
Promise::new(self.contract_owner.clone()).transfer(env::account_balance());
}
}
O que está acontecendo no contrato?
Então, o que está acontecendo aqui no contrato? Vamos olhar mais de perto.
- O contrato é definido por #[near_bindgen] no ContentTracker, é semelhante a um construtor no Solidity e é chamado quando o contrato é implantado.
- A função de compra é anotada com #[payable].
- O contrato inclui chamadas assíncronas na forma de Promise::new(…).transfer(…); lines.
- A estrutura de dados LookupMap<String, ContentRecord> lida com a pesquisa de valor-chave, que acessa o armazenamento. Isso é igual ao “mapping” do Solidity.
Conclusão
Tanto Solana quanto NEAR Protocol são contratos inteligente brilhantes, plataformas que construíram comunidades altamente ativas. Ambos trazem recursos especiais que ajudam a combater o maior problema que assola o mundo descentralizado – a velocidade. Ambas as plataformas ainda estão crescendo e são muito promissoras.
Updated: Abril 13, 2023

