@unruggable/gateways
Version:
Trustless Ethereum Multichain CCIP-Read Gateway
105 lines (104 loc) • 4.47 kB
JavaScript
;
Object.defineProperty(exports, "__esModule", { value: true });
exports.StarknetRollup = void 0;
const abi_1 = require("ethers/abi");
const chains_js_1 = require("../chains.cjs");
const rollup_js_1 = require("../rollup.cjs");
const StarknetProver_js_1 = require("./StarknetProver.cjs");
const contract_1 = require("ethers/contract");
const utils_js_1 = require("../utils.cjs");
const EthProver_js_1 = require("../eth/EthProver.cjs");
const rlp_js_1 = require("../rlp.cjs");
const utils_1 = require("ethers/utils");
const hash_1 = require("ethers/hash");
const CORE_ABI = new abi_1.Interface([
`function stateRoot() view returns (bytes32)`,
`function stateBlockNumber() view returns (uint256)`,
`function updateStateKzgDA(uint256[] programOutput, bytes[] kzgProofs)`,
`event LogStateUpdate(uint256 globalRoot, int256 blockNumber, uint256 blockHash)`,
]);
const SLOT_STATE_ROOT = BigInt((0, hash_1.id)('STARKNET_1.0_INIT_STARKNET_STATE_STRUCT'));
class StarknetRollup extends rollup_js_1.AbstractRollup {
// https://docs.starknet.io/tools/important-addresses/
static mainnetConfig = {
chain1: chains_js_1.CHAINS.MAINNET,
chain2: chains_js_1.CHAINS.STARKNET,
Rollup: '0xc662c410C0ECf747543f5bA90660f6ABeBD9C8c4',
};
static sepoliaConfig = {
chain1: chains_js_1.CHAINS.SEPOLIA,
chain2: chains_js_1.CHAINS.SCROLL_SEPOLIA,
Rollup: '0xE2Bb56ee936fd6433DC0F6e7e3b8365C906AA057',
};
Rollup;
constructor(providers, config) {
super(providers);
this.Rollup = new contract_1.Contract(config.Rollup, CORE_ABI, this.provider1);
}
async findStateUpdate(l2BlockNumber) {
loop: for (let block = await this.provider1.getBlockNumber(); block >= 0; block -= this.getLogsStepSize) {
const events = await this.Rollup.queryFilter(this.Rollup.filters.LogStateUpdate(), Math.max(0, block - this.getLogsStepSize), block);
for (let i = events.length - 1; i >= 0; i--) {
const event = events[i];
const bn = BigInt((0, utils_1.dataSlice)(event.data, 32, 64));
if (bn === l2BlockNumber)
return event;
if (bn < l2BlockNumber)
break loop;
}
}
throw new Error(`not finalized: ${l2BlockNumber}`);
}
fetchLatestCommitIndex() {
return this.Rollup.stateBlockNumber({
blockTag: this.latestBlockTag,
});
}
async _fetchParentCommitIndex(commit) {
const tx = await this.provider1.getTransaction(commit.commitTx);
if (!tx)
throw new Error(`no commit: ${commit.commitTx}`);
const desc = this.Rollup.interface.parseTransaction(tx);
if (!desc || desc.name !== 'updateStateKzgDA') {
throw new Error(`expected updateStateKzgDA: ${tx}`);
}
return desc.args.programOutput[2]; // prev blockNumber
}
async _fetchCommit(index) {
const event = await this.findStateUpdate(index);
// const [event] = await this.Rollup.queryFilter(
// this.Rollup.filters.LogStateUpdate(null, index, null)
// );
// if (!event) throw new Error(`not finalized`);
const prover1 = new EthProver_js_1.EthProver(this.provider1, event.blockNumber);
const [block, proof] = await Promise.all([
prover1.fetchBlock(),
prover1.fetchProofs(await this.Rollup.getAddress(), [SLOT_STATE_ROOT]),
]);
const prover = new StarknetProver_js_1.StarknetProver(this.provider2, Number(index));
return {
index,
prover,
commitTx: event.transactionHash,
rlpEncodedL1Block: (0, rlp_js_1.encodeRlpBlock)(block),
accountProof: EthProver_js_1.EthProver.encodeProof(proof.accountProof),
storageProof: EthProver_js_1.EthProver.encodeProof(proof.storageProof[0].proof),
};
}
encodeWitness(commit, proofSeq) {
return utils_js_1.ABI_CODER.encode(['(uint256, bytes, bytes, bytes, bytes[], bytes)'], [
commit.index,
commit.rlpEncodedL1Block,
commit.accountProof,
commit.storageProof,
proofSeq.proofs,
proofSeq.order,
]);
}
windowFromSec(_sec) {
// finalization is not onchain
// TODO: fix me
return 69420;
}
}
exports.StarknetRollup = StarknetRollup;