The XCC oracle
StNearRateOracle reads stNEAR's NEAR value from Meta Pool on NEAR, from Solidity.
Aurora contracts can schedule calls to NEAR contracts through the cross-contract-call (XCC) precompile at 0x516Cded1D16af10CAd47D6D49128E2eB7d27b372. StNearRateOracle uses it for a view call:
function sync() external {
PromiseCreateArgs memory query = near.call(metaPool, "get_st_near_price", "{}", 0, VIEW_GAS);
PromiseCreateArgs memory callback =
near.auroraCall(address(this), abi.encodeCall(this.onRate, ()), 0, CALLBACK_GAS);
query.then(callback).transact();
}A few NEAR blocks later the engine calls onRate() back. It:
- Accepts only the contract's own XCC account as the caller (its implicit Aurora address).
- Reads the promise result. A failed view emits
SyncFailed. - Parses the quoted u128 strictly (
NearJson.parseU128). - Ignores a lower reading (
RateRejected). Otherwise it storesrateandupdatedAt.
Check it on testnet:
cast call 0xA8adEFE2C8f0F71a585a73c1259997f593F9e463 "rate()(uint256)" -r https://testnet.aurora.devThe answer equals get_st_near_price on meta-v2.pool.testnet.
First sync costs 2 NEAR
The first XCC call creates the contract's account on NEAR, which needs 2 NEAR of storage. The precompile pulls it as wNEAR from the caller, so approve 2 wNEAR to the oracle first. Later syncs are free view calls.
Why stNEAR and not native staking
Staking NEAR directly through XCC turns out to be one way. The precompile charges the caller wNEAR for every NEAR a promise attaches, so NEAR withdrawn to the contract's NEAR account could never come back to Aurora. stNEAR keeps the staking yield, is already an ERC-20 on Aurora, and needs XCC only for a free view.