Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...
Loading...

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
import { HashiProver } from "./HashiProver.sol";
contract MockERC20Prover {
event TransferEventVerified(uint256 indexed chainID, bytes rlpEncodedEvent);
HashiProver public hashiProver;
address public erc20Contract;
uint256 public chainID;
constructor(address shoyuBashi_, address erc20Contract_, uint256 chainID_) {
hashiProver = HashiProver(shoyuBashi_);
erc20Contract = erc20Contract_;
chainID = chainID_;
}
function verifyTransferEvent(HashiProver.ReceiptProof calldata proof, bytes memory expectedRlpEncodedEvent) external {
require(proof.chainId == chainID, "Invalid chain id");
bytes memory rlpEncodedEvent = hashiProver.verifyForeignEvent(proof);
require(keccak256(rlpEncodedEvent) == keccak256(expectedRlpEncodedEvent), "invalid event");
emit TransferEventVerified(proof.chainId , rlpEncodedEvent);
// TODO: Define custom logic here
}
}// Example of submitting the proof in Solidity (or via web3 call)
HashiProver.ReceiptProof memory proof = { /* fetched proof from curl command */ };
MockERC20Prover.verifyTransferEvent(proof, expectedRlpEncodedEvent);Transfer event.
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
import { HashiProver } from "https://github.com/gnosis/hashi/blob/feat/hashi-prover/packages/evm/contracts/prover/HashiProver.sol";
contract UsdcTotalSupplyReader is HashiProver {
event UsdcTotalSupply(uint256 totalSupply);
constructor(address shoyuBashi) HashiProver(shoyuBashi) {}
function readTotalSupply(HashiProver.AccountAndStorageProof calldata proof) external {
require(proof.chainId == 10, "Invalid chain id"); // Optimism
require(proof.account == 0x0b2C639c533813f4Aa9D7837CAf62653d097Ff85, "Invalid account");
require(proof.storageKeys.length == 1 && proof.storageKeys[0] == bytes32(uint256(0xb)), "Invalid storage key");
// Verify the proof against the latest block header stored in Hashi
uint256 totalSupply = uint256(bytes32(verifyForeignStorage(proof)[0]));
emit UsdcTotalSupply(totalSupply);
}
}
import axios from "axios";
const main = async () => {
// fetch event proof from Hashi Prover
console.log("Fetching event proof from Hashi prover...");
const result = await axios.post(
`http://jsonrpc.hashi-explorer.xyz:3000/v1`,
{
jsonrpc: "2.0",
method: "hashi_getReceiptProof",
params: {
logIndex: 397,
blockNumber: 7016999,
chainId: 11155111,
transactionHash: "0x25a6a5c138f3b5a434a3a2b5d6bf7bdf97cb700bd7515f801ecfb71f1d965e7b",
},
id: 1,
},
{
headers: {
"Content-Type": "application/json",
},
}
);
console.log("Event proof result", result.data.result.proof);
};
main();curl --location --request POST 'https://jsonrpc.hashi-explorer.xyz/v1' \
--header 'Content-Type: application/json' \
--data-raw '{
"id": 1,
"jsonrpc": "2.0",
"method": "hashi_getAccountAndStorageProof",
"params": {
"chainId": 10,
"address": "0x0b2c639c533813f4aa9d7837caf62653d097ff85",
"storageKeys": ["0x00000000000000000000000000000000000000000000000000000000000000b"],
"blockNumber": 126086800
}
}'import axios from "axios";
const main = async () => {
// fetch storage proof from Hashi Prover
console.log("Fetching storage proof from Hashi prover...");
const result = await axios.post(
"http://jsonrpc.hashi-explorer.xyz:3000/v1",
{
jsonrpc: "2.0",
method: "hashi_getAccountAndStorageProof",
params: {
chainId: 10,
address: "0x0b2c639c533813f4aa9d7837caf62653d097ff85",
storageKeys: ["0x00000000000000000000000000000000000000000000000000000000000000b"],
blockNumber: 126086800
},
id: 1,
},
{
headers: {
"Content-Type": "application/json",
},
}
);
console.log("Storage proof result", result.data.result.proof);
};
main();// Example of submitting the proof in Solidity (or via web3 call)
HashiProver.AccountAndStorageProof memory proof = { /* fetched proof from curl command */ };
usdcTotalSupplyReader.readTotalSupply(proof);RUST_LOG=info cargo run --release -- --execute \
--rpc-url https://mainnet.infura.io/v3/YOUR-PROJECT-ID \
--reference-block-number 0x7B60EA3 \
--proof-block-number 0x783EE90 \
--account 0x0b2c639c533813f4aa9d7837caf62653d097ff85 \
--storage-key 0x000000000000000000000000000000000000000000000000000000000000000b// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
interface IYaho {
function dispatchMessageToAdapters(
uint256 targetChainId,
uint256 threshold,
address targetAddress,
bytes memory data,
address[] memory reporters,
address[] memory adapters
) external;
}
contract SepoliaSender {
IYaho public yaho = IYaho(0x21eAB033C7D2DF6A67AeF6C5Bda9A7F151eB9f52); // Yaho address on Sepolia
uint256 public threshold;
address[] public reporters;
address[] public adapters;
constructor(address _yaho, uint256 _threshold, address[] memory _reporters, address[] memory _adapters) {
threshold = _threshold;
reporters = _reporters;
adapters = _adapters;
}
// Function to send a cross-chain message to Chiado
function sendMessageToChiado(
uint256 targetChainId,
address targetAddress,
string memory _message
) public {
bytes memory data = abi.encode(_message);
yaho.dispatchMessageToAdapters(targetChainId, threshold, targetAddress, data, reporters, adapters);
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
contract ChiadoReceiver {
/// @dev Yaru contract on the Chiado w.r.t the Sepolia
address public YARU = 0xBA9165973963a6E5608f03b9648c34A737E48f68;
/// @dev Source chain ID of Sepolia
uint256 public SOURCE_CHAIN_ID = 11155111;
/// @dev Expected threshold to be met by the adapters
uint256 public EXPECTED_THRESHOLD;
/// @dev Sender SepoliaSender contract address
address public SOURCE_SENDER_ADDRESS;
/// @dev hash of adapters address
bytes32 public ADAPTERS_HASH;
/// @dev message that is last received from sender contract's sendMessageToTarget function
string public lastReceivedMessage;
constructor(uint256 expectedThreshold, address sourceSender, address[] memory adapters){
EXPECTED_THRESHOLD = expectedThreshold;
SOURCE_SENDER_ADDRESS = sourceSender;
ADAPTERS_HASH = keccak256(abi.encodePacked(adapters));
}
/// @dev Function that gets triggered when the message is relayed, called by Yaru contract
/// @param chainId chainId of the chain where message is sending from
/// @param sender sender contract
/// @param threshold threshold of the message that should be met by adapters
/// @param adapters an array of adapters to check the threshold with
/// @param data abi-encoded message
/// @return
function onMessage(
uint256, /*messageId*/
uint256 chainId,
address sender,
uint256 threshold,
address[] memory adapters,
bytes memory data
) external returns (bytes memory) {
require(msg.sender == YARU, "only called by Yaru");
require(chainId == SOURCE_CHAIN_ID, "invalid source chain ID");
require(threshold == EXPECTED_THRESHOLD, "invalid number of threshold");
require(sender == SOURCE_SENDER_ADDRESS, "invalid sender address from source chain");
require( keccak256(abi.encodePacked(adapters)) == ADAPTERS_HASH, "invalid adapters hash");
// Decode the message and store it
(string memory message) = abi.decode(data, (string));
lastReceivedMessage = message;
return "";
}
}RUST_LOG=info cargo run --release -- --execute \
--rpc-url <rpc_url> \
--block-number <block_number_hex_encoded> \
--proof-block-number <ancestral_block_number_hex_encoded> \
--account <account> \
--storage-key <storage_key>const [configKey] = PublicKey.findProgramAddressSync([Buffer.from("config", "utf-8")], snapshotter.programId)
const systemProgram = new PublicKey("11111111111111111111111111111111")
await snapshotter.methods
.subscribe(systemProgram)
.accounts({
config: configKey,
} as any)
.rpc()const [configKey] = PublicKey.findProgramAddressSync([Buffer.from("config", "utf-8")], snapshotter.programId)
const batch = new anchor.BN(0) // must be equal to the current batch
await snapshotter.methods
.calculateRoot(batch)
.accounts({
config: configKey,
} as any)
.remainingAccounts(batchAccounts)
.rpc()const tracker = await getProgramSequenceTracker(provider.connection, reporter.programId, CORE_BRIDGE_PID)
const message = deriveWormholeMessageKey(reporter.programId, tracker.sequence + 1n)
const wormholeAccounts = getPostMessageCpiAccounts(
reporter.programId,
CORE_BRIDGE_PID,
provider.publicKey,
message,
)
const [configKey] = PublicKey.findProgramAddressSync([Buffer.from("config", "utf-8")], reporter.programId)
const [snapshotterConfigkey] = PublicKey.findProgramAddressSync(
[Buffer.from("config", "utf-8")],
snapshotter.programId,
)
await reporter.methods
.dispatchRoot()
.accounts({
config: configKey,
wormholeProgram: new PublicKey(CORE_BRIDGE_PID),
snapshotterConfig: snapshotterConfigkey,
...wormholeAccounts,
} as any)
.rpc()pragma solidity ^0.8.20;
import { HashiProver } from "../prover/HashiProver.sol";
import "../prover/HashiProverStructs.sol";
contract SolanaAccountReader is HashiProver {
constructor(address shoyuBashi) HashiProver(shoyuBashi) {}
function getSolanaAccount(SolanaAccountProof calldata proof) external view returns (bytes memory) {
return verifyForeignSolanaAccount(proof);
}
}