See·two-phase async
ᛇ
Image Generation
Generate images
DALL-E and others. Returns content URI + content hash + dimensions.
0x0000000000000000000000000000000000000818Explorer
Two-phase async. eth_call validates encoding only. Real generation requires a consumer contract with
onImageReady callback — paste the exported Solidity to your project.click 'auto' (capability = 4)
What to generate
px
px
min escrow: 0.1000 RITUALyou have: — RITUAL
Connect your wallet to submit a real transaction.
to: 0x0000000000000000000000000000000000000818chainId 1979 · two-phase
Output
Click Validate to encode the 21-field image request.
1024 × 1024 · FLUX.2-klein-4B
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.24;
import {PrecompileConsumer} from "./utils/PrecompileConsumer.sol";
contract ImageMinter is PrecompileConsumer {
address constant IMAGE = address(0x818);
address constant ASYNC_DELIVERY = 0x5A16214fF555848411544b005f7Ac063742f39F6;
struct StorageRef { string platform; string path; string credentials; }
struct ModalInput {
uint8 inputType; bytes data; string uri; bytes32 contentHash;
uint32 param1; uint32 param2; bool encrypted;
}
struct OutputConfig {
uint8 outputType; uint32 maxParam1; uint32 maxParam2; uint32 maxParam3;
bool encryptOutput; uint16 numInferenceSteps; uint16 guidanceScaleX100;
uint32 seed; uint8 fps; string negativePrompt;
}
event ImageRequested(bytes32 indexed jobId, address indexed sender);
event ImageReady(bytes32 indexed jobId, string uri, uint32 width, uint32 height);
mapping(bytes32 => address) public pending;
function generate(address executor) external {
ModalInput[] memory inputs = new ModalInput[](1);
inputs[0] = ModalInput({
inputType: 0,
data: bytes("A mystical sigil glowing on a black obsidian altar, ember + violet light, hyperdetailed"),
uri: "",
contentHash: bytes32(0),
param1: 0, param2: 0, encrypted: false
});
OutputConfig memory output = OutputConfig({
outputType: 1,
maxParam1: 1024, maxParam2: 1024, maxParam3: 0,
encryptOutput: false,
numInferenceSteps: 28,
guidanceScaleX100: 750,
seed: 1979,
fps: 0,
negativePrompt: "blurry, low quality, watermark"
});
StorageRef memory storage_ = StorageRef(
"gcs",
"images/sigil-playground",
"GCS_CREDS"
);
bytes memory encoded = abi.encode(
executor,
new bytes[](0), uint256(300), new bytes[](0), bytes(""),
uint64(5), uint64(400), "IMAGE_TASK_ID",
address(this), this.onImageReady.selector,
uint256(500000), uint256(1_000_000_000), uint256(100_000_000), uint256(0),
"black-forest-labs/FLUX.2-klein-4B",
inputs, output, storage_,
new bytes[](0)
);
(bool ok,) = IMAGE.call(encoded);
require(ok, "image precompile failed");
bytes32 jobId = keccak256(abi.encodePacked(block.number, msg.sender));
pending[jobId] = msg.sender;
emit ImageRequested(jobId, msg.sender);
}
/// @notice AsyncDelivery callback after Phase 2 settles.
function onImageReady(bytes32 jobId, bytes calldata result) external {
require(msg.sender == ASYNC_DELIVERY, "unauth");
(bool hasError, , string memory uri, , , , uint32 width, uint32 height, ) =
abi.decode(result,
(bool, bytes, string, bytes32, bool, uint32, uint32, uint32, string));
require(!hasError, "image gen failed");
emit ImageReady(jobId, uri, width, height);
// Mint NFT, store URI, etc. — pending[jobId] knows the recipient
}
}