Appearance
Read a contract nobody has verified
Call a function by its signature when no ABI can be found, and keep the ABI in your library once you have it.
Not available yet
.call() and revert_reason() are not available in the workbench yet. This page shows the queries as the language defines them; they run unchanged once they are.
cql
let stETH = ethereum:0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84;
let wstETH = ethereum:0x7f39C581F595B53c5cb19bD0b3f8dA6c935E2Ca0;
from stETH with { abi: none } as c
| project {
ethPerShare: c.call('getPooledEthByShares(uint256)(uint256)', 1e18),
balance: c.call('balanceOf(address)(uint256)', wstETH),
locator: c.call('getLidoLocator()(address)')
}One row with the three values, decoded by the signatures you wrote — the same numbers the ABI gives, since these are stETH's own functions. A call the contract does not understand comes back null, and revert_reason(c.call('owner()(address)')) says why.
How it reads
with { abi: none } says not to look for an ABI at all, and .call(sig, args…) calls a function by its signature — name(inputs)(outputs). The inputs are what the arguments are encoded as, the outputs what the answer is decoded as; leave the outputs off and you get the raw bytes.
You do not need abi: none to use .call — it works alongside an ABI, and is how you reach an overloaded function unambiguously. stETH is verified, so here it only shows the shape; on a contract that is not, it also saves waiting for a lookup that will fail.
Keeping the ABI
Writing signatures into every query gets old. When you have the ABI — from the team that deployed the contract, from a compiler's output — click Add ABI under ABI library in the workbench's left rail, give it a name, and paste the JSON or a list of signatures, or drop the compiler's output file onto the dialog. From then on:
cql
let stETH = ethereum:0xae7ab96520DE3A18E5e111B5EaAb095312D7fE84 with { abi: 'lido' };
from stETH as s
| project { ethPerShare: format(s.getPooledEthByShares(1e18), 18), locator: s.getLidoLocator() }Open the entry and Insert writes with { abi: 'lido' } at your cursor. Uploading under a name that already exists replaces it, as does Replace contents on the entry, and every query that names it reads the new one on its next run.
If it was verified after all
A contract can be verified after CQL last looked, and CQL remembers a not verified answer for a while. Beside CQL3008 in the diagnostics list is a Check again button that forgets the answer and asks the verification services once more.