Skip to main content

Ethereum Virtual Machine (EVM)

Acurast can be used to get access to computational resources for various use cases and bring them to EVM chains. For that, the Consumer creates a Job that performs a given task on the Acurast Console.

Integration Example

The following example shows a possible integration approach for an EVM chain.

EVM smart contract implementation

The first step is the implementation and deployment of the EVM contract.

The example used is a simple entropy provider, which receives entropy from an Acurast Processor and exposes it to other contracts in the EVM environment.

In this example, the contract expects the Acurast Processor to be known in advance, this can also be adapted at a later stage, depending on how you want to assign your Job to one or more Processors.

For simplicity purposes, this example uses the address 0x176583fbcd4e378c138dea7a4630e7b2b759af96 as a Processor.

Deploy with Remix

EntropyProvider.sol
// SPDX-License-Identifier: None
pragma solidity ^0.8.0;

contract EntropyProvider {
bytes entropy;
uint last_update;
address processor;

constructor(address _processor) {
processor = _processor;
}

/**
* Receive entropy (random bytes) from an Acurast job.
*/
function receive_entropy(bytes memory _entropy) public {
// Ensures that only the processor can call this function
require(msg.sender == processor, "NOT_ALLOWED");
// Update entropy
entropy = _entropy;
last_update = block.timestamp;
}

/**
* A view that exposes the entropy to other contracts.
*/
function consume_entropy(uint maxAge) public view returns (bytes memory) {
// Consumers can specify the maximum entropy age they are willing to accept
require(block.timestamp - last_update <= maxAge, "ENTROPY_TOO_OLD");

return entropy;
}
}

Deployed contract example on Goerli chain: 0x2c503cfba7178eb0ac2dc5df45279527d437657a

Job specification

Now that the contract has been deployed, we can prepare the script that will get executed by the Processor to provision the entropy.

The script below computes some random bytes securely and calls the function receive_entropy of the contract deployed above. The Consumer can also specify the gas limit and maximum costs per gas unit.

JobLogic.js
// Destination contract address
const destination = "<0x evm_contract_address>";
// Generate entropy
const entropy = _STD_.random.generateSecureRandomHex();
// Fulfill entropy
_STD_.chains.ethereum.fulfill(
"https://rpc.ankr.com/eth_goerli", // RPC
destination, // Destination contract address
entropy, // Payload
// Transaction parameters
{
methodSignature: "receive_entropy(bytes)",
gasLimit: "9000000",
maxFeePerGas: "255000000000",
maxPriorityFeePerGas: "2550000000",
},
// Success callback
(opHash) => {
print("Succeeded: " + opHash);
},
// Error callback
(err) => {
print("Failed: " + err);
}
);
https://example.com

Job Registration

Check out How to get started with the Acurast Console to register your Job.

Price feeds with Chainlink-compatible contracts have been deployed to multiple protocols. These can be called by other smart contracts to fetch asset pricing data like the BTC / USD feed.

These feeds use data fetched by Acurast Processors and pushed directly to the contract. Each price feed has an on-chain address and functions that enable contracts to read pricing data from that address.

This guide shows you how to read Price Feeds and store the value on-chain using Solidity.

Consuming Price Feeds

This example contract obtains the latest price answer from the BTC / USD feed, but you can modify it to read any of the different types of data, depending on your script.

// SPDX-License-Identifier: MIT
pragma solidity ^0.6.0;

import "@chainlink/contracts/src/v0.6/interfaces/AggregatorInterface.sol";

contract DataConsumer {
AggregatorInterface internal dataFeed;

/**
* Network: Astar zKatana
* Aggregator: BTC/USD
*/
constructor() {
dataFeed = AggregatorInterface(
0xDBb23274EE9354367155C290c673733374d57967
);
}

/**
* Returns the latest answer.
*/
function getLatestAnswer() public view returns (int256) {
int256 answer = dataFeed.latestAnswer();
return answer;
}
}

The contract has the following components:

  • The import line imports an interface named AggregatorInterface. Interfaces define functions without their implementation, which leaves inheriting contracts to define the actual implementation themselves.

  • The constructor() {} initializes an interface object named dataFeed that uses AggregatorInterface and connects specifically to a proxy aggregator contract that is already deployed at 0xDBb23274EE9354367155C290c673733374d57967. The interface allows your contract to run functions on that deployed aggregator contract.

  • The getLatestAnswer() function calls your dataFeed object and runs the latestAnswer() function. When you deploy the contract, it initializes the dataFeed object to point to the aggregator at 0xDBb23274EE9354367155C290c673733374d57967, which is the proxy address for the Astar zKatana BTC / USD data feed. Your contract connects to that address and executes the function. The aggregator connects with one or several Acurast Processors and aggregates the pricing data from those nodes. The response from the aggregator includes several variables, but getlatestAnswer() returns only the answer variable.

Deployed Contracts

A list of deployed contracts updated regularly by Acurast Processors.

BoB (Build on Bitcoin)

SymbolAddress
ASTR/BTC0x418dc698f0a1d949cf72096619d1d08f90da59ba
BNB/BTC0xc3e5d03d5969776a589cb09238ad9a3c235075c5
BTC/USD0x77b5887f0f545cdfaf62e168c10a8ef1c4934c2c
DAI/BTC0xe5d7497e04559680a99c8be8cc3a0fecc9a52ba1
DOT/BTC0x3d280dfe494502dbe0b0159aff72146517f0da19
ETH/BTC0x4270d588bc5d681f42aba6bd681c09dad171abe7
MATIC/BTC0x27cadc58771ed8cc24b9303cd8458f24fad2f832
USDC/BTC0x025cb9a8a0fcc586fa5e1c79dbcd56cd45656c86
USDT/BTC0x9ae4afd93dec973778740808202d559f132fad04
stETH/BTC0x32e1e8bb5667a07ee4da9c4ba0673b4155883c2d
BTC Fee Estimation0x452a09e72444cf6a526b02c1a27d250305d450b5

zKatana (Astar zkEVM)

SymbolAddress
ASTR/USD0xde4F97786EAB4e47b96A0A65EdD7755895077073
BTC/USD0xDBb23274EE9354367155C290c673733374d57967
ETH/USD0x448786CD6E53E706AEdd984C620D63d48B720e6A
BNB/USD0xb6B94e18957376ac6d22bAF31C7BF1661B238F4A
USDT/USD0xD12ad062A6bFBB27024a7B76E4EF7FDC5bf49Aeb
USDC/USD0x2E23a70dfe6059f9F2DC35C1e940e3B3288BDE04
DAI/USD0xEC6985D9eA362fb85fEa72263169C375F8f065E7
stETH/USD0xA2FB708105a412710Df254D7406A27764408A657
DOT/USD0x208f799E0EE205bc6607Fae430485c66F9fe6012
MATIC/USD0x77Ed3BAc1B3Dd4DBB8D2636b6f3adFd4f21d15B3