Using the fingerprint()
method in this contract:
// SPDX-License-Identifier: MIT
pragma solidity >=0.8.0;
contract Fingerprint {
function fingerprint() public view returns (address,address,uint,uint,uint,bytes32,uint) {
return (
msg.sender,
tx.origin,
tx.gasprice,
gasleft(),
block.number,
blockhash(block.number - 1),
block.timestamp);
}
}
Evaluated in different contexts:
Remix (JS VM) | Remix (testnet) | Etherscan | ethers + infura | ethers + alchemy | |
---|---|---|---|---|---|
msg.sender | builtin addr | connected addr | 0x0 | 0x0 | 0x0 |
tx.origin | builtin addr | connected addr | 0x0 | 0x0 | 0x0 |
tx.gasprice | 1 | 0 | 0 | 0 | 0 |
gasleft() | 2978728 | 2978794 | 99978666 | 499978794 | 549978794 |
block.number | 1 | real (6380005) | real | real | real |
blockhash | H1 |
real | real | real | real |
block.ts | 1644870999 | 1644877262 | real | real | real |
Based on this table, we could use this crude off-chain evaluation mechanism:
function isEvaluatedOffchain() public view returns (bool) {
return tx.origin == address(0)
|| tx.gasprice <= 1
|| gasleft() > 30_000_000;
}
Testing it:
/// fingerprint.mjs
import {ethers} from "ethers";
const provider = new ethers.providers.JsonRpcProvider('<https://eth-goerli.alchemyapi.io/v2/-dTf2BzzoSXZ0k_DAjwcNSXcOFpidhxA>');
const humanReadableAbi = [
"function fingerprint() public view returns (address,address,uint,uint,uint,bytes32,uint)",
"function isEvaluatedOffchain() public view returns (bool)",
];
const Fingerprint = new ethers.Contract("0xDC4DcA57c94Fc4aB8483f708B24e2D36E5dB36bf", humanReadableAbi, provider);
Fingerprint.fingerprint({
gasLimit:500000,
maxFeePerGas: 59000000000,
from: "0x8830c393b2ed864Bb3c1A2FB9Fce8dA83f6db66c"
}).then(console.log);
const naiveEval = await Fingerprint.isEvaluatedOffchain();
// => true
const fancyEval = await Fingerprint.isEvaluatedOffchain({
gasLimit:500000,
maxFeePerGas: 59000000000,
from: "0x8830c393b2ed864Bb3c1A2FB9Fce8dA83f6db66c"
});
// => false
console.log("isEvaluatedOffchain with naive evaluation?", naiveEval);
console.log("isEvaluatedOffchain with fancy evaluation?", fancyEval);
https://github.com/Vectorized/solady/pull/876
contract to check the values:
https://holesky.etherscan.io/address/0x881edfb1cd148894fd50542d77fda8004d5c8056#readContract