Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
- Contract name:
- P256Verifier
- Optimization enabled
- true
- Compiler version
- v0.8.30+commit.73712a01
- Optimization runs
- 200
- EVM Version
- prague
- Verified at
- 2025-12-15T12:45:59.609128Z
node_modules/p256-verifier/src/P256Verifier.sol
// SPDX-License-Identifier: MIT
// Force a specific Solidity version for reproducibility.
pragma solidity ^0.8.20;
/**
* This contract verifies P256 (secp256r1) signatures. It matches the exact
* interface specified in the EIP-7212 precompile, allowing it to be used as a
* fallback. It's based on Ledger's optimized implementation:
* https://github.com/rdubois-crypto/FreshCryptoLib/tree/master/solidity
**/
contract P256Verifier {
struct CompDoubleZZ {
uint256 comp_U;
uint256 comp_V;
uint256 comp_W;
uint256 comp_S;
uint256 comp_M;
}
struct CompDaddAffine {
uint256 comp_P;
uint256 comp_PP;
uint256 comp_PPP;
uint256 comp_Q;
uint256 comp_R;
}
/**
* Precompiles don't use a function signature. The first byte of callldata
* is the first byte of an input argument. In this case:
*
* input[ 0: 32] = signed data hash
* input[ 32: 64] = signature r
* input[ 64: 96] = signature s
* input[ 96:128] = public key x
* input[128:160] = public key y
*
* result[ 0: 32] = 0x00..00 (invalid) or 0x00..01 (valid)
*
* For details, see https://eips.ethereum.org/EIPS/eip-7212
*/
fallback(bytes calldata input) external returns (bytes memory) {
if (input.length != 160) {
return abi.encodePacked(uint256(0));
}
bytes32 hash = bytes32(input[0:32]);
uint256 r = uint256(bytes32(input[32:64]));
uint256 s = uint256(bytes32(input[64:96]));
uint256 x = uint256(bytes32(input[96:128]));
uint256 y = uint256(bytes32(input[128:160]));
uint256 ret = ecdsa_verify(hash, r, s, [x, y]) ? 1 : 0;
return abi.encodePacked(ret);
}
// Parameters for the sec256r1 (P256) elliptic curve
// Curve prime field modulus
uint256 constant p =
0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFF;
// Short weierstrass first coefficient
uint256 constant a = // The assumption a == -3 (mod p) is used throughout the codebase
0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFC;
// Short weierstrass second coefficient
uint256 constant b =
0x5AC635D8AA3A93E7B3EBBD55769886BC651D06B0CC53B0F63BCE3C3E27D2604B;
// Generating point affine coordinates
uint256 constant GX =
0x6B17D1F2E12C4247F8BCE6E563A440F277037D812DEB33A0F4A13945D898C296;
uint256 constant GY =
0x4FE342E2FE1A7F9B8EE7EB4A7C0F9E162BCE33576B315ECECBB6406837BF51F5;
// Curve order (number of points)
uint256 constant n =
0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC632551;
// -2 mod p constant, used to speed up inversion and doubling (avoid negation)
uint256 constant minus_2modp =
0xFFFFFFFF00000001000000000000000000000000FFFFFFFFFFFFFFFFFFFFFFFD;
// -2 mod n constant, used to speed up inversion
uint256 constant minus_2modn =
0xFFFFFFFF00000000FFFFFFFFFFFFFFFFBCE6FAADA7179E84F3B9CAC2FC63254F;
/**
* @dev ECDSA verification given signature and public key.
*/
function ecdsa_verify(
bytes32 message_hash,
uint256 r,
uint256 s,
uint256[2] memory pubKey
) private view returns (bool) {
// Check r and s are in the scalar field
if (r == 0 || r >= n || s == 0 || s >= n) {
return false;
}
if (!ecAff_isValidPubkey(pubKey[0], pubKey[1])) {
return false;
}
uint256 sInv = nModInv(s);
uint256 scalar_u = mulmod(uint256(message_hash), sInv, n); // (h * s^-1) in scalar field
uint256 scalar_v = mulmod(r, sInv, n); // (r * s^-1) in scalar field
uint256 r_x = ecZZ_mulmuladd(
pubKey[0],
pubKey[1],
scalar_u,
scalar_v
);
return r_x % n == r;
}
/**
* @dev Check if a point in affine coordinates is on the curve
* Reject 0 point at infinity.
*/
function ecAff_isValidPubkey(
uint256 x,
uint256 y
) internal pure returns (bool) {
if (x >= p || y >= p || (x == 0 && y == 0)) {
return false;
}
return ecAff_satisfiesCurveEqn(x, y);
}
function ecAff_satisfiesCurveEqn(
uint256 x,
uint256 y
) internal pure returns (bool) {
uint256 LHS = mulmod(y, y, p); // y^2
uint256 RHS = addmod(mulmod(mulmod(x, x, p), x, p), mulmod(a, x, p), p); // x^3 + a x
RHS = addmod(RHS, b, p); // x^3 + a*x + b
return LHS == RHS;
}
/**
* @dev Computation of uG + vQ using Strauss-Shamir's trick, G basepoint, Q public key
* returns tuple of (x coordinate of uG + vQ, boolean that is false if internal precompile staticcall fail)
* Strauss-Shamir is described well in https://stackoverflow.com/a/50994362
*/
function ecZZ_mulmuladd(
uint256 QX,
uint256 QY, // affine rep for input point Q
uint256 scalar_u,
uint256 scalar_v
) internal view returns (uint256 X) {
uint256 zz = 1;
uint256 zzz = 1;
uint256 Y;
uint256 HX;
uint256 HY;
if (scalar_u == 0 && scalar_v == 0) return 0;
// H = g + Q
(HX, HY) = ecAff_add(GX, GY, QX, QY);
int256 index = 255;
uint256 bitpair;
// Find the first bit index that's active in either scalar_u or scalar_v.
while(index >= 0) {
bitpair = compute_bitpair(uint256(index), scalar_u, scalar_v);
index--;
if (bitpair != 0) break;
}
// initialise (X, Y) depending on the first active bitpair.
// invariant(bitpair != 0); // bitpair == 0 is only possible if u and v are 0.
if (bitpair == 1) {
(X, Y) = (GX, GY);
} else if (bitpair == 2) {
(X, Y) = (QX, QY);
} else if (bitpair == 3) {
(X, Y) = (HX, HY);
}
uint256 TX;
uint256 TY;
while(index >= 0) {
(X, Y, zz, zzz) = ecZZ_double_zz(X, Y, zz, zzz);
bitpair = compute_bitpair(uint256(index), scalar_u, scalar_v);
index--;
if (bitpair == 0) {
continue;
} else if (bitpair == 1) {
(TX, TY) = (GX, GY);
} else if (bitpair == 2) {
(TX, TY) = (QX, QY);
} else {
(TX, TY) = (HX, HY);
}
(X, Y, zz, zzz) = ecZZ_dadd_affine(X, Y, zz, zzz, TX, TY);
}
uint256 zzInv = pModInv(zz); // If zz = 0, zzInv = 0.
X = mulmod(X, zzInv, p); // X/zz
}
/**
* @dev Compute the bits at `index` of u and v and return
* them as 2 bit concatenation. The bit at index 0 is on
* if the `index`th bit of scalar_u is on and the bit at
* index 1 is on if the `index`th bit of scalar_v is on.
* Examples:
* - compute_bitpair(0, 1, 1) == 3
* - compute_bitpair(0, 1, 0) == 1
* - compute_bitpair(0, 0, 1) == 2
*/
function compute_bitpair(uint256 index, uint256 scalar_u, uint256 scalar_v) internal pure returns (uint256 ret) {
ret = (((scalar_v >> index) & 1) << 1) + ((scalar_u >> index) & 1);
}
/**
* @dev Add two elliptic curve points in affine coordinates
* Assumes points are on the EC
*/
function ecAff_add(
uint256 x1,
uint256 y1,
uint256 x2,
uint256 y2
) internal view returns (uint256, uint256) {
// invariant(ecAff_IsZero(x1, y1) || ecAff_isOnCurve(x1, y1));
// invariant(ecAff_IsZero(x2, y2) || ecAff_isOnCurve(x2, y2));
uint256 zz1;
uint256 zzz1;
if (ecAff_IsInf(x1, y1)) return (x2, y2);
if (ecAff_IsInf(x2, y2)) return (x1, y1);
(x1, y1, zz1, zzz1) = ecZZ_dadd_affine(x1, y1, 1, 1, x2, y2);
return ecZZ_SetAff(x1, y1, zz1, zzz1);
}
/**
* @dev Check if a point is the infinity point in affine rep.
* Assumes point is on the EC or is the point at infinity.
*/
function ecAff_IsInf(
uint256 x,
uint256 y
) internal pure returns (bool flag) {
// invariant((x == 0 && y == 0) || ecAff_isOnCurve(x, y));
return (x == 0 && y == 0);
}
/**
* @dev Check if a point is the infinity point in ZZ rep.
* Assumes point is on the EC or is the point at infinity.
*/
function ecZZ_IsInf(
uint256 zz,
uint256 zzz
) internal pure returns (bool flag) {
// invariant((zz == 0 && zzz == 0) || ecAff_isOnCurve(x, y) for affine
// form of the point)
return (zz == 0 && zzz == 0);
}
/**
* @dev Add a ZZ point to an affine point and return as ZZ rep
* Uses madd-2008-s and mdbl-2008-s internally
* https://hyperelliptic.org/EFD/g1p/auto-shortw-xyzz-3.html#addition-madd-2008-s
* Matches https://github.com/supranational/blst/blob/9c87d4a09d6648e933c818118a4418349804ce7f/src/ec_ops.h#L705 closely
* Handles points at infinity gracefully
*/
function ecZZ_dadd_affine(
uint256 x1,
uint256 y1,
uint256 zz1,
uint256 zzz1,
uint256 x2,
uint256 y2
) internal pure returns (uint256 x3, uint256 y3, uint256 zz3, uint256 zzz3) {
if (ecAff_IsInf(x2, y2)) { // (X2, Y2) is point at infinity
if (ecZZ_IsInf(zz1, zzz1)) return ecZZ_PointAtInf();
return (x1, y1, zz1, zzz1);
} else if (ecZZ_IsInf(zz1, zzz1)) { // (X1, Y1) is point at infinity
return (x2, y2, 1, 1);
}
CompDaddAffine memory comp;
comp.comp_R = addmod(mulmod(y2, zzz1, p), p - y1, p); // R = S2 - y1 = y2*zzz1 - y1
comp.comp_P = addmod(mulmod(x2, zz1, p), p - x1, p); // P = U2 - x1 = x2*zz1 - x1
if (comp.comp_P != 0) { // X1 != X2
// invariant(x1 != x2);
comp.comp_PP = mulmod(comp.comp_P, comp.comp_P, p); // PP = P^2
comp.comp_PPP = mulmod(comp.comp_PP, comp.comp_P, p); // PPP = P*PP
zz3 = mulmod(zz1, comp.comp_PP, p); //// ZZ3 = ZZ1*PP
zzz3 = mulmod(zzz1, comp.comp_PPP, p); //// ZZZ3 = ZZZ1*PPP
comp.comp_Q = mulmod(x1, comp.comp_PP, p); // Q = X1*PP
x3 = addmod(
addmod(mulmod(comp.comp_R, comp.comp_R, p), p - comp.comp_PPP, p), // (R^2) + (-PPP)
mulmod(minus_2modp, comp.comp_Q, p), // (-2)*(Q)
p
); // R^2 - PPP - 2*Q
y3 = addmod(
mulmod(addmod(comp.comp_Q, p - x3, p), comp.comp_R, p), //(Q+(-x3))*R
mulmod(p - y1, comp.comp_PPP, p), // (-y1)*PPP
p
); // R*(Q-x3) - y1*PPP
} else if (comp.comp_R == 0) { // X1 == X2 and Y1 == Y2
// invariant(x1 == x2 && y1 == y2);
// Must be affine because (X2, Y2) is affine.
(x3, y3, zz3, zzz3) = ecZZ_double_affine(x2, y2);
} else { // X1 == X2 and Y1 == -Y2
// invariant(x1 == x2 && y1 == p - y2);
(x3, y3, zz3, zzz3) = ecZZ_PointAtInf();
}
return (x3, y3, zz3, zzz3);
}
/**
* @dev Double a ZZ point
* Uses http://hyperelliptic.org/EFD/g1p/auto-shortw-xyzz.html#doubling-dbl-2008-s-1
* Handles point at infinity gracefully
*/
function ecZZ_double_zz(uint256 x1,
uint256 y1, uint256 zz1, uint256 zzz1) internal pure returns (uint256, uint256, uint256, uint256) {
if (ecZZ_IsInf(zz1, zzz1)) return ecZZ_PointAtInf();
CompDoubleZZ memory comp;
comp.comp_U = mulmod(2, y1, p); // U = 2*Y1
comp.comp_V = mulmod(comp.comp_U, comp.comp_U, p); // V = U^2
comp.comp_W = mulmod(comp.comp_U, comp.comp_V, p); // W = U*V
comp.comp_S = mulmod(x1, comp.comp_V, p); // S = X1*V
comp.comp_M = addmod(mulmod(3, mulmod(x1, x1, p), p), mulmod(a, mulmod(zz1, zz1, p), p), p); //M = 3*(X1)^2 + a*(zz1)^2
uint256 x3 = addmod(mulmod(comp.comp_M, comp.comp_M, p), mulmod(minus_2modp, comp.comp_S, p), p); // M^2 + (-2)*S
return(
x3, // M^2 + (-2)*S
addmod(mulmod(comp.comp_M, addmod(comp.comp_S, p - x3, p), p), mulmod(p - comp.comp_W, y1, p), p), // M*(S+(-X3)) + (-W)*Y1
mulmod(comp.comp_V, zz1, p), // V*ZZ1
mulmod(comp.comp_W, zzz1, p) // W*ZZZ1
);
}
/**
* @dev Double an affine point and return as a ZZ point
* Uses http://hyperelliptic.org/EFD/g1p/auto-shortw-xyzz.html#doubling-mdbl-2008-s-1
* Handles point at infinity gracefully
*/
function ecZZ_double_affine(uint256 x1,
uint256 y1) internal pure returns (uint256 x3, uint256 y3, uint256 zz3, uint256 zzz3) {
if (ecAff_IsInf(x1, y1)) return ecZZ_PointAtInf();
uint256 comp_U = mulmod(2, y1, p); // U = 2*Y1
zz3 = mulmod(comp_U, comp_U, p); // V = U^2 = zz3
zzz3 = mulmod(comp_U, zz3, p); // W = U*V = zzz3
uint256 comp_S = mulmod(x1, zz3, p); // S = X1*V
uint256 comp_M = addmod(mulmod(3, mulmod(x1, x1, p), p), a, p); // M = 3*(X1)^2 + a
x3 = addmod(mulmod(comp_M, comp_M, p), mulmod(minus_2modp, comp_S, p), p); // M^2 + (-2)*S
y3 = addmod(mulmod(comp_M, addmod(comp_S, p - x3, p), p), mulmod(p - zzz3, y1, p), p); // M*(S+(-X3)) + (-W)*Y1
}
/**
* @dev Convert from ZZ rep to affine rep
* Assumes (zz)^(3/2) == zzz (i.e. zz == z^2 and zzz == z^3)
* See https://hyperelliptic.org/EFD/g1p/auto-shortw-xyzz-3.html
*/
function ecZZ_SetAff(
uint256 x,
uint256 y,
uint256 zz,
uint256 zzz
) internal view returns (uint256 x1, uint256 y1) {
if(ecZZ_IsInf(zz, zzz)) {
(x1, y1) = ecAffine_PointAtInf();
return (x1, y1);
}
uint256 zzzInv = pModInv(zzz); // 1 / zzz
uint256 zInv = mulmod(zz, zzzInv, p); // 1 / z
uint256 zzInv = mulmod(zInv, zInv, p); // 1 / zz
// invariant(mulmod(FCL_pModInv(zInv), FCL_pModInv(zInv), p) == zz)
// invariant(mulmod(mulmod(FCL_pModInv(zInv), FCL_pModInv(zInv), p), FCL_pModInv(zInv), p) == zzz)
x1 = mulmod(x, zzInv, p); // X / zz
y1 = mulmod(y, zzzInv, p); // y = Y / zzz
}
/**
* @dev Point at infinity in ZZ rep
*/
function ecZZ_PointAtInf() internal pure returns (uint256, uint256, uint256, uint256) {
return (0, 0, 0, 0);
}
/**
* @dev Point at infinity in affine rep
*/
function ecAffine_PointAtInf() internal pure returns (uint256, uint256) {
return (0, 0);
}
/**
* @dev u^-1 mod n
*/
function nModInv(uint256 u) internal view returns (uint256) {
return modInv(u, n, minus_2modn);
}
/**
* @dev u^-1 mod p
*/
function pModInv(uint256 u) internal view returns (uint256) {
return modInv(u, p, minus_2modp);
}
/**
* @dev u^-1 mod f = u^(phi(f) - 1) mod f = u^(f-2) mod f for prime f
* by Fermat's little theorem, compute u^(f-2) mod f using modexp precompile
* Assume f != 0. If u is 0, then u^-1 mod f is undefined mathematically,
* but this function returns 0.
*/
function modInv(uint256 u, uint256 f, uint256 minus_2modf) internal view returns (uint256 result) {
// invariant(f != 0);
// invariant(f prime);
// This seems like a relatively standard way to use this precompile:
// https://github.com/OpenZeppelin/openzeppelin-contracts/pull/3298/files#diff-489d4519a087ca2c75be3315b673587abeca3b302f807643e97efa7de8cb35a5R427
(bool success, bytes memory ret) = (address(0x05).staticcall(abi.encode(32, 32, 32, u, minus_2modf, f)));
assert(success); // precompile should never fail on regular EVM environments
result = abi.decode(ret, (uint256));
}
}
Compiler Settings
{"viaIR":true,"remappings":["openzeppelin/=node_modules/@openzeppelin/","@openzeppelin/=node_modules/@openzeppelin/","@openzeppelin-upgrades/contracts/=node_modules/@openzeppelin/contracts-upgradeable/","@risc0/contracts/=node_modules/risc0-ethereum/contracts/src/","@solady/=node_modules/solady/","solady/src/=node_modules/solady/src/","solady/utils/=node_modules/solady/src/utils/","@optimism/=node_modules/optimism/","@sp1-contracts/=node_modules/sp1-contracts/contracts/","forge-std/=node_modules/forge-std/","@p256-verifier/contracts/=node_modules/p256-verifier/src/","@eth-fabric/urc/=node_modules/urc/src/","ds-test/=node_modules/ds-test/","src/=contracts/","test/=test/","script/=script/","optimism/=node_modules/optimism/","p256-verifier/=node_modules/p256-verifier/","risc0-ethereum/=node_modules/risc0-ethereum/","sp1-contracts/=node_modules/sp1-contracts/","urc/=node_modules/urc/"],"outputSelection":{"*":{"*":["*"],"":["*"]}},"optimizer":{"runs":200,"enabled":true},"metadata":{"useLiteralContent":false,"bytecodeHash":"ipfs","appendCBOR":true},"libraries":{"contracts/layer1/core/libs/LibInboxSetup.sol":{"LibInboxSetup":"0xf88Ef5437749A225621101BE8C1BE1A0cE967758"},"contracts/layer1/core/libs/LibForcedInclusion.sol":{"LibForcedInclusion":"0xd1a27F331c17eD8Cbb6DAbce67A42d6b8a6B0e14"}},"evmVersion":"prague"}
Contract ABI
[{"type":"fallback","stateMutability":"nonpayable"}]
Contract Creation Code
0x60808060405234601557610f29908161001a8239f35b5f80fdfe60c06040523461001a5761001236610054565b602081519101f35b5f80fd5b90601f8019910116810190811067ffffffffffffffff82111761004057604052565b634e487b7160e01b5f52604160045260245ffd5b60a081036100ef578060201161001a575f358160401161001a576020358260601161001a57604035908360801161001a576060359360a01161001a576080359260405193604085019585871067ffffffffffffffff881117610040576100c39660405285526020850152610108565b156100e95760015b60ff60405191166020820152602081526100e660408261001e565b90565b5f6100cb565b506040515f6020820152602081526100e660408261001e565b9291909283158015610275575b801561026d575b8015610256575b61024e5782519161013a602085019384519061028c565b15610245575f8091604051602081019160208352602060408301526020606083015260808201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f60a08201525f516020610eb45f395f51905f5260c082015260c081526101a960e08261001e565b519060055afa913d1561023d573d9267ffffffffffffffff841161004057604051936101df601f8201601f19166020018661001e565b84523d5f602086013e5b156102295760208380518101031261001a575f516020610eb45f395f51905f529384602061022495015191519181818909940991519061037c565b061490565b634e487b7160e01b5f52600160045260245ffd5b6060926101e9565b50505050505f90565b505050505f90565b505f516020610eb45f395f51905f52821015610123565b50811561011c565b505f516020610eb45f395f51905f52841015610115565b600160601b63ffffffff60c01b0319811080159061033f575b801561032e575b61032857600160601b63ffffffff60c01b0319907f5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b90829081816003600160601b0363ffffffff60c01b03190990600160601b63ffffffff60c01b0319908181800909080890600160601b63ffffffff60c01b03199080091490565b50505f90565b50801580156102ac575081156102ac565b50600160601b63ffffffff60c01b03198210156102a5565b600160ff1b8114610368575f190190565b634e487b7160e01b5f52601160045260245ffd5b90926080525f9060019384935f9281158061052a575b61051f576103a083826105f0565b95909460ff60a0525f5b5f60a05112156104f6575b808a036104c5575050505f516020610ed45f395f51905f52955f516020610e945f395f51905f52969593919492955b5f60a0511215610412575050505050505061040d600163ffffffff60601b0360601b1992610534565b900990565b6104239395979891929496986106b2565b80989398979291979188998192819a6104416080518960a05161065c565b61044c60a051610357565b60a052806104655750505050505b9593919492956103e4565b92955092959a5092506104a2959a50600181145f146104ac57505f516020610ed45f395f51905f52935f516020610e945f395f51905f5293610abe565b909792969161045a565b6002036104bc5785938993610abe565b87938793610abe565b600281036104df57505050829581969593919492956103e4565b9197916002190161045a575095508495849661045a565b506105066080518560a05161065c565b61051160a051610357565b60a05280156103aa576103b5565b505050505050505f90565b5060805115610392565b5f8091604051602081019160208352602060408301526020606083015260808201526002600160601b0363ffffffff60c01b031960a0820152600163ffffffff60601b0360601b1960c082015260c0815261059060e08261001e565b519060055afa3d156105e8573d9067ffffffffffffffff821161004057604051916105c5601f8201601f19166020018461001e565b82523d5f602084013e5b156102295760208180518101031261001a576020015190565b6060906105cf565b801580610654575b6106325761062e91610625915f516020610ed45f395f51905f525f516020610e945f395f51905f52610861565b92919091610cf1565b9091565b50505f516020610e945f395f51905f52905f516020610ed45f395f51905f5290565b5081156105f8565b91906002600192841c831b16921c1681018091116103685790565b6040519060a0820182811067ffffffffffffffff821117610040576040525f6080838281528260208201528260408201528260608201520152565b919390841580610859575b61084b576106c9610677565b92600160601b63ffffffff60c01b031982600209808552600160601b63ffffffff60c01b03199080096020850181815285519091600160601b63ffffffff60c01b0319910991604086019283526080600163ffffffff60601b0360601b19835183096060880190815291600160601b63ffffffff60c01b03199081808c80096003600160601b0363ffffffff60c01b03190990600160601b63ffffffff60c01b0319908190800960030908960186815281519096600160601b63ffffffff60c01b03199182906002600160601b0363ffffffff60c01b03190990600160601b63ffffffff60c01b0319908009089551905192600160601b63ffffffff60c01b031987810393908411610368578151600160601b63ffffffff60c01b03199081039a908b11610368579051600160601b63ffffffff60c01b031991900990519097600160601b63ffffffff60c01b031991099597600160601b63ffffffff60c01b03199485910992600160601b63ffffffff60c01b031992839108900908929190565b505f93508392508291508190565b5083156106bd565b91939290935f91811580610ab6575b1561089057505080610886575091906001908190565b9250508180918190565b909391505f61089d610677565b95600160601b63ffffffff60c01b031990810392908311610aa2576080870195600160601b63ffffffff60c01b0319848160018509088752600160601b63ffffffff60c01b0319868103908111610a8e57600160601b63ffffffff60c01b03199081600184090880895215610a5f5750508551600160601b63ffffffff60c01b0319908009602087018181528751909691600160601b63ffffffff60c01b031991900990604088019182526060600163ffffffff60601b03811b19885160010997600163ffffffff60601b03821b19845160010997600163ffffffff60601b03831b1991519009980197885280518251600160601b63ffffffff60c01b0319908103908111610a4b578951600160601b63ffffffff60c01b0319929083906002600160601b0363ffffffff60c01b03190991600160601b63ffffffff60c01b0319918290800908089751600160601b63ffffffff60c01b031989810391908211610a4b579151600160601b63ffffffff60c01b03199290918391080990519092600160601b63ffffffff60c01b0319919009600160601b63ffffffff60c01b03199290915008935b93929190565b634e487b7160e01b85526011600452602485fd5b939592509350945051155f14610a8357610a7a929350610d5d565b91939092610a45565b505081829183610a45565b634e487b7160e01b84526011600452602484fd5b634e487b7160e01b82526011600452602482fd5b508015610870565b91949592939095811580610ce9575b15610aee575050831580610ae6575b61084b5793929190565b508215610adc565b85919294951580610ce1575b610cd157610b06610677565b96600160601b63ffffffff60c01b031990810393908411610368576080880191600160601b63ffffffff60c01b031985818a8409088352600160601b63ffffffff60c01b031987810390811161036857600160601b63ffffffff60c01b0319908186850908808a5215610caa5750508651606090600160601b63ffffffff60c01b03199080096020890190808252600163ffffffff60601b03831b19908a5190099360408a01948552600163ffffffff60601b03831b19908251900997600163ffffffff60601b03831b19908551900996600163ffffffff60601b03831b1991519009970196875280518251600160601b63ffffffff60c01b0319908103908111610368578851600160601b63ffffffff60c01b0319929083906002600160601b0363ffffffff60c01b03190991600160601b63ffffffff60c01b0319918290800908089651600160601b63ffffffff60c01b031988810391908211610368579151600160601b63ffffffff60c01b03199290918391080990519091600160601b63ffffffff60c01b0319919009600160601b63ffffffff60c01b03199108929190565b95509550929550505051155f14610cc457610a7a91610d5d565b50505f5f905f925f610a45565b9550509150915091906001908190565b508515610afa565b508015610acd565b90919392841580610d55575b610d4a57610d0a90610534565b93600160601b63ffffffff60c01b031990859009600160601b63ffffffff60c01b0319919082908009900992600160601b63ffffffff60c01b0319910990565b50505090505f905f90565b508015610cfd565b9190821580610e8b575b610e7f57600160601b63ffffffff60c01b03198160020990600160601b63ffffffff60c01b031982800991600160601b63ffffffff60c01b03199083900990600160601b63ffffffff60c01b031983860994600160601b63ffffffff60c01b0319906003600160601b0363ffffffff60c01b0319908290819080096003090894600160601b63ffffffff60c01b031980826002600160601b0363ffffffff60c01b031909600160601b63ffffffff60c01b03198880090895600160601b63ffffffff60c01b03198781039190821161036857600160601b63ffffffff60c01b031985810390811161036857600160601b63ffffffff60c01b03199485910992600160601b63ffffffff60c01b03199283910890090892565b505f9150819081908190565b508015610d6756fe6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325514fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5a2646970667358221220a4f58cb3360e9427cfd6bd7d7ba7e37f1447c47e1b06f2ca6d1d420678eb6a2064736f6c634300081e0033
Deployed ByteCode
0x60c06040523461001a5761001236610054565b602081519101f35b5f80fd5b90601f8019910116810190811067ffffffffffffffff82111761004057604052565b634e487b7160e01b5f52604160045260245ffd5b60a081036100ef578060201161001a575f358160401161001a576020358260601161001a57604035908360801161001a576060359360a01161001a576080359260405193604085019585871067ffffffffffffffff881117610040576100c39660405285526020850152610108565b156100e95760015b60ff60405191166020820152602081526100e660408261001e565b90565b5f6100cb565b506040515f6020820152602081526100e660408261001e565b9291909283158015610275575b801561026d575b8015610256575b61024e5782519161013a602085019384519061028c565b15610245575f8091604051602081019160208352602060408301526020606083015260808201527fffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc63254f60a08201525f516020610eb45f395f51905f5260c082015260c081526101a960e08261001e565b519060055afa913d1561023d573d9267ffffffffffffffff841161004057604051936101df601f8201601f19166020018661001e565b84523d5f602086013e5b156102295760208380518101031261001a575f516020610eb45f395f51905f529384602061022495015191519181818909940991519061037c565b061490565b634e487b7160e01b5f52600160045260245ffd5b6060926101e9565b50505050505f90565b505050505f90565b505f516020610eb45f395f51905f52821015610123565b50811561011c565b505f516020610eb45f395f51905f52841015610115565b600160601b63ffffffff60c01b0319811080159061033f575b801561032e575b61032857600160601b63ffffffff60c01b0319907f5ac635d8aa3a93e7b3ebbd55769886bc651d06b0cc53b0f63bce3c3e27d2604b90829081816003600160601b0363ffffffff60c01b03190990600160601b63ffffffff60c01b0319908181800909080890600160601b63ffffffff60c01b03199080091490565b50505f90565b50801580156102ac575081156102ac565b50600160601b63ffffffff60c01b03198210156102a5565b600160ff1b8114610368575f190190565b634e487b7160e01b5f52601160045260245ffd5b90926080525f9060019384935f9281158061052a575b61051f576103a083826105f0565b95909460ff60a0525f5b5f60a05112156104f6575b808a036104c5575050505f516020610ed45f395f51905f52955f516020610e945f395f51905f52969593919492955b5f60a0511215610412575050505050505061040d600163ffffffff60601b0360601b1992610534565b900990565b6104239395979891929496986106b2565b80989398979291979188998192819a6104416080518960a05161065c565b61044c60a051610357565b60a052806104655750505050505b9593919492956103e4565b92955092959a5092506104a2959a50600181145f146104ac57505f516020610ed45f395f51905f52935f516020610e945f395f51905f5293610abe565b909792969161045a565b6002036104bc5785938993610abe565b87938793610abe565b600281036104df57505050829581969593919492956103e4565b9197916002190161045a575095508495849661045a565b506105066080518560a05161065c565b61051160a051610357565b60a05280156103aa576103b5565b505050505050505f90565b5060805115610392565b5f8091604051602081019160208352602060408301526020606083015260808201526002600160601b0363ffffffff60c01b031960a0820152600163ffffffff60601b0360601b1960c082015260c0815261059060e08261001e565b519060055afa3d156105e8573d9067ffffffffffffffff821161004057604051916105c5601f8201601f19166020018461001e565b82523d5f602084013e5b156102295760208180518101031261001a576020015190565b6060906105cf565b801580610654575b6106325761062e91610625915f516020610ed45f395f51905f525f516020610e945f395f51905f52610861565b92919091610cf1565b9091565b50505f516020610e945f395f51905f52905f516020610ed45f395f51905f5290565b5081156105f8565b91906002600192841c831b16921c1681018091116103685790565b6040519060a0820182811067ffffffffffffffff821117610040576040525f6080838281528260208201528260408201528260608201520152565b919390841580610859575b61084b576106c9610677565b92600160601b63ffffffff60c01b031982600209808552600160601b63ffffffff60c01b03199080096020850181815285519091600160601b63ffffffff60c01b0319910991604086019283526080600163ffffffff60601b0360601b19835183096060880190815291600160601b63ffffffff60c01b03199081808c80096003600160601b0363ffffffff60c01b03190990600160601b63ffffffff60c01b0319908190800960030908960186815281519096600160601b63ffffffff60c01b03199182906002600160601b0363ffffffff60c01b03190990600160601b63ffffffff60c01b0319908009089551905192600160601b63ffffffff60c01b031987810393908411610368578151600160601b63ffffffff60c01b03199081039a908b11610368579051600160601b63ffffffff60c01b031991900990519097600160601b63ffffffff60c01b031991099597600160601b63ffffffff60c01b03199485910992600160601b63ffffffff60c01b031992839108900908929190565b505f93508392508291508190565b5083156106bd565b91939290935f91811580610ab6575b1561089057505080610886575091906001908190565b9250508180918190565b909391505f61089d610677565b95600160601b63ffffffff60c01b031990810392908311610aa2576080870195600160601b63ffffffff60c01b0319848160018509088752600160601b63ffffffff60c01b0319868103908111610a8e57600160601b63ffffffff60c01b03199081600184090880895215610a5f5750508551600160601b63ffffffff60c01b0319908009602087018181528751909691600160601b63ffffffff60c01b031991900990604088019182526060600163ffffffff60601b03811b19885160010997600163ffffffff60601b03821b19845160010997600163ffffffff60601b03831b1991519009980197885280518251600160601b63ffffffff60c01b0319908103908111610a4b578951600160601b63ffffffff60c01b0319929083906002600160601b0363ffffffff60c01b03190991600160601b63ffffffff60c01b0319918290800908089751600160601b63ffffffff60c01b031989810391908211610a4b579151600160601b63ffffffff60c01b03199290918391080990519092600160601b63ffffffff60c01b0319919009600160601b63ffffffff60c01b03199290915008935b93929190565b634e487b7160e01b85526011600452602485fd5b939592509350945051155f14610a8357610a7a929350610d5d565b91939092610a45565b505081829183610a45565b634e487b7160e01b84526011600452602484fd5b634e487b7160e01b82526011600452602482fd5b508015610870565b91949592939095811580610ce9575b15610aee575050831580610ae6575b61084b5793929190565b508215610adc565b85919294951580610ce1575b610cd157610b06610677565b96600160601b63ffffffff60c01b031990810393908411610368576080880191600160601b63ffffffff60c01b031985818a8409088352600160601b63ffffffff60c01b031987810390811161036857600160601b63ffffffff60c01b0319908186850908808a5215610caa5750508651606090600160601b63ffffffff60c01b03199080096020890190808252600163ffffffff60601b03831b19908a5190099360408a01948552600163ffffffff60601b03831b19908251900997600163ffffffff60601b03831b19908551900996600163ffffffff60601b03831b1991519009970196875280518251600160601b63ffffffff60c01b0319908103908111610368578851600160601b63ffffffff60c01b0319929083906002600160601b0363ffffffff60c01b03190991600160601b63ffffffff60c01b0319918290800908089651600160601b63ffffffff60c01b031988810391908211610368579151600160601b63ffffffff60c01b03199290918391080990519091600160601b63ffffffff60c01b0319919009600160601b63ffffffff60c01b03199108929190565b95509550929550505051155f14610cc457610a7a91610d5d565b50505f5f905f925f610a45565b9550509150915091906001908190565b508515610afa565b508015610acd565b90919392841580610d55575b610d4a57610d0a90610534565b93600160601b63ffffffff60c01b031990859009600160601b63ffffffff60c01b0319919082908009900992600160601b63ffffffff60c01b0319910990565b50505090505f905f90565b508015610cfd565b9190821580610e8b575b610e7f57600160601b63ffffffff60c01b03198160020990600160601b63ffffffff60c01b031982800991600160601b63ffffffff60c01b03199083900990600160601b63ffffffff60c01b031983860994600160601b63ffffffff60c01b0319906003600160601b0363ffffffff60c01b0319908290819080096003090894600160601b63ffffffff60c01b031980826002600160601b0363ffffffff60c01b031909600160601b63ffffffff60c01b03198880090895600160601b63ffffffff60c01b03198781039190821161036857600160601b63ffffffff60c01b031985810390811161036857600160601b63ffffffff60c01b03199485910992600160601b63ffffffff60c01b03199283910890090892565b505f9150819081908190565b508015610d6756fe6b17d1f2e12c4247f8bce6e563a440f277037d812deb33a0f4a13945d898c296ffffffff00000000ffffffffffffffffbce6faada7179e84f3b9cac2fc6325514fe342e2fe1a7f9b8ee7eb4a7c0f9e162bce33576b315ececbb6406837bf51f5a2646970667358221220a4f58cb3360e9427cfd6bd7d7ba7e37f1447c47e1b06f2ca6d1d420678eb6a2064736f6c634300081e0033
External libraries
LibForcedInclusion : 0xd1a27F331c17eD8Cbb6DAbce67A42d6b8a6B0e14
LibInboxSetup : 0xf88Ef5437749A225621101BE8C1BE1A0cE967758