Acessando feeds de preço com Acurast¶
Introdução¶
Acurast oferece computação permissionless, confiável e acessível para implantar aplicações. Um dos usos é permitir que desenvolvedores criem oráculos push/pull, consultando APIs off-chain para trazer preços on-chain. Os dados são processados de forma confidencial pelos Processors e enviados a contratos de redes EVM compatíveis com Tanssi via a interface padrão Chainlink Aggregator.
Este tutorial mostra um demo de como interagir com feeds de preço fornecidos pela Acurast na rede EVM de demonstração do Tanssi. Você também pode implantar seus próprios feeds na sua rede EVM com tecnologia Tanssi. Para produção, é altamente recomendável contatar a equipe Acurast para auxiliar no lançamento e garantir a integridade do processo.
O que é Acurast?¶
Acurast é uma nuvem descentralizada e sem servidor em que qualquer pessoa pode contribuir poder de computação (inclusive com celulares) e receber recompensas. Esses Processors formam uma rede distribuída mundialmente. Processors e desenvolvedores interagem pelo Acurast Console.
Obter dados de preço¶
Você pode desenhar o feed de preço Acurast como quiser. Os dados ficam em uma série de contratos (um por feed) e podem ser consultados via a interface do agregador. O feed demo usa a mesma interface de preço da Chainlink:
AggregatorV3Interface.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface AggregatorV3Interface {
/**
* Returns the decimals to offset on the getLatestPrice call
*/
function decimals() external view returns (uint8);
/**
* Returns the description of the underlying price feed aggregator
*/
function description() external view returns (string memory);
/**
* Returns the version number representing the type of aggregator the proxy points to
*/
function version() external view returns (uint256);
/**
* Returns price data about a specific round
*/
function getRoundData(uint80 _roundId) external view returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);
/**
* Returns price data from the latest round
*/
function latestRoundData() external view returns (uint80 roundId, int256 answer, uint256 startedAt, uint256 updatedAt, uint80 answeredInRound);
}
Na interface, cinco funções retornam dados: decimals, description, version, getRoundData e latestRoundData. Consulte a referência da Chainlink para detalhes.
Interagir com feeds na rede EVM demo do Tanssi¶
Vamos usar o feed BTC/USDT já implantado (veja Ativos suportados). O contrato do agregador no Blockscout:
0x02093b190D9462d964C11587f7DedD92718D7B56
Como interagir pelo Remix:
- Conecte a MetaMask à rede EVM demo (guia Remix).
- Cole o contrato Aggregator em um novo arquivo e compile.
- Em Deploy and Run, defina ENVIRONMENT para Injected Provider -- MetaMask.
- Selecione AggregatorV3Interface em CONTRACT.
- No campo At Address, informe
0x02093b190D9462d964C11587f7DedD92718D7B56e clique At Address.
Para consultar:
- Expanda AggregatorV3Interface.
- Clique em decimals para ver quantas casas decimais o preço usa.
- Clique em description para verificar o par.
- Clique em latestRoundData para ver o preço mais recente (retornado em int256 answer).
Lembre-se de ajustar pelo número de decimais informado por decimals(). Ex.: se o feed retorna 51933620000 e decimals = 6, o preço é 51,933.62.
Ativos suportados¶
Exemplo de chamada de API usada no demo:
curl "https://api.binance.com/api/v3/ticker/price?symbol=BTCUSDT"
Saída de exemplo:
Nota
Este exemplo usa apenas uma fonte (uma exchange). É possível construir scripts que agreguem múltiplas fontes.
Por design, a Acurast pode suportar o feed de qualquer ativo acessível por API.
Feeds implantados na rede EVM demo:
| Ativo/Par | Contrato agregador |
|---|---|
| AAVE/USDT | 0x6239Ff749De3a21DC219bcFeF9d27B0dfE171F42 |
| BTC/USDT | 0x02093b190D9462d964C11587f7DedD92718D7B56 |
| CRV/USDT | 0x01F143dfd745861902dA396ad7dfca962e5C83cA |
| DAI/USDT | 0x73aF6b14b73059686a9B93Cd28b2dEABF76AeC92 |
| ETH/USDT | 0x007c3F3cc99302c19792F73b7434E3eCbbC3db25 |
| USDC/USDT | 0xe4a46ef4cFbf87D026C3eB293b7672998d932F62 |
| USDT/USD | 0xf9c885E3A5846CEA887a0D69655BC08e52afe569 |
Esses endereços estão disponíveis para testes, mas você pode implantar feeds adicionais para outros pares conforme necessário.
Criar e lançar seu próprio feed de preço¶
Você pode criar seu próprio feed Acurast na rede EVM do Tanssi. Este tutorial é apenas demonstrativo; para produção, contate a equipe Acurast.
São necessários dois componentes: contrato e script. No exemplo anterior de interação com BTC/USD usamos a interface Chainlink porque é simples de demonstrar. O contrato subjacente segue a interface Chainlink Aggregator, mas o demo adiciona eventos e lógica exemplo. Código de contrato e script estão no repositório da Acurast.
O contrato de demo InsecureDummyPriceFeed.sol emite eventos quando o preço é atualizado e quando um novo round inicia. O método setPrice é inseguro e serve apenas para mostrar onde adicionar consenso, controle de acesso etc.
InsecureDummyPriceFeed.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import "./interfaces/chainlink/AggregatorV2V3Interface.sol";
/**
This Dummy Oracle is compatible with Chainlink's AggregatorV2V3Interface, meaning projects currently using
Chainlink can seamlessly migrate. The updating of the price feed happens in the interval you specified on
the Acurast script.
At the moment no check on the signer/source is being performed, making this implementation INSECURE. However
with a minimal effort you can extend the "setPrice" entrypoint to reflext the kind of logic you are looking for
(i.e. Aggregation Consensus, Check sources, thresholds, etc).
**/
contract DummyChainlinkCompatibleOracle is AggregatorV2V3Interface {
int256 private latestPrice;
uint256 private latestPriceTimestamp;
uint256 private latestRoundId;
// Assuming price can be set without restriction for simplicity
// In a real-world scenario, there should be access control mechanisms
function setPrice(int256 _price) external {
latestPrice = _price;
latestPriceTimestamp = block.timestamp;
latestRoundId++;
emit AnswerUpdated(latestPrice, latestRoundId, latestPriceTimestamp);
emit NewRound(latestRoundId, msg.sender, latestPriceTimestamp);
}
// AggregatorInterface functions
function latestAnswer() external view override returns (int256) {
return latestPrice;
}
function latestTimestamp() external view override returns (uint256) {
return latestPriceTimestamp;
}
function latestRound() external view override returns (uint256) {
return latestRoundId;
}
function getAnswer(uint256 _roundId) external view override returns (int256) {
if(_roundId == latestRoundId) {
return latestPrice;
}
return 0; // Simplification, should handle historical data
}
function getTimestamp(uint256 _roundId) external view override returns (uint256) {
if(_roundId == latestRoundId) {
return latestPriceTimestamp;
}
return 0; // Simplification, should handle historical data
}
// AggregatorV3Interface functions
function decimals() external pure override returns (uint8) {
return 6; // Assume a common decimal value for simplicity
}
function description() external pure override returns (string memory) {
return "Sample Price Feed";
}
function version() external pure override returns (uint256) {
return 1;
}
function getRoundData(uint80 _roundId)
external
view
override
returns (
uint80 roundId,
int256 answer,
uint256 startedAt,
uint256 updatedAt,
uint80 answeredInRound
)
{
require(_roundId == latestRoundId, "Only latest round data available");
return (uint80(latestRoundId), latestPrice, latestPriceTimestamp, latestPriceTimestamp, uint80(latestRoundId));
}
function latestRoundData()
external
view
override
returns (
uint80 roundId,
int256 answer,
uint256 startedAt,
uint256 updatedAt,
uint80 answeredInRound
)
{
return (uint80(latestRoundId), latestPrice, latestPriceTimestamp, latestPriceTimestamp, uint80(latestRoundId));
}
}
Atenção
O contrato de demonstração tem vulnerabilidades e não possui controles de acesso; não use em produção.
Antes de prosseguir, implante o contrato do seu feed na rede EVM do Tanssi (ou na rede demo). Guarde o endereço, pois será usado no script Acurast.
Construindo o script Acurast¶
O script Acurast atualiza o oracle on-chain com os preços, fazendo a ponte entre o feed de preço da rede Tanssi e a rede Acurast. No console você define parâmetros como frequência, agenda e recompensa dos Processors. Para publicar jobs você precisará de tokens cACU (pegue no faucet) — eles são a moeda nativa da rede Canary da Acurast.
O script atualiza o oracle on-chain com preços. Exemplo de script:
AcurastScript.js
/**
* This Oracle Script observes the BTC USDT Pair and posts the price on-chain.
* Deploying the script is easy using console.acurast.com and simply copy/pasting
* this script. Make sure to update `DESTINATION_CONTRACT` and `EVM_RPC_NODE` to
* reflect your deployment. For RPC's with API keys like i.e. infura make sure
* to work with the Acurast confidential environment variables. After having set
* them for your job, you can access them easily with a `_STD_.env["MY_KEY"]`. They
* also come in handy for paid API KEYs, that you don't want to share publicly.
*/
const DESTINATION_CONTRACT = 'INSERT_CONTRACT_ADDRESS';
const EVM_RPC_NODE = 'INSERT_NETWORK_RPC_URL';
httpGET(
'https://api.binance.com/api/v3/ticker/price?symbol=BTCUSDT',
{},
(response, certificate) => {
if (
certificate ===
'4795062d13e1ed971c6b6e5699764681e4d090bad39a7ef367cc9cb705652384'
) {
//const price = BigInt(JSON.parse(response)["price"] * 10 ** 18); // if you need more precision, just keep in mind that JS stored bigger numbers in float format, rounding up/down your stuff.
const price = BigInt(JSON.parse(response)['price'] * 10 ** 6);
const int256AsBytes = '0x' + price.toString(16).padStart(64, '0');
const payload = '0x' + _STD_.chains.ethereum.abi.encode(int256AsBytes);
_STD_.chains.ethereum.fulfill(
EVM_RPC_NODE,
DESTINATION_CONTRACT,
payload,
{
methodSignature: 'setPrice(int256)',
gasLimit: '9000000',
maxFeePerGas: '2550000000',
maxPriorityFeePerGas: '2550000000',
},
(opHash) => {
console.log('Succeeded: ' + opHash);
},
(err) => {
console.log('Failed: ' + err);
}
);
}
},
(err) => {
console.log('Failed: ' + err);
}
);
Se você reutilizar o script de exemplo da Acurast, lembre-se de atualizar o endereço do contrato e o RPC da sua rede.
No console Acurast, configure o job:
- Create Jobs → cadeia Moonbeam, ambiente Moonbase (Tanssi herda a compatibilidade EVM do Moonbeam).
- Selecione Price Feeds.
- Cole o script (altere o endereço do contrato implantado e o RPC da sua rede — disponível no Tanssi dApp).
- Opcional: teste o código; erros aparecem no console do navegador.
- Em seguida, defina Use Public Processors, Interval, horário de início/fim, intervalo em minutos, duração e max start delay.
- Defina o Number of processors (mais processadores exigem mais cACU; obtenha no faucet).
- Defina o Max Reward por execução (exemplo:
0.01cACU). - Revise e clique Publish Job. Depois acompanhe o status na mesma página.
Na tela seguinte você pode monitorar o status do job publicado.
Para mais detalhes sobre como construir e acessar feeds de preço na sua rede EVM Tanssi, consulte a documentação da Acurast.
Com isso você tem um fluxo completo: contrato on-chain, script de atualização e job publicado na Acurast para manter o feed de preços ativo.
| Criada: 9 de dezembro de 2025




