Skip to content

Instantly share code, notes, and snippets.

@tynes
Last active June 4, 2025 23:49
Show Gist options
  • Save tynes/0f565318646292d22b20bf425fbcfa85 to your computer and use it in GitHub Desktop.
Save tynes/0f565318646292d22b20bf425fbcfa85 to your computer and use it in GitHub Desktop.
Ithaca Account OP Stack Interop Signer Auth
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.23;
import {IIthacaAccount} from "./interfaces/IIthacaAccount.sol";
import {ISigner} from "./interfaces/ISigner.sol";
struct Identifier {
address origin;
uint256 blockNumber;
uint256 logIndex;
uint256 timestamp;
uint256 chainId;
}
interface ICrossL2Inbox {
function validateMessage(Identifier calldata _id, bytes32 _msgHash) external;
}
// most simple implementation, requires a change to IthacaAccount
contract InteropSigner is ISigner {
address internal constant CROSS_L2_INBOX = 0x4200000000000000000000000000000000000022;
bytes4 internal constant _MAGIC_VALUE = 0x8afc93b4;
// this is static called by the IthacaAccount but interop validation uses LOG opcode
// if updated to use call, this should work, but need to not double hash digest with sha2
function isValidSignatureWithKeyHash(bytes32 digest, bytes32, bytes memory signature)
public
returns (bytes4 magicValue)
{
Identifier memory id = abi.decode(signature, (Identifier));
//
ICrossL2Inbox(CROSS_L2_INBOX).validateMessage(id, digest);
return _MAGIC_VALUE;
}
}
// If there is no desire to change the static call into a call, we can do an alternative approach
// 1. user calls `validateMessage`, stores the hash after its been validated
// 2. IthacaAccount calls `isValidSignatureWithKeyHash`
contract InteropSigner is ISigner {
bytes4 internal constant _MAGIC_VALUE = 0x8afc93b4;
bytes4 internal constant _FAIL_VALUE = 0xffffffff;
mapping(bytes32 => bool) valid;
function validateMessage(Identifier calldata _id, bytes32 _msgHash) external {
ICrossL2Inbox(CROSS_L2_INBOX).validateMessage(_id, _msgHash);
valid[_msgHash] = true;
}
// not exactly sure how to do replay protection
function isValidSignatureWithKeyHash(bytes32 digest, bytes32, bytes memory signature)
public
view
returns (bytes4 magicValue)
{
if (valid[_msgHash]) return _MAGIC_VALUE;
return _FAIL_VALUE;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment