Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
- Contract name:
- Risc0CircuitVerifier
- Optimization enabled
- true
- Compiler version
- v0.8.33+commit.64118f21
- Optimization runs
- 200
- EVM Version
- shanghai
- Verified at
- 2026-02-24T05:53:10.764758Z
Constructor Arguments
0x000000000000000000000000d1934807041b168f383870a0d8f565ade2df9d7d37a5e85c934ec15f7752cfced2f407f40e6c28978dffcb3b895dc100a76acaf8
Arg [0] (address) : 0xd1934807041b168f383870a0d8f565ade2df9d7d
Arg [1] (bytes32) : 37a5e85c934ec15f7752cfced2f407f40e6c28978dffcb3b895dc100a76acaf8
src/impl/Risc0CircuitVerifier.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.33;
import {ICircuitVerifier} from "../iface/ICircuitVerifier.sol";
import {IRiscZeroVerifier} from "../iface/IRiscZeroVerifier.sol";
/// @custom:security-contact security@taiko.xyz
/// @notice Adapter that binds Shadow public inputs to a RISC Zero journal and
/// delegates seal verification to a deployed RISC0 verifier contract.
contract Risc0CircuitVerifier is ICircuitVerifier {
error ZeroVerifier();
error InvalidPublicInputsLength(uint256 actual);
error InvalidProofEncoding();
error InvalidJournalLength(uint256 actual);
error JournalBlockNumberMismatch(uint256 expected, uint256 actual);
error JournalChainIdMismatch(uint256 expected, uint256 actual);
error JournalAmountMismatch(uint256 expected, uint256 actual);
error JournalBlockHashMismatch(bytes32 expected, bytes32 actual);
error JournalRecipientMismatch(address expected, address actual);
error JournalNullifierMismatch(bytes32 expected, bytes32 actual);
error PublicInputByteOutOfRange(uint256 index, uint256 value);
IRiscZeroVerifier public immutable risc0Verifier;
bytes32 public immutable imageId;
uint256 private constant _PUBLIC_INPUTS_LEN = 87;
uint256 private constant _IDX_BLOCK_NUMBER = 0;
uint256 private constant _IDX_BLOCK_HASH = 1;
uint256 private constant _IDX_CHAIN_ID = 33;
uint256 private constant _IDX_AMOUNT = 34;
uint256 private constant _IDX_RECIPIENT = 35;
uint256 private constant _IDX_NULLIFIER = 55;
uint256 private constant _JOURNAL_LEN = 116;
uint256 private constant _OFFSET_BLOCK_NUMBER = 0;
uint256 private constant _OFFSET_BLOCK_HASH = 8;
uint256 private constant _OFFSET_CHAIN_ID = 40;
uint256 private constant _OFFSET_AMOUNT = 48;
uint256 private constant _OFFSET_RECIPIENT = 64;
uint256 private constant _OFFSET_NULLIFIER = 84;
constructor(address _risc0Verifier, bytes32 _imageId) {
require(_risc0Verifier != address(0), ZeroVerifier());
risc0Verifier = IRiscZeroVerifier(_risc0Verifier);
imageId = _imageId;
}
/// @notice Decode proof payload `(bytes seal, bytes journal)`.
function decodeProof(bytes calldata _proof) external pure returns (bytes memory _seal_, bytes memory _journal_) {
(_seal_, _journal_) = abi.decode(_proof, (bytes, bytes));
}
function verifyProof(bytes calldata _proof, uint256[] calldata _publicInputs)
external
view
returns (bool _isValid_)
{
bytes memory seal;
bytes32 journalDigest;
try this.decodeAndValidateProof(_proof, _publicInputs) returns (
bytes memory decodedSeal, bytes32 decodedJournalDigest
) {
seal = decodedSeal;
journalDigest = decodedJournalDigest;
} catch {
return false;
}
try risc0Verifier.verify(seal, imageId, journalDigest) {
_isValid_ = true;
} catch {
_isValid_ = false;
}
}
/// @notice Decodes and validates proof payload and binding against public inputs.
/// @dev Intended for internal `try/catch` orchestration in `verifyProof`.
function decodeAndValidateProof(bytes calldata _proof, uint256[] calldata _publicInputs)
external
view
returns (bytes memory seal_, bytes32 journalDigest_)
{
require(_publicInputs.length == _PUBLIC_INPUTS_LEN, InvalidPublicInputsLength(_publicInputs.length));
bytes memory seal;
bytes memory journal;
try this.decodeProof(_proof) returns (bytes memory decodedSeal, bytes memory decodedJournal) {
seal = decodedSeal;
journal = decodedJournal;
} catch {
require(false, InvalidProofEncoding());
}
_requireJournalMatchesPublicInputs(journal, _publicInputs);
seal_ = seal;
journalDigest_ = sha256(journal);
}
function _requireJournalMatchesPublicInputs(bytes memory _journal, uint256[] calldata _publicInputs) private pure {
require(_journal.length == _JOURNAL_LEN, InvalidJournalLength(_journal.length));
uint256 blockNumber = _readLeUint(_journal, _OFFSET_BLOCK_NUMBER, 8);
require(
blockNumber == _publicInputs[_IDX_BLOCK_NUMBER],
JournalBlockNumberMismatch(_publicInputs[_IDX_BLOCK_NUMBER], blockNumber)
);
uint256 chainId = _readLeUint(_journal, _OFFSET_CHAIN_ID, 8);
require(chainId == _publicInputs[_IDX_CHAIN_ID], JournalChainIdMismatch(_publicInputs[_IDX_CHAIN_ID], chainId));
uint256 amount = _readLeUint(_journal, _OFFSET_AMOUNT, 16);
require(amount == _publicInputs[_IDX_AMOUNT], JournalAmountMismatch(_publicInputs[_IDX_AMOUNT], amount));
bytes32 blockHash = _readBytes32(_journal, _OFFSET_BLOCK_HASH);
bytes32 nullifier = _readBytes32(_journal, _OFFSET_NULLIFIER);
address recipient = _readAddress(_journal, _OFFSET_RECIPIENT);
bytes32 expectedBlockHash = _readBytes32FromPublicInputs(_publicInputs, _IDX_BLOCK_HASH);
require(blockHash == expectedBlockHash, JournalBlockHashMismatch(expectedBlockHash, blockHash));
address expectedRecipient = _readAddressFromPublicInputs(_publicInputs, _IDX_RECIPIENT);
require(recipient == expectedRecipient, JournalRecipientMismatch(expectedRecipient, recipient));
bytes32 expectedNullifier = _readBytes32FromPublicInputs(_publicInputs, _IDX_NULLIFIER);
require(nullifier == expectedNullifier, JournalNullifierMismatch(expectedNullifier, nullifier));
}
function _readLeUint(bytes memory _data, uint256 _offset, uint256 _len) private pure returns (uint256 value_) {
for (uint256 i = 0; i < _len; ++i) {
value_ |= uint256(uint8(_data[_offset + i])) << (8 * i);
}
}
function _readBytes32(bytes memory _data, uint256 _offset) private pure returns (bytes32 value_) {
assembly {
value_ := mload(add(add(_data, 0x20), _offset))
}
}
function _readAddress(bytes memory _data, uint256 _offset) private pure returns (address addr_) {
uint256 word;
for (uint256 i = 0; i < 20; ++i) {
word = (word << 8) | uint8(_data[_offset + i]);
}
addr_ = address(uint160(word));
}
function _readBytes32FromPublicInputs(uint256[] calldata _publicInputs, uint256 _offset)
private
pure
returns (bytes32 value_)
{
uint256 word;
for (uint256 i = 0; i < 32; ++i) {
uint256 b = _publicInputs[_offset + i];
require(b <= type(uint8).max, PublicInputByteOutOfRange(_offset + i, b));
word = (word << 8) | b;
}
value_ = bytes32(word);
}
function _readAddressFromPublicInputs(uint256[] calldata _publicInputs, uint256 _offset)
private
pure
returns (address addr_)
{
uint256 word;
for (uint256 i = 0; i < 20; ++i) {
uint256 b = _publicInputs[_offset + i];
require(b <= type(uint8).max, PublicInputByteOutOfRange(_offset + i, b));
word = (word << 8) | b;
}
addr_ = address(uint160(word));
}
}
src/iface/ICircuitVerifier.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.33;
/// @custom:security-contact security@taiko.xyz
interface ICircuitVerifier {
/// @notice Verifies a proof against public inputs.
function verifyProof(bytes calldata _proof, uint256[] calldata _publicInputs)
external
view
returns (bool _isValid_);
}
src/iface/IRiscZeroVerifier.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.33;
/// @custom:security-contact security@taiko.xyz
interface IRiscZeroVerifier {
/// @notice Verify a RISC Zero receipt seal for an image ID and journal digest.
function verify(bytes calldata _seal, bytes32 _imageId, bytes32 _journalDigest) external view;
}
Compiler Settings
{"viaIR":true,"remappings":["forge-std/=node_modules/forge-std/src/","@openzeppelin/contracts/=node_modules/@openzeppelin/contracts/","@openzeppelin/contracts-upgradeable/=node_modules/@openzeppelin/contracts-upgradeable/","risc0-ethereum/=lib/risc0-ethereum/contracts/src/","openzeppelin/contracts/=node_modules/@openzeppelin/contracts/"],"outputSelection":{"*":{"*":["*"],"":["*"]}},"optimizer":{"runs":200,"enabled":true},"metadata":{"useLiteralContent":false,"bytecodeHash":"ipfs","appendCBOR":true},"libraries":{},"evmVersion":"shanghai"}
Contract ABI
[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"address","name":"_risc0Verifier","internalType":"address"},{"type":"bytes32","name":"_imageId","internalType":"bytes32"}]},{"type":"error","name":"InvalidJournalLength","inputs":[{"type":"uint256","name":"actual","internalType":"uint256"}]},{"type":"error","name":"InvalidProofEncoding","inputs":[]},{"type":"error","name":"InvalidPublicInputsLength","inputs":[{"type":"uint256","name":"actual","internalType":"uint256"}]},{"type":"error","name":"JournalAmountMismatch","inputs":[{"type":"uint256","name":"expected","internalType":"uint256"},{"type":"uint256","name":"actual","internalType":"uint256"}]},{"type":"error","name":"JournalBlockHashMismatch","inputs":[{"type":"bytes32","name":"expected","internalType":"bytes32"},{"type":"bytes32","name":"actual","internalType":"bytes32"}]},{"type":"error","name":"JournalBlockNumberMismatch","inputs":[{"type":"uint256","name":"expected","internalType":"uint256"},{"type":"uint256","name":"actual","internalType":"uint256"}]},{"type":"error","name":"JournalChainIdMismatch","inputs":[{"type":"uint256","name":"expected","internalType":"uint256"},{"type":"uint256","name":"actual","internalType":"uint256"}]},{"type":"error","name":"JournalNullifierMismatch","inputs":[{"type":"bytes32","name":"expected","internalType":"bytes32"},{"type":"bytes32","name":"actual","internalType":"bytes32"}]},{"type":"error","name":"JournalRecipientMismatch","inputs":[{"type":"address","name":"expected","internalType":"address"},{"type":"address","name":"actual","internalType":"address"}]},{"type":"error","name":"PublicInputByteOutOfRange","inputs":[{"type":"uint256","name":"index","internalType":"uint256"},{"type":"uint256","name":"value","internalType":"uint256"}]},{"type":"error","name":"ZeroVerifier","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes","name":"seal_","internalType":"bytes"},{"type":"bytes32","name":"journalDigest_","internalType":"bytes32"}],"name":"decodeAndValidateProof","inputs":[{"type":"bytes","name":"_proof","internalType":"bytes"},{"type":"uint256[]","name":"_publicInputs","internalType":"uint256[]"}]},{"type":"function","stateMutability":"pure","outputs":[{"type":"bytes","name":"_seal_","internalType":"bytes"},{"type":"bytes","name":"_journal_","internalType":"bytes"}],"name":"decodeProof","inputs":[{"type":"bytes","name":"_proof","internalType":"bytes"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"imageId","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IRiscZeroVerifier"}],"name":"risc0Verifier","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"bool","name":"_isValid_","internalType":"bool"}],"name":"verifyProof","inputs":[{"type":"bytes","name":"_proof","internalType":"bytes"},{"type":"uint256[]","name":"_publicInputs","internalType":"uint256[]"}]}]
Contract Creation Code
0x60c0346100a157601f610c2938819003918201601f19168301916001600160401b038311848410176100a55780849260409485528339810103126100a15780516001600160a01b03811691908290036100a157602001519080156100925760805260a052604051610b6f90816100ba823960805181818161027c01526105c8015260a05181818161037401526106140152f35b634a8bdce360e01b5f5260045ffd5b5f80fd5b634e487b7160e01b5f52604160045260245ffdfe60806040526004361015610011575f80fd5b5f3560e01c806317279047146100645780631e8e1e131461005f5780635c9770c51461005a578063c9d4ef1f146100555763ef3f7dd514610050575f80fd5b61035d565b6102d3565b610267565b610237565b3461012c576100a45f6100763661015e565b9492610089866057819795949714610397565b60405163c9d4ef1f60e01b81529384928392600484016104b3565b0381305afa92835f925f95610102575b50155f036104cf576020926100d06100dc925f949692836107f1565b604051918280926104de565b039060025afa156100fd575f51906100f96040519283928361021b565b0390f35b6104c4565b9094506101229192503d805f833e61011a81836103c5565b81019061044a565b91909193856100b4565b5f80fd5b9181601f8401121561012c5782359167ffffffffffffffff831161012c576020838186019501011161012c57565b90604060031983011261012c5760043567ffffffffffffffff811161012c578261018a91600401610130565b9290929160243567ffffffffffffffff811161012c578260238201121561012c5780600401359267ffffffffffffffff841161012c5760248460051b8301011161012c576024019190565b5f5b8381106101e65750505f910152565b81810151838201526020016101d7565b9060209161020f815180928185528580860191016101d5565b601f01601f1916010190565b9291906102326020916040865260408601906101f6565b930152565b3461012c57602061025361024a3661015e565b9291909161058a565b6040519015158152f35b5f91031261012c57565b3461012c575f36600319011261012c576040517f00000000000000000000000000000000000000000000000000000000000000006001600160a01b03168152602090f35b90916102c26102d0936040845260408401906101f6565b9160208184039101526101f6565b90565b3461012c57602036600319011261012c5760043567ffffffffffffffff811161012c57610304903690600401610130565b81019060408183031261012c57803567ffffffffffffffff811161012c578261032e918301610696565b91602082013567ffffffffffffffff811161012c5761034d9201610696565b906100f9604051928392836102ab565b3461012c575f36600319011261012c5760206040517f00000000000000000000000000000000000000000000000000000000000000008152f35b1561039f5750565b631d75bf0560e01b5f5260045260245ffd5b634e487b7160e01b5f52604160045260245ffd5b90601f8019910116810190811067ffffffffffffffff8211176103e757604052565b6103b1565b67ffffffffffffffff81116103e757601f01601f191660200190565b81601f8201121561012c57805161041e816103ec565b9261042c60405194856103c5565b8184526020828401011161012c576102d091602080850191016101d5565b91909160408184031261012c57805167ffffffffffffffff811161012c5783610474918301610408565b92602082015167ffffffffffffffff811161012c576102d09201610408565b908060209392818452848401375f828201840152601f01601f1916010190565b9160206102d0938181520191610493565b6040513d5f823e3d90fd5b63236bd13760e01b5f5260045ffd5b906104f1602092828151948592016101d5565b0190565b919060408382031261012c57825167ffffffffffffffff811161012c57602091610520918501610408565b92015190565b919061053a91604084526040840191610493565b8181036020909201919091528281526001600160fb1b03831161012c5760209260051b809284830137010190565b610580604092959493956060835260608301906101f6565b9460208201520152565b6105ab5f93946040519586948594631727904760e01b865260048601610526565b0381305afa90815f915f93610670575b506105c65750505f90565b7f00000000000000000000000000000000000000000000000000000000000000006001600160a01b031691823b1561012c5760405163ab750e7560e01b8152925f9284928391829161063d917f00000000000000000000000000000000000000000000000000000000000000009060048501610568565b03915afa9081610656575b50610651575f90565b600190565b806106645f61066a936103c5565b8061025d565b5f610648565b90925061068f91503d805f833e61068781836103c5565b8101906104f5565b915f6105bb565b81601f8201121561012c578035906106ad826103ec565b926106bb60405194856103c5565b8284526020838301011161012c57815f926020809301838601378301015290565b634e487b7160e01b5f52603260045260245ffd5b90156106f95790565b6106dc565b90602110156106f9576104200190565b90602210156106f9576104400190565b91908110156106f95760051b0190565b15610737575050565b63e382912560e01b5f5260045260245260445ffd5b15610755575050565b63591c97fb60e11b5f5260045260245260445ffd5b15610773575050565b63f81c222960e01b5f5260045260245260445ffd5b15610791575050565b633a62068960e21b5f5260045260245260445ffd5b156107af575050565b6382238b7760e01b5f9081526001600160a01b039182166004529116602452604490fd5b156107dc575050565b63089d5fad60e31b5f5260045260245260445ffd5b91908251607481036108de575082916108d4916108316108136108dc96610915565b61081d84846106f0565b3561082885856106f0565b3590821461072e565b61085b61083d8561095e565b61084784846106fe565b3561085285856106fe565b3590821461074c565b610885610867856109ae565b610871848461070e565b3561087c858561070e565b3590821461076a565b6108cf60288501516108b161089e6074880151976109fe565b916108a98686610a63565b808214610788565b6108bb8484610af0565b6001600160a01b03828116908216146107a6565b610ab0565b8082146107d3565b565b63b0fe347f60e01b5f5260045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b9081518110156106f9570160200190565b905f915f905b60088210610927575050565b90926109338483610904565b5160f81c906001600160fd1b0385168503610959576001918560031b1b1793019061091b565b6108f0565b905f915f905b60088210610970575050565b90928360280180602811610959576109889083610904565b5160f81c906001600160fd1b0385168503610959576001918560031b1b17930190610964565b905f915f905b601082106109c0575050565b90928360300180603011610959576109d89083610904565b5160f81c906001600160fd1b0385168503610959576001918560031b1b179301906109b4565b5f905f905b60148210610a195750506001600160a01b031690565b909182604001908160401161095957610a3460019284610904565b5160f81c9060081b17920190610a03565b15610a4e575050565b639552326f60e01b5f5260045260245260445ffd5b5f915f915b60208310610a765750505090565b909192836001018060011161095957600191610aa3610a9683878761071e565b35809360ff821115610a45565b60081b1793019190610a68565b5f915f915b60208310610ac35750505090565b909192836037018060371161095957600191610ae3610a9683878761071e565b60081b1793019190610ab5565b5f915f915b60148310610b0c575050506001600160a01b031690565b909192836023018060231161095957600191610b2c610a9683878761071e565b60081b1793019190610af556fea264697066735822122052bde3379f70be20252109abe22a9dfeecc739a4f1648a0cf71468a85ce82d7664736f6c63430008210033000000000000000000000000d1934807041b168f383870a0d8f565ade2df9d7d37a5e85c934ec15f7752cfced2f407f40e6c28978dffcb3b895dc100a76acaf8
Deployed ByteCode
0x60806040526004361015610011575f80fd5b5f3560e01c806317279047146100645780631e8e1e131461005f5780635c9770c51461005a578063c9d4ef1f146100555763ef3f7dd514610050575f80fd5b61035d565b6102d3565b610267565b610237565b3461012c576100a45f6100763661015e565b9492610089866057819795949714610397565b60405163c9d4ef1f60e01b81529384928392600484016104b3565b0381305afa92835f925f95610102575b50155f036104cf576020926100d06100dc925f949692836107f1565b604051918280926104de565b039060025afa156100fd575f51906100f96040519283928361021b565b0390f35b6104c4565b9094506101229192503d805f833e61011a81836103c5565b81019061044a565b91909193856100b4565b5f80fd5b9181601f8401121561012c5782359167ffffffffffffffff831161012c576020838186019501011161012c57565b90604060031983011261012c5760043567ffffffffffffffff811161012c578261018a91600401610130565b9290929160243567ffffffffffffffff811161012c578260238201121561012c5780600401359267ffffffffffffffff841161012c5760248460051b8301011161012c576024019190565b5f5b8381106101e65750505f910152565b81810151838201526020016101d7565b9060209161020f815180928185528580860191016101d5565b601f01601f1916010190565b9291906102326020916040865260408601906101f6565b930152565b3461012c57602061025361024a3661015e565b9291909161058a565b6040519015158152f35b5f91031261012c57565b3461012c575f36600319011261012c576040517f000000000000000000000000d1934807041b168f383870a0d8f565ade2df9d7d6001600160a01b03168152602090f35b90916102c26102d0936040845260408401906101f6565b9160208184039101526101f6565b90565b3461012c57602036600319011261012c5760043567ffffffffffffffff811161012c57610304903690600401610130565b81019060408183031261012c57803567ffffffffffffffff811161012c578261032e918301610696565b91602082013567ffffffffffffffff811161012c5761034d9201610696565b906100f9604051928392836102ab565b3461012c575f36600319011261012c5760206040517f37a5e85c934ec15f7752cfced2f407f40e6c28978dffcb3b895dc100a76acaf88152f35b1561039f5750565b631d75bf0560e01b5f5260045260245ffd5b634e487b7160e01b5f52604160045260245ffd5b90601f8019910116810190811067ffffffffffffffff8211176103e757604052565b6103b1565b67ffffffffffffffff81116103e757601f01601f191660200190565b81601f8201121561012c57805161041e816103ec565b9261042c60405194856103c5565b8184526020828401011161012c576102d091602080850191016101d5565b91909160408184031261012c57805167ffffffffffffffff811161012c5783610474918301610408565b92602082015167ffffffffffffffff811161012c576102d09201610408565b908060209392818452848401375f828201840152601f01601f1916010190565b9160206102d0938181520191610493565b6040513d5f823e3d90fd5b63236bd13760e01b5f5260045ffd5b906104f1602092828151948592016101d5565b0190565b919060408382031261012c57825167ffffffffffffffff811161012c57602091610520918501610408565b92015190565b919061053a91604084526040840191610493565b8181036020909201919091528281526001600160fb1b03831161012c5760209260051b809284830137010190565b610580604092959493956060835260608301906101f6565b9460208201520152565b6105ab5f93946040519586948594631727904760e01b865260048601610526565b0381305afa90815f915f93610670575b506105c65750505f90565b7f000000000000000000000000d1934807041b168f383870a0d8f565ade2df9d7d6001600160a01b031691823b1561012c5760405163ab750e7560e01b8152925f9284928391829161063d917f37a5e85c934ec15f7752cfced2f407f40e6c28978dffcb3b895dc100a76acaf89060048501610568565b03915afa9081610656575b50610651575f90565b600190565b806106645f61066a936103c5565b8061025d565b5f610648565b90925061068f91503d805f833e61068781836103c5565b8101906104f5565b915f6105bb565b81601f8201121561012c578035906106ad826103ec565b926106bb60405194856103c5565b8284526020838301011161012c57815f926020809301838601378301015290565b634e487b7160e01b5f52603260045260245ffd5b90156106f95790565b6106dc565b90602110156106f9576104200190565b90602210156106f9576104400190565b91908110156106f95760051b0190565b15610737575050565b63e382912560e01b5f5260045260245260445ffd5b15610755575050565b63591c97fb60e11b5f5260045260245260445ffd5b15610773575050565b63f81c222960e01b5f5260045260245260445ffd5b15610791575050565b633a62068960e21b5f5260045260245260445ffd5b156107af575050565b6382238b7760e01b5f9081526001600160a01b039182166004529116602452604490fd5b156107dc575050565b63089d5fad60e31b5f5260045260245260445ffd5b91908251607481036108de575082916108d4916108316108136108dc96610915565b61081d84846106f0565b3561082885856106f0565b3590821461072e565b61085b61083d8561095e565b61084784846106fe565b3561085285856106fe565b3590821461074c565b610885610867856109ae565b610871848461070e565b3561087c858561070e565b3590821461076a565b6108cf60288501516108b161089e6074880151976109fe565b916108a98686610a63565b808214610788565b6108bb8484610af0565b6001600160a01b03828116908216146107a6565b610ab0565b8082146107d3565b565b63b0fe347f60e01b5f5260045260245ffd5b634e487b7160e01b5f52601160045260245ffd5b9081518110156106f9570160200190565b905f915f905b60088210610927575050565b90926109338483610904565b5160f81c906001600160fd1b0385168503610959576001918560031b1b1793019061091b565b6108f0565b905f915f905b60088210610970575050565b90928360280180602811610959576109889083610904565b5160f81c906001600160fd1b0385168503610959576001918560031b1b17930190610964565b905f915f905b601082106109c0575050565b90928360300180603011610959576109d89083610904565b5160f81c906001600160fd1b0385168503610959576001918560031b1b179301906109b4565b5f905f905b60148210610a195750506001600160a01b031690565b909182604001908160401161095957610a3460019284610904565b5160f81c9060081b17920190610a03565b15610a4e575050565b639552326f60e01b5f5260045260245260445ffd5b5f915f915b60208310610a765750505090565b909192836001018060011161095957600191610aa3610a9683878761071e565b35809360ff821115610a45565b60081b1793019190610a68565b5f915f915b60208310610ac35750505090565b909192836037018060371161095957600191610ae3610a9683878761071e565b60081b1793019190610ab5565b5f915f915b60148310610b0c575050506001600160a01b031690565b909192836023018060231161095957600191610b2c610a9683878761071e565b60081b1793019190610af556fea264697066735822122052bde3379f70be20252109abe22a9dfeecc739a4f1648a0cf71468a85ce82d7664736f6c63430008210033