false
true
0

Contract Address Details

0xb04C1e546d7Cf8dc39E10dFC1714847573790806

Contract Name
SRA
Creator
0xfcafcc–9963aa at 0xbe872c–caf108
Balance
0 tPLS
Tokens
Fetching tokens...
Transactions
Fetching transactions...
Transfers
Fetching transfers...
Gas Used
Fetching gas used...
Last Balance Update
25348463
Warning! Contract bytecode has been changed and doesn't match the verified one. Therefore, interaction with this smart contract may be risky.
Contract name:
SRA




Optimization enabled
false
Compiler version
v0.8.28+commit.7893614a




EVM Version




Verified at
2026-08-20T06:38:31.029535Z

Constructor Arguments


              

contracts/lib/SRA.sol

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.28;

/// @title SRA — commutative-encryption verification primitives
/// @notice On-chain half of the SRA mental-poker protocol (SPEC §2). All
///         deck values are 1024-bit big-endian byte strings (quadratic
///         residues mod P); all exponent checks run forward through the
///         MODEXP precompile. Mirrors web/js/sra.mjs.
library SRA {
    /// RFC 2409 Oakley Group 2 prime (1024-bit safe prime), big-endian words.
    uint256 internal constant P0 = 0xFFFFFFFFFFFFFFFFC90FDAA22168C234C4C6628B80DC1CD129024E088A67CC74;
    uint256 internal constant P1 = 0x020BBEA63B139B22514A08798E3404DDEF9519B3CD3A431B302B0A6DF25F1437;
    uint256 internal constant P2 = 0x4FE1356D6D51C245E485B576625E7EC6F44C42E9A637ED6B0BFF5CB6F406B7ED;
    uint256 internal constant P3 = 0xEE386BFB5A899FA5AE9F24117C4B1FE649286651ECE65381FFFFFFFFFFFFFFFF;

    uint256 internal constant VALUE_BYTES = 128;
    uint256 internal constant DECK = 52;

    /// @dev P as a 128-byte string (for the precompile modulus field).
    function pBytes() internal pure returns (bytes memory out) {
        out = new bytes(128);
        assembly ("memory-safe") {
            mstore(add(out, 32), P0)
            mstore(add(out, 64), P1)
            mstore(add(out, 96), P2)
            mstore(add(out, 128), P3)
        }
    }

    /// @notice base^exp mod P with a 32-byte exponent; returns 128-byte result.
    function modexp32(bytes memory base128, uint256 exp) public view returns (bytes memory) {
        return _modexp(base128, abi.encodePacked(exp));
    }

    /// @notice base^(e1*e2) mod P (512-bit exponent product of two scalars).
    function modexpMul(bytes memory base128, uint256 e1, uint256 e2)
        public view returns (bytes memory)
    {
        (uint256 hi, uint256 lo) = mul512(e1, e2);
        return _modexp(base128, abi.encodePacked(hi, lo));
    }

    /// @dev Full 512-bit product of two uint256.
    function mul512(uint256 a, uint256 b) internal pure returns (uint256 hi, uint256 lo) {
        unchecked {
            lo = a * b;
            uint256 mm = mulmod(a, b, type(uint256).max);
            hi = mm - lo;
            if (mm < lo) hi--;
        }
    }

    /// @dev MODEXP precompile call; base must be 128 bytes; mod = P.
    function _modexp(bytes memory base128, bytes memory exp)
        private view returns (bytes memory result)
    {
        require(base128.length == 128, "base len");
        bytes memory input = abi.encodePacked(
            uint256(128), uint256(exp.length), uint256(128), base128, exp, pBytes()
        );
        result = new bytes(128);
        bool ok;
        assembly ("memory-safe") {
            ok := staticcall(gas(), 0x05, add(input, 32), mload(input), add(result, 32), 128)
        }
        require(ok, "modexp failed");
    }

    /// @notice keccak of base^exp mod P — cheap equality comparisons.
    function modexpHash32(bytes memory base128, uint256 exp) public view returns (bytes32) {
        return keccak256(modexp32(base128, exp));
    }

    /// @notice base^exp mod P with an arbitrary-length exponent (used for
    ///         1024-bit inverse exponents in dispute round-trips).
    function modexpBytes(bytes memory base128, bytes memory exp) public view returns (bytes memory) {
        return _modexp(base128, exp);
    }

    /// @notice Deterministic card code for k in [0,52): full-size QR mod P.
    /// @dev h = BE(keccak(TAG‖k‖0)‖…‖keccak(TAG‖k‖3)); code = h^2 mod P.
    ///      Mirrors sra.mjs cardCode().
    function cardCode(uint8 k) public view returns (bytes memory) {
        require(k < DECK, "bad card");
        bytes memory h = new bytes(128);
        bytes memory tag = "PLSHOLDEM_CARD_V1";
        for (uint8 ctr = 0; ctr < 4; ctr++) {
            bytes32 part = keccak256(abi.encodePacked(tag, k, ctr));
            assembly ("memory-safe") {
                mstore(add(add(h, 32), mul(ctr, 32)), part)
            }
        }
        return _modexp(h, hex"02");
    }

    /// @notice keccak of cardCode(k).
    function cardCodeHash(uint8 k) internal view returns (bytes32) {
        return keccak256(cardCode(k));
    }

    /// @notice Find the card index whose code hashes to `h`; 255 if none.
    function cardFromHash(bytes32 h) public view returns (uint8) {
        for (uint8 k = 0; k < DECK; k++) {
            if (cardCodeHash(k) == h) return k;
        }
        return 255;
    }

    /// @notice Extract 128-byte value i from a packed 52-value deck blob.
    function deckValue(bytes calldata deck, uint256 i) internal pure returns (bytes memory v) {
        v = deck[i * VALUE_BYTES:(i + 1) * VALUE_BYTES];
    }

    /// @notice Validate a posted deck stage: exactly 52 values, each in
    ///         (1, P-1), all distinct. Reverts otherwise.
    function checkDeck(bytes calldata deck) public pure {
        require(deck.length == DECK * VALUE_BYTES, "deck len");
        bytes32[DECK] memory hashes;
        for (uint256 i = 0; i < DECK; i++) {
            uint256 off = i * VALUE_BYTES;
            uint256 w0;
            uint256 w1;
            uint256 w2;
            uint256 w3;
            assembly ("memory-safe") {
                w0 := calldataload(add(deck.offset, off))
                w1 := calldataload(add(deck.offset, add(off, 32)))
                w2 := calldataload(add(deck.offset, add(off, 64)))
                w3 := calldataload(add(deck.offset, add(off, 96)))
            }
            require(inRange(w0, w1, w2, w3), "value range");
            bytes32 h = keccak256(abi.encodePacked(w0, w1, w2, w3));
            for (uint256 j = 0; j < i; j++) {
                require(hashes[j] != h, "duplicate value");
            }
            hashes[i] = h;
        }
    }

    /// @dev true iff 1 < v < P-1 for v given as 4 big-endian words.
    function inRange(uint256 w0, uint256 w1, uint256 w2, uint256 w3) internal pure returns (bool) {
        // v > 1
        if (w0 == 0 && w1 == 0 && w2 == 0 && w3 <= 1) return false;
        // v < P - 1  (P3 ends in ...FFFF, so P-1 differs only in last word)
        if (w0 < P0) return true;
        if (w0 > P0) return false;
        if (w1 < P1) return true;
        if (w1 > P1) return false;
        if (w2 < P2) return true;
        if (w2 > P2) return false;
        return w3 < P3 - 1;
    }

    /// @notice Range-check a 128-byte memory value (used for proven values).
    function inRangeMem(bytes memory v) internal pure returns (bool) {
        require(v.length == 128, "len");
        uint256 w0;
        uint256 w1;
        uint256 w2;
        uint256 w3;
        assembly ("memory-safe") {
            w0 := mload(add(v, 32))
            w1 := mload(add(v, 64))
            w2 := mload(add(v, 96))
            w3 := mload(add(v, 128))
        }
        return inRange(w0, w1, w2, w3);
    }

    /// @dev Scalar exponent sanity: odd (invertible mod P-1) and nonzero.
    function validScalar(uint256 e) internal pure returns (bool) {
        return e & 1 == 1 && e > 1;
    }
}
        

Compiler Settings

{"viaIR":true,"outputSelection":{"*":{"*":["abi","evm.bytecode","evm.deployedBytecode","evm.methodIdentifiers","metadata"],"":["ast"]}},"optimizer":{"runs":1,"enabled":true},"libraries":{},"evmVersion":"paris"}
              

Contract ABI

[{"type":"function","stateMutability":"view","outputs":[{"type":"bytes","name":"","internalType":"bytes"}],"name":"cardCode","inputs":[{"type":"uint8","name":"k","internalType":"uint8"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint8","name":"","internalType":"uint8"}],"name":"cardFromHash","inputs":[{"type":"bytes32","name":"h","internalType":"bytes32"}]},{"type":"function","stateMutability":"pure","outputs":[],"name":"checkDeck","inputs":[{"type":"bytes","name":"deck","internalType":"bytes"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes","name":"","internalType":"bytes"}],"name":"modexp32","inputs":[{"type":"bytes","name":"base128","internalType":"bytes"},{"type":"uint256","name":"exp","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes","name":"","internalType":"bytes"}],"name":"modexpBytes","inputs":[{"type":"bytes","name":"base128","internalType":"bytes"},{"type":"bytes","name":"exp","internalType":"bytes"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes32","name":"","internalType":"bytes32"}],"name":"modexpHash32","inputs":[{"type":"bytes","name":"base128","internalType":"bytes"},{"type":"uint256","name":"exp","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"bytes","name":"","internalType":"bytes"}],"name":"modexpMul","inputs":[{"type":"bytes","name":"base128","internalType":"bytes"},{"type":"uint256","name":"e1","internalType":"uint256"},{"type":"uint256","name":"e2","internalType":"uint256"}]}]
              

Contract Creation Code

0x6080806040523460195761095f908161001f823930815050f35b600080fdfe608080604052600436101561001357600080fd5b60003560e01c9081626a007d146101cb575080633c8dfb44146101af57806340604be71461013557806349b11d3714610110578063631ec63f146100fb578063d325c5b1146100945763ee307cb41461006b57600080fd5b602036600319011261008f576020610084600435610600565b60ff60405191168152f35b600080fd5b604036600319011261008f576004356001600160401b03811161008f576100bf9036906004016103c7565b6024356001600160401b03811161008f576100f7916100e56100eb9236906004016103c7565b90610760565b60405191829182610471565b0390f35b6100f76100eb61010a3661041d565b906105e3565b602036600319011261008f5760043560ff8116810361008f576100eb6100f7916104c4565b606036600319011261008f576004356001600160401b03811161008f576100eb6101666100f79236906004016103c7565b60443560243581810292916000199109918080840393106101a4575b60405192602084015260408301526040825261019f60608361038e565b610760565b916000190191610182565b60206101bd61010a3661041d565b818151910120604051908152f35b602036600319011261008f57600435906001600160401b03821161008f573660238301121561008f5760048201356001600160401b03811161008f57366024828501011161008f57611a000361036157506040519061068061022d818461038e565b3683376000905b6034821061023e57005b8160071b8281046080148315171561034b578101602481013590604481013590608460648201359101359061027582828587610643565b15610318576040519260208401948552604084015260608301526080820152608081526102a360a08261038e565b5190209160005b8181106102c85750600191926102c0828661049d565b520190610234565b836102d3828761049d565b51146102e1576001016102aa565b60405162461bcd60e51b815260206004820152600f60248201526e6475706c69636174652076616c756560881b6044820152606490fd5b60405162461bcd60e51b815260206004820152600b60248201526a76616c75652072616e676560a81b6044820152606490fd5b634e487b7160e01b600052601160045260246000fd5b62461bcd60e51b81526020600482015260086024820152673232b1b5903632b760c11b6044820152606490fd5b601f909101601f19168101906001600160401b038211908210176103b157604052565b634e487b7160e01b600052604160045260246000fd5b81601f8201121561008f578035906001600160401b0382116103b157604051926103fb601f8401601f19166020018561038e565b8284526020838301011161008f57816000926020809301838601378301015290565b604060031982011261008f57600435906001600160401b03821161008f57610447916004016103c7565b9060243590565b60005b8381106104615750506000910152565b8181015183820152602001610451565b60409160208252610491815180928160208601526020868601910161044e565b601f01601f1916010190565b9060348110156104ae5760051b0190565b634e487b7160e01b600052603260045260246000fd5b90603460ff831610156105b3576040516104df60a08261038e565b60808082523660208301376040908151936104fa838661038e565b601185526020850170504c53484f4c44454d5f434152445f563160781b815260005b600460ff8216106105525750505061054f92935061053c8251928361038e565b60018252600160f91b6020830152610760565b90565b600160ff9188875161059f6002602083818101955161057281888d61044e565b81018960f81b8c60f81b16838201528960f81b8860f81b1660218201520301601d1981018452018261038e565b51902060208260051b88010152011661051c565b60405162461bcd60e51b81526020600482015260086024820152671898590818d85c9960c21b6044820152606490fd5b9061054f916040519160208301526020825261019f60408361038e565b60005b603460ff82161061061557505060ff90565b8161061f826104c4565b602081519101201461063e5760ff1660ff811461034b57600101610603565b905090565b801580610758575b80610750575b80610745575b61073c577736f0255dde973dcb3b399d747f23e32ed6fdb1f77598338b198110610733577736f0255dde973dcb3b399d747f23e32ed6fdb1f77598338b191061072b576000805160206108ea8339815191528110610723576000805160206108ea8339815191521061071c5760008051602061090a83398151915281106107155760008051602061090a8339815191521061070f57600277771c35fdad44cfd2d74f9208be258ff324943328f67329c160411b031190565b50600090565b5050600190565b5050600090565b505050600190565b505050600090565b50505050600190565b50505050600090565b506001841115610657565b508215610651565b50811561064b565b91909160808151036108b957608090835160a061085e60405193610784838661038e565b85855260208501601f19840195863683377736f0255dde973dcb3b399d747f23e32ed6fdb1f77598338b1982526000805160206108ea833981519152604082015260008051602061090a8339815191526060820152600177771c35fdad44cfd2d74f9208be258ff324943328f67329c160411b038882015261084f886040519b8c956020870199838b52604088015282606088015261082c815180926020868b01910161044e565b8601610841825180936020868501910161044e565b01019283925193849161044e565b0103601f19810188528761038e565b61086b604051918261038e565b838152602081019236843794519060055afa1561088457565b60405162461bcd60e51b815260206004820152600d60248201526c1b5bd9195e1c0819985a5b1959609a1b6044820152606490fd5b60405162461bcd60e51b81526020600482015260086024820152673130b9b2903632b760c11b6044820152606490fdfe020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7eda2646970667358221220fe4da8e805a981b6b28046ad1f5f57fddb372485082facd8fe6163e78b0cab1f64736f6c634300081c0033

Deployed ByteCode

0x608080604052600436101561001357600080fd5b60003560e01c9081626a007d146101cb575080633c8dfb44146101af57806340604be71461013557806349b11d3714610110578063631ec63f146100fb578063d325c5b1146100945763ee307cb41461006b57600080fd5b602036600319011261008f576020610084600435610600565b60ff60405191168152f35b600080fd5b604036600319011261008f576004356001600160401b03811161008f576100bf9036906004016103c7565b6024356001600160401b03811161008f576100f7916100e56100eb9236906004016103c7565b90610760565b60405191829182610471565b0390f35b6100f76100eb61010a3661041d565b906105e3565b602036600319011261008f5760043560ff8116810361008f576100eb6100f7916104c4565b606036600319011261008f576004356001600160401b03811161008f576100eb6101666100f79236906004016103c7565b60443560243581810292916000199109918080840393106101a4575b60405192602084015260408301526040825261019f60608361038e565b610760565b916000190191610182565b60206101bd61010a3661041d565b818151910120604051908152f35b602036600319011261008f57600435906001600160401b03821161008f573660238301121561008f5760048201356001600160401b03811161008f57366024828501011161008f57611a000361036157506040519061068061022d818461038e565b3683376000905b6034821061023e57005b8160071b8281046080148315171561034b578101602481013590604481013590608460648201359101359061027582828587610643565b15610318576040519260208401948552604084015260608301526080820152608081526102a360a08261038e565b5190209160005b8181106102c85750600191926102c0828661049d565b520190610234565b836102d3828761049d565b51146102e1576001016102aa565b60405162461bcd60e51b815260206004820152600f60248201526e6475706c69636174652076616c756560881b6044820152606490fd5b60405162461bcd60e51b815260206004820152600b60248201526a76616c75652072616e676560a81b6044820152606490fd5b634e487b7160e01b600052601160045260246000fd5b62461bcd60e51b81526020600482015260086024820152673232b1b5903632b760c11b6044820152606490fd5b601f909101601f19168101906001600160401b038211908210176103b157604052565b634e487b7160e01b600052604160045260246000fd5b81601f8201121561008f578035906001600160401b0382116103b157604051926103fb601f8401601f19166020018561038e565b8284526020838301011161008f57816000926020809301838601378301015290565b604060031982011261008f57600435906001600160401b03821161008f57610447916004016103c7565b9060243590565b60005b8381106104615750506000910152565b8181015183820152602001610451565b60409160208252610491815180928160208601526020868601910161044e565b601f01601f1916010190565b9060348110156104ae5760051b0190565b634e487b7160e01b600052603260045260246000fd5b90603460ff831610156105b3576040516104df60a08261038e565b60808082523660208301376040908151936104fa838661038e565b601185526020850170504c53484f4c44454d5f434152445f563160781b815260005b600460ff8216106105525750505061054f92935061053c8251928361038e565b60018252600160f91b6020830152610760565b90565b600160ff9188875161059f6002602083818101955161057281888d61044e565b81018960f81b8c60f81b16838201528960f81b8860f81b1660218201520301601d1981018452018261038e565b51902060208260051b88010152011661051c565b60405162461bcd60e51b81526020600482015260086024820152671898590818d85c9960c21b6044820152606490fd5b9061054f916040519160208301526020825261019f60408361038e565b60005b603460ff82161061061557505060ff90565b8161061f826104c4565b602081519101201461063e5760ff1660ff811461034b57600101610603565b905090565b801580610758575b80610750575b80610745575b61073c577736f0255dde973dcb3b399d747f23e32ed6fdb1f77598338b198110610733577736f0255dde973dcb3b399d747f23e32ed6fdb1f77598338b191061072b576000805160206108ea8339815191528110610723576000805160206108ea8339815191521061071c5760008051602061090a83398151915281106107155760008051602061090a8339815191521061070f57600277771c35fdad44cfd2d74f9208be258ff324943328f67329c160411b031190565b50600090565b5050600190565b5050600090565b505050600190565b505050600090565b50505050600190565b50505050600090565b506001841115610657565b508215610651565b50811561064b565b91909160808151036108b957608090835160a061085e60405193610784838661038e565b85855260208501601f19840195863683377736f0255dde973dcb3b399d747f23e32ed6fdb1f77598338b1982526000805160206108ea833981519152604082015260008051602061090a8339815191526060820152600177771c35fdad44cfd2d74f9208be258ff324943328f67329c160411b038882015261084f886040519b8c956020870199838b52604088015282606088015261082c815180926020868b01910161044e565b8601610841825180936020868501910161044e565b01019283925193849161044e565b0103601f19810188528761038e565b61086b604051918261038e565b838152602081019236843794519060055afa1561088457565b60405162461bcd60e51b815260206004820152600d60248201526c1b5bd9195e1c0819985a5b1959609a1b6044820152606490fd5b60405162461bcd60e51b81526020600482015260086024820152673130b9b2903632b760c11b6044820152606490fdfe020bbea63b139b22514a08798e3404ddef9519b3cd3a431b302b0a6df25f14374fe1356d6d51c245e485b576625e7ec6f44c42e9a637ed6b0bff5cb6f406b7eda2646970667358221220fe4da8e805a981b6b28046ad1f5f57fddb372485082facd8fe6163e78b0cab1f64736f6c634300081c0033