S Price: $0.415766 (+0.94%)

Contract

0x57F060A4FCbdC366fDfc52Caf2758C8F96252282

Overview

S Balance

Sonic LogoSonic LogoSonic Logo0 S

S Value

$0.00

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To

There are no matching entries

Please try again later

Parent Transaction Hash Block From To
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
MuonClient

Compiler Version
v0.8.20+commit.a1b79de6

Optimization Enabled:
Yes with 200 runs

Other Settings:
paris EvmVersion
File 1 of 3 : MuonClient.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "./MuonClientBase.sol";

contract MuonClient is MuonClientBase {
    constructor(uint256 _muonAppId, PublicKey memory _muonPublicKey) {
        validatePubKey(_muonPublicKey.x);

        muonAppId = _muonAppId;
        muonPublicKey = _muonPublicKey;
    }
}

File 2 of 3 : MuonClientBase.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;

import "./utils/SchnorrSECP256K1Verifier.sol";

contract MuonClientBase is SchnorrSECP256K1Verifier {
    struct SchnorrSign {
        uint256 signature;
        address owner;
        address nonce;
    }

    struct PublicKey {
        uint256 x;
        uint8 parity;
    }

    event MuonTX(bytes reqId, PublicKey pubKey);

    uint256 public muonAppId;
    PublicKey public muonPublicKey;

    function muonVerify(
        bytes calldata reqId,
        uint256 hash,
        SchnorrSign memory signature,
        PublicKey memory pubKey
    ) public returns (bool) {
        if (
            !verifySignature(
                pubKey.x,
                pubKey.parity,
                signature.signature,
                hash,
                signature.nonce
            )
        ) {
            return false;
        }
        emit MuonTX(reqId, pubKey);
        return true;
    }
}

File 3 of 3 : SchnorrSECP256K1Verifier.sol
// SPDX-License-Identifier: MIT

pragma solidity  >=0.7.0 <0.9.0;

contract SchnorrSECP256K1Verifier {
  // See https://en.bitcoin.it/wiki/Secp256k1 for this constant.
  uint256 constant public Q = // Group order of secp256k1
    // solium-disable-next-line indentation
    0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141;
  // solium-disable-next-line zeppelin/no-arithmetic-operations
  uint256 constant public HALF_Q = (Q >> 1) + 1;

  /** **************************************************************************
      @notice verifySignature returns true iff passed a valid Schnorr signature.

      @dev See https://en.wikipedia.org/wiki/Schnorr_signature for reference.

      @dev In what follows, let d be your secret key, PK be your public key,
      PKx be the x ordinate of your public key, and PKyp be the parity bit for
      the y ordinate (i.e., 0 if PKy is even, 1 if odd.)
      **************************************************************************
      @dev TO CREATE A VALID SIGNATURE FOR THIS METHOD

      @dev First PKx must be less than HALF_Q. Then follow these instructions
           (see evm/test/schnorr_test.js, for an example of carrying them out):
      @dev 1. Hash the target message to a uint256, called msgHash here, using
              keccak256

      @dev 2. Pick k uniformly and cryptographically securely randomly from
              {0,...,Q-1}. It is critical that k remains confidential, as your
              private key can be reconstructed from k and the signature.

      @dev 3. Compute k*g in the secp256k1 group, where g is the group
              generator. (This is the same as computing the public key from the
              secret key k. But it's OK if k*g's x ordinate is greater than
              HALF_Q.)

      @dev 4. Compute the ethereum address for k*g. This is the lower 160 bits
              of the keccak hash of the concatenated affine coordinates of k*g,
              as 32-byte big-endians. (For instance, you could pass k to
              ethereumjs-utils's privateToAddress to compute this, though that
              should be strictly a development convenience, not for handling
              live secrets, unless you've locked your javascript environment
              down very carefully.) Call this address
              nonceTimesGeneratorAddress.

      @dev 5. Compute e=uint256(keccak256(PKx as a 32-byte big-endian
                                        ‖ PKyp as a single byte
                                        ‖ msgHash
                                        ‖ nonceTimesGeneratorAddress))
              This value e is called "msgChallenge" in verifySignature's source
              code below. Here "‖" means concatenation of the listed byte
              arrays.

      @dev 6. Let x be your secret key. Compute s = (k - d * e) % Q. Add Q to
              it, if it's negative. This is your signature. (d is your secret
              key.)
      **************************************************************************
      @dev TO VERIFY A SIGNATURE

      @dev Given a signature (s, e) of msgHash, constructed as above, compute
      S=e*PK+s*generator in the secp256k1 group law, and then the ethereum
      address of S, as described in step 4. Call that
      nonceTimesGeneratorAddress. Then call the verifySignature method as:

      @dev    verifySignature(PKx, PKyp, s, msgHash,
                              nonceTimesGeneratorAddress)
      **************************************************************************
      @dev This signging scheme deviates slightly from the classical Schnorr
      signature, in that the address of k*g is used in place of k*g itself,
      both when calculating e and when verifying sum S as described in the
      verification paragraph above. This reduces the difficulty of
      brute-forcing a signature by trying random secp256k1 points in place of
      k*g in the signature verification process from 256 bits to 160 bits.
      However, the difficulty of cracking the public key using "baby-step,
      giant-step" is only 128 bits, so this weakening constitutes no compromise
      in the security of the signatures or the key.

      @dev The constraint signingPubKeyX < HALF_Q comes from Eq. (281), p. 24
      of Yellow Paper version 78d7b9a. ecrecover only accepts "s" inputs less
      than HALF_Q, to protect against a signature- malleability vulnerability in
      ECDSA. Schnorr does not have this vulnerability, but we must account for
      ecrecover's defense anyway. And since we are abusing ecrecover by putting
      signingPubKeyX in ecrecover's "s" argument the constraint applies to
      signingPubKeyX, even though it represents a value in the base field, and
      has no natural relationship to the order of the curve's cyclic group.
      **************************************************************************
      @param signingPubKeyX is the x ordinate of the public key. This must be
             less than HALF_Q.
      @param pubKeyYParity is 0 if the y ordinate of the public key is even, 1
             if it's odd.
      @param signature is the actual signature, described as s in the above
             instructions.
      @param msgHash is a 256-bit hash of the message being signed.
      @param nonceTimesGeneratorAddress is the ethereum address of k*g in the
             above instructions
      **************************************************************************
      @return True if passed a valid signature, false otherwise. */
  function verifySignature(
    uint256 signingPubKeyX,
    uint8 pubKeyYParity,
    uint256 signature,
    uint256 msgHash,
    address nonceTimesGeneratorAddress) public pure returns (bool) {
    require(signingPubKeyX < HALF_Q, "Public-key x >= HALF_Q");
    // Avoid signature malleability from multiple representations for ℤ/Qℤ elts
    require(signature < Q, "signature must be reduced modulo Q");

    // Forbid trivial inputs, to avoid ecrecover edge cases. The main thing to
    // avoid is something which causes ecrecover to return 0x0: then trivial
    // signatures could be constructed with the nonceTimesGeneratorAddress input
    // set to 0x0.
    //
    // solium-disable-next-line indentation
    require(nonceTimesGeneratorAddress != address(0) && signingPubKeyX > 0 &&
      signature > 0 && msgHash > 0, "no zero inputs allowed");

    // solium-disable-next-line indentation
    uint256 msgChallenge = // "e"
      // solium-disable-next-line indentation
      uint256(keccak256(abi.encodePacked(signingPubKeyX, pubKeyYParity,
        msgHash, nonceTimesGeneratorAddress))
    );

    // Verify msgChallenge * signingPubKey + signature * generator ==
    //        nonce * generator
    //
    // https://ethresear.ch/t/you-can-kinda-abuse-ecrecover-to-do-ecmul-in-secp256k1-today/2384/9
    // The point corresponding to the address returned by
    // ecrecover(-s*r,v,r,e*r) is (r⁻¹ mod Q)*(e*r*R-(-s)*r*g)=e*R+s*g, where R
    // is the (v,r) point. See https://crypto.stackexchange.com/a/18106
    //
    // solium-disable-next-line indentation
    address recoveredAddress = ecrecover(
      // solium-disable-next-line zeppelin/no-arithmetic-operations
      bytes32(Q - mulmod(signingPubKeyX, signature, Q)),
      // https://ethereum.github.io/yellowpaper/paper.pdf p. 24, "The
      // value 27 represents an even y value and 28 represents an odd
      // y value."
      (pubKeyYParity == 0) ? 27 : 28,
      bytes32(signingPubKeyX),
      bytes32(mulmod(msgChallenge, signingPubKeyX, Q)));
    return nonceTimesGeneratorAddress == recoveredAddress;
  }

  function validatePubKey (uint256 signingPubKeyX) public pure {
    require(signingPubKeyX < HALF_Q, "Public-key x >= HALF_Q");
  }
}

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 200
  },
  "evmVersion": "paris",
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "metadata": {
    "useLiteralContent": true
  },
  "libraries": {}
}

Contract Security Audit

Contract ABI

[{"inputs":[{"internalType":"uint256","name":"_muonAppId","type":"uint256"},{"components":[{"internalType":"uint256","name":"x","type":"uint256"},{"internalType":"uint8","name":"parity","type":"uint8"}],"internalType":"struct MuonClientBase.PublicKey","name":"_muonPublicKey","type":"tuple"}],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes","name":"reqId","type":"bytes"},{"components":[{"internalType":"uint256","name":"x","type":"uint256"},{"internalType":"uint8","name":"parity","type":"uint8"}],"indexed":false,"internalType":"struct MuonClientBase.PublicKey","name":"pubKey","type":"tuple"}],"name":"MuonTX","type":"event"},{"inputs":[],"name":"HALF_Q","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"Q","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"muonAppId","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"muonPublicKey","outputs":[{"internalType":"uint256","name":"x","type":"uint256"},{"internalType":"uint8","name":"parity","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"reqId","type":"bytes"},{"internalType":"uint256","name":"hash","type":"uint256"},{"components":[{"internalType":"uint256","name":"signature","type":"uint256"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"address","name":"nonce","type":"address"}],"internalType":"struct MuonClientBase.SchnorrSign","name":"signature","type":"tuple"},{"components":[{"internalType":"uint256","name":"x","type":"uint256"},{"internalType":"uint8","name":"parity","type":"uint8"}],"internalType":"struct MuonClientBase.PublicKey","name":"pubKey","type":"tuple"}],"name":"muonVerify","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"signingPubKeyX","type":"uint256"}],"name":"validatePubKey","outputs":[],"stateMutability":"pure","type":"function"},{"inputs":[{"internalType":"uint256","name":"signingPubKeyX","type":"uint256"},{"internalType":"uint8","name":"pubKeyYParity","type":"uint8"},{"internalType":"uint256","name":"signature","type":"uint256"},{"internalType":"uint256","name":"msgHash","type":"uint256"},{"internalType":"address","name":"nonceTimesGeneratorAddress","type":"address"}],"name":"verifySignature","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"pure","type":"function"}]

608060405234801561001057600080fd5b506040516108fd3803806108fd83398101604081905261002f916100d7565b805161003a90610061565b6000919091558051600155602001516002805460ff191660ff909216919091179055610187565b6100826fa2a8918ca85bafe22016d0b997e4df60600160ff1b036001610160565b81106100d45760405162461bcd60e51b815260206004820152601660248201527f5075626c69632d6b65792078203e3d2048414c465f5100000000000000000000604482015260640160405180910390fd5b50565b60008082840360608112156100eb57600080fd5b835192506040601f198201121561010157600080fd5b50604080519081016001600160401b038111828210171561013257634e487b7160e01b600052604160045260246000fd5b60409081526020850151825284015160ff8116811461015057600080fd5b6020820152919491935090915050565b8082018082111561018157634e487b7160e01b600052601160045260246000fd5b92915050565b610767806101966000396000f3fe608060405234801561001057600080fd5b506004361061007d5760003560e01c8063af663e9b1161005b578063af663e9b146100d5578063b3f74d89146100fd578063e493ef8c14610106578063ff51dff21461011f57600080fd5b80637669c2bb146100825780638224604a146100aa5780638efb3bb2146100bf575b600080fd5b610095610090366004610577565b610132565b60405190151581526020015b60405180910390f35b6100bd6100b836600461064b565b6101a5565b005b6100c7610215565b6040519081526020016100a1565b6001546002546100e6919060ff1682565b6040805192835260ff9091166020830152016100a1565b6100c760005481565b6100c770014551231950b75fc4402da1732fc9bebe1981565b61009561012d366004610664565b610239565b6000610151826000015183602001518560000151878760400151610239565b61015d5750600061019c565b7f77e158c4de5b89cd65592962239c3cc6136696032ecc462ad1b04af14e8df53b868684604051610190939291906106a8565b60405180910390a15060015b95945050505050565b6101c66fa2a8918ca85bafe22016d0b997e4df60600160ff1b036001610705565b81106102125760405162461bcd60e51b81526020600482015260166024820152755075626c69632d6b65792078203e3d2048414c465f5160501b60448201526064015b60405180910390fd5b50565b6102366fa2a8918ca85bafe22016d0b997e4df60600160ff1b036001610705565b81565b600061025c6fa2a8918ca85bafe22016d0b997e4df60600160ff1b036001610705565b86106102a35760405162461bcd60e51b81526020600482015260166024820152755075626c69632d6b65792078203e3d2048414c465f5160501b6044820152606401610209565b70014551231950b75fc4402da1732fc9bebe19841061030f5760405162461bcd60e51b815260206004820152602260248201527f7369676e6174757265206d7573742062652072656475636564206d6f64756c6f604482015261205160f01b6064820152608401610209565b6001600160a01b038216158015906103275750600086115b80156103335750600084115b801561033f5750600083115b6103845760405162461bcd60e51b81526020600482015260166024820152751b9bc81e995c9bc81a5b9c1d5d1cc8185b1b1bddd95960521b6044820152606401610209565b60408051602080820189905260f888901b6001600160f81b0319168284015260418201869052606085901b6bffffffffffffffffffffffff1916606183015282516055818403018152607590920190925280519101206000600170014551231950b75fc4402da1732fc9bebe19878a096104109070014551231950b75fc4402da1732fc9bebe1961071e565b60ff89161561042057601c610423565b601b5b8a70014551231950b75fc4402da1732fc9bebe198c87096040805160008152602081018083529590955260ff909316928401929092526060830152608082015260a0016020604051602081039080840390855afa158015610488573d6000803e3d6000fd5b5050604051601f1901516001600160a01b03868116911614935050505095945050505050565b6040516060810167ffffffffffffffff811182821017156104df57634e487b7160e01b600052604160045260246000fd5b60405290565b80356001600160a01b03811681146104fc57600080fd5b919050565b803560ff811681146104fc57600080fd5b60006040828403121561052457600080fd5b6040516040810181811067ffffffffffffffff8211171561055557634e487b7160e01b600052604160045260246000fd5b6040528235815290508061056b60208401610501565b60208201525092915050565b600080600080600085870360e081121561059057600080fd5b863567ffffffffffffffff808211156105a857600080fd5b818901915089601f8301126105bc57600080fd5b8135818111156105cb57600080fd5b8a60208285010111156105dd57600080fd5b6020928301985096505087013593506060603f19820112156105fe57600080fd5b506106076104ae565b6040870135815261061a606088016104e5565b602082015261062b608088016104e5565b6040820152915061063f8760a08801610512565b90509295509295909350565b60006020828403121561065d57600080fd5b5035919050565b600080600080600060a0868803121561067c57600080fd5b8535945061068c60208701610501565b9350604086013592506060860135915061063f608087016104e5565b606081528260608201528284608083013760006080848301015260006080601f19601f86011683010190508251602083015260ff6020840151166040830152949350505050565b634e487b7160e01b600052601160045260246000fd5b80820180821115610718576107186106ef565b92915050565b81810381811115610718576107186106ef56fea264697066735822122063c0cff8cbe6bc97011a68cf4fd67f3764a4bee9c3fa958bbbb42f9ba93eff6364736f6c63430008140033df1914d3e7dc5d2e08fc0481d84e7d8f736efaf5112bbb2b110b6303f17f4ffe25ee4bc28f38b61b1a0036dc08084300c0b8a423c4da17911a2ba4d9e845c2e50000000000000000000000000000000000000000000000000000000000000001

Deployed Bytecode

0x608060405234801561001057600080fd5b506004361061007d5760003560e01c8063af663e9b1161005b578063af663e9b146100d5578063b3f74d89146100fd578063e493ef8c14610106578063ff51dff21461011f57600080fd5b80637669c2bb146100825780638224604a146100aa5780638efb3bb2146100bf575b600080fd5b610095610090366004610577565b610132565b60405190151581526020015b60405180910390f35b6100bd6100b836600461064b565b6101a5565b005b6100c7610215565b6040519081526020016100a1565b6001546002546100e6919060ff1682565b6040805192835260ff9091166020830152016100a1565b6100c760005481565b6100c770014551231950b75fc4402da1732fc9bebe1981565b61009561012d366004610664565b610239565b6000610151826000015183602001518560000151878760400151610239565b61015d5750600061019c565b7f77e158c4de5b89cd65592962239c3cc6136696032ecc462ad1b04af14e8df53b868684604051610190939291906106a8565b60405180910390a15060015b95945050505050565b6101c66fa2a8918ca85bafe22016d0b997e4df60600160ff1b036001610705565b81106102125760405162461bcd60e51b81526020600482015260166024820152755075626c69632d6b65792078203e3d2048414c465f5160501b60448201526064015b60405180910390fd5b50565b6102366fa2a8918ca85bafe22016d0b997e4df60600160ff1b036001610705565b81565b600061025c6fa2a8918ca85bafe22016d0b997e4df60600160ff1b036001610705565b86106102a35760405162461bcd60e51b81526020600482015260166024820152755075626c69632d6b65792078203e3d2048414c465f5160501b6044820152606401610209565b70014551231950b75fc4402da1732fc9bebe19841061030f5760405162461bcd60e51b815260206004820152602260248201527f7369676e6174757265206d7573742062652072656475636564206d6f64756c6f604482015261205160f01b6064820152608401610209565b6001600160a01b038216158015906103275750600086115b80156103335750600084115b801561033f5750600083115b6103845760405162461bcd60e51b81526020600482015260166024820152751b9bc81e995c9bc81a5b9c1d5d1cc8185b1b1bddd95960521b6044820152606401610209565b60408051602080820189905260f888901b6001600160f81b0319168284015260418201869052606085901b6bffffffffffffffffffffffff1916606183015282516055818403018152607590920190925280519101206000600170014551231950b75fc4402da1732fc9bebe19878a096104109070014551231950b75fc4402da1732fc9bebe1961071e565b60ff89161561042057601c610423565b601b5b8a70014551231950b75fc4402da1732fc9bebe198c87096040805160008152602081018083529590955260ff909316928401929092526060830152608082015260a0016020604051602081039080840390855afa158015610488573d6000803e3d6000fd5b5050604051601f1901516001600160a01b03868116911614935050505095945050505050565b6040516060810167ffffffffffffffff811182821017156104df57634e487b7160e01b600052604160045260246000fd5b60405290565b80356001600160a01b03811681146104fc57600080fd5b919050565b803560ff811681146104fc57600080fd5b60006040828403121561052457600080fd5b6040516040810181811067ffffffffffffffff8211171561055557634e487b7160e01b600052604160045260246000fd5b6040528235815290508061056b60208401610501565b60208201525092915050565b600080600080600085870360e081121561059057600080fd5b863567ffffffffffffffff808211156105a857600080fd5b818901915089601f8301126105bc57600080fd5b8135818111156105cb57600080fd5b8a60208285010111156105dd57600080fd5b6020928301985096505087013593506060603f19820112156105fe57600080fd5b506106076104ae565b6040870135815261061a606088016104e5565b602082015261062b608088016104e5565b6040820152915061063f8760a08801610512565b90509295509295909350565b60006020828403121561065d57600080fd5b5035919050565b600080600080600060a0868803121561067c57600080fd5b8535945061068c60208701610501565b9350604086013592506060860135915061063f608087016104e5565b606081528260608201528284608083013760006080848301015260006080601f19601f86011683010190508251602083015260ff6020840151166040830152949350505050565b634e487b7160e01b600052601160045260246000fd5b80820180821115610718576107186106ef565b92915050565b81810381811115610718576107186106ef56fea264697066735822122063c0cff8cbe6bc97011a68cf4fd67f3764a4bee9c3fa958bbbb42f9ba93eff6364736f6c63430008140033

Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)

df1914d3e7dc5d2e08fc0481d84e7d8f736efaf5112bbb2b110b6303f17f4ffe25ee4bc28f38b61b1a0036dc08084300c0b8a423c4da17911a2ba4d9e845c2e50000000000000000000000000000000000000000000000000000000000000001

-----Decoded View---------------
Arg [0] : _muonAppId (uint256): 100910080158581338655846085823554014103388703502741867366803429671510325809150
Arg [1] : _muonPublicKey (tuple): System.Collections.Generic.List`1[Nethereum.ABI.FunctionEncoding.ParameterOutput]

-----Encoded View---------------
3 Constructor Arguments found :
Arg [0] : df1914d3e7dc5d2e08fc0481d84e7d8f736efaf5112bbb2b110b6303f17f4ffe
Arg [1] : 25ee4bc28f38b61b1a0036dc08084300c0b8a423c4da17911a2ba4d9e845c2e5
Arg [2] : 0000000000000000000000000000000000000000000000000000000000000001


Block Transaction Gas Used Reward
view all blocks produced

Block Uncle Number Difficulty Gas Used Reward
View All Uncles
Loading...
Loading
Loading...
Loading

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits

A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.