Messager

Description:

Proxy contract enabling upgradeable smart contract patterns. Delegates calls to an implementation contract.

Blockchain: Ethereum

Source Code: View Code On The Blockchain

Solidity Source Code:

{{
  "language": "Solidity",
  "sources": {
    "rainlink-contract-main/core/Messager.sol": {
      "content": "// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.20;

import {ECDSA} from "@openzeppelin/contracts@5.0.0/utils/cryptography/ECDSA.sol";
import {Address} from "@openzeppelin/contracts@5.0.0/utils/Address.sol";
import {Types} from "../comn/Types.sol";
import {IMessager} from "../comn/IMessager.sol";
import {IValidator} from "../comn/IValidator.sol";
import {ComFunUtil} from "../comn/ComFunUtil.sol";
import {Comn} from "./Comn.sol";

/**
 * @title Messager
 * @dev This contract inherits from both Comn and IMessager. It is designed to handle messaging - related operations in the context of a cross - chain or decentralized system.
 * It may be responsible for emitting, consuming, and decoding messages, which are crucial for coordinating actions between different components, chains, or contracts.
 * The contract serves as a communication hub to ensure the proper flow of information and execution of associated tasks within the overall system.
 */
contract Messager is Comn, IMessager {
    uint public bridge_fee;
    // The fee for cross - chain bridging operations.

    // Mapping from target chain ID to a nonce value. Nonce starts from 1 for each chain ID.
    // to chain_id => id start from 1
    mapping(uint => uint) public nonceMap;
    // Mapping from source chain ID to another mapping of nonce to a boolean indicating if the nonce has been used.
    // from chain_id => (nonce => bool)
    mapping(uint => mapping(uint => bool)) public nonceStateMap;

    /**
     * @dev Sets the bridge fee. Only the administrator can call this function.
     * @param _bridge_fee The new bridge fee to be set.
     */
    function set_bridge_fee(uint _bridge_fee) public onlyAdmin {
        bridge_fee = _bridge_fee;
    }

    /**
     * @dev Decodes a bytes - encoded message into a Types.Message struct.
     * @param message The bytes array representing the encoded message.
     * @return A Types.Message struct decoded from the input bytes.
     */
    function decode_msg(
        bytes memory message
    ) public pure returns (Types.Message memory) {
        return abi.decode(message, (Types.Message));
    }

    /**
     * @dev Decodes the body of a bridge message from a calldata bytes.
     * @param msg_body The calldata bytes representing the ABI - packed bridge message body.
     * @return A Types.BridgeMessageBody struct decoded from the input bytes.
     */
    function decode_bridge_msg_body(
        bytes calldata msg_body // this is a abi packed type
    ) public pure returns (Types.BridgeMessageBody memory) {
        bytes32 source_token = bytes32(msg_body[0:32]);
        uint128 all_amount = uint128(bytes16(msg_body[32:48]));
        // uint upload_gas_fee = uint(bytes32(msg_body[64:96]));
        bytes32 from_who = bytes32(msg_body[48:80]);
        bytes32 to_who = bytes32(msg_body[80:112]);
        bytes calldata biz_data = msg_body[112:];

        return
            Types.BridgeMessageBody({
                source_token: source_token,
                all_amount: all_amount,
                // upload_gas_fee: upload_gas_fee,
                from_who: from_who,
                to_who: to_who,
                biz_data: biz_data
            });
    }

    /**
     * @dev Converts a Types.MessageHeader struct to a bytes array.
     * @param header The Types.MessageHeader struct to be converted.
     * @return A bytes array representing the encoded message header.
     */
    function _convert_header_to_bytes(
        Types.MessageHeader memory header
    ) private pure returns (bytes memory) {
        return
            abi.encodePacked(
                header.msg_type,
                header.nonce,
                ComFunUtil.combainChain(header.from_chain),
                header.sender,
                ComFunUtil.combainChain(header.to_chain),
                header.receiver,
                header.upload_gas_fee
            );
    }

    /**
     * @dev Verifies the signature of a message and checks if it meets the minimum validator requirements.
     * @param messageDec The decoded Types.Message struct.
     * @param signature An array of bytes representing the signatures of the message.
     * @return A boolean indicating if the message is valid and the original decoded message.
     */
    function _verify_msg(
        Types.Message memory messageDec,
        bytes[] memory signature
    ) private returns (bool, Types.Message memory) {
        bytes32 msgHash = keccak256(
            bytes.concat(
                _convert_header_to_bytes(messageDec.msg_header),
                messageDec.msg_body
            )
        );

        emit Types.Log("msgHash in verify_msg: ", msgHash);
        Types.Message memory msgDec = messageDec;

        (address[] memory validators, uint min_verify_threshold) = IValidator(
            ValidatorAddr
        ).fetch_all_validators();
        if (signature.length < min_verify_threshold) {
            emit Types.Log("require min verify node", min_verify_threshold);
            return (false, msgDec);
        }

        uint256 validSignerCount = 0;
        bool[] memory uniqueSigners = new bool[](validators.length);
        for (uint i = 0; i < signature.length; i++) {
            address msg_signer = ECDSA.recover(msgHash, signature[i]);

            if (!isValidator(msg_signer, validators)) {
                revert("Not a valid signer node");
            }

            uint256 signerIndex = getValidatorIndex(msg_signer, validators);
            if (!uniqueSigners[signerIndex]) {
                uniqueSigners[signerIndex] = true;
                validSignerCount++;
            }
        }

        require(
            validSignerCount >= min_verify_threshold,
            "not meet minimum signer requirement"
        );
        return (true, msgDec);
    }

    /**
     * @dev Checks if an address is a validator.
     * @param signer The address to be checked.
     * @param validators An array of validator addresses.
     * @return A boolean indicating if the address is a validator.
     */
    function isValidator(
        address signer,
        address[] memory validators
    ) private pure returns (bool) {
        for (uint256 i = 0; i < validators.length; i++) {
            if (validators[i] == signer) {
                return true;
            }
        }
        return false;
    }

    /**
     * @dev Gets the index of a validator address in the validators array.
     * @param signer The address of the validator.
     * @param validators An array of validator addresses.
     * @return The index of the validator address in the array.
     */
    function getValidatorIndex(
        address signer,
        address[] memory validators
    ) private pure returns (uint256) {
        for (uint256 i = 0; i < validators.length; i++) {
            if (validators[i] == signer) {
                return i;
            }
        }
        revert("Signer not found in validators");
    }

    /**
     * @dev Verifies the signature of a message and returns a boolean indicating its validity.
     * @param messageDec The decoded Types.Message struct.
     * @param signature An array of bytes representing the signatures of the message.
     * @return A boolean indicating if the message is valid.
     */
    function verify_msg(
        Types.Message memory messageDec,
        bytes[] memory signature
    ) public returns (bool) {
        (bool rs, ) = _verify_msg(messageDec, signature);
        return rs;
    }

    /**
     * @dev Verifies the signature of a bridge message and consumes it by marking the nonce as used.
     * @param messageDec The decoded Types.Message struct.
     * @param signature An array of bytes representing the signatures of the message.
     * @return A boolean indicating if the message is valid and can be consumed.
     */
    function consume_bridge_msg(
        Types.Message memory messageDec,
        bytes[] memory signature
    ) public returns (bool) {
        address receiver = ComFunUtil.bytes32ToAddress(
            messageDec.msg_header.receiver
        );
        require(msg.sender == receiver, "not match receiver");

        (bool rs, ) = _verify_msg(messageDec, signature);

        uint from_chain_id = ComFunUtil.combainChain(
            messageDec.msg_header.from_chain
        );
        uint nonce = messageDec.msg_header.nonce;

        // not empty key
        if (nonceStateMap[from_chain_id][nonce]) {
            emit Types.Log("nonce has been used");
            return false;
        } else {
            nonceStateMap[from_chain_id][nonce] = true;
        }

        return rs;
    }

    /**
     * @dev Emits a message for cross - chain communication.
     * @param msg_type The type of the message.
     * @param to_chain The target chain information.
     * @param receiver The receiver's identifier in bytes32 format.
     * @param body_message The body of the message in bytes.
     * @param upload_gas_fee The gas fee for uploading the message.
     */
    function emit_msg(
        uint8 msg_type,
        Types.Chain memory to_chain,
        bytes32 receiver,
        bytes memory body_message,
        uint128 upload_gas_fee
    ) public payable {
        require(bridge_fee <= msg.value, "not enough gas");
        require(upload_gas_fee > 0, "upload_gas_fee must greater than 0");

        uint to_chain_uint = ComFunUtil.combainChain(to_chain);
        nonceMap[to_chain_uint] += 1;
        uint nonce = nonceMap[to_chain_uint];
        require(
            block.chainid <= type(uint64).max,
            "chainid exceed the maximum"
        );
        require(nonce <= type(uint64).max, "nonce exceed the maximum");

        Types.Message memory rs = Types.Message(
            Types.MessageHeader({
                msg_type: msg_type,
                nonce: uint64(nonce),
                from_chain: Types.Chain(
                    uint8(ChainType),
                    uint64(block.chainid)
                ),
                sender: ComFunUtil.addressToBytes32(address(msg.sender)),
                to_chain: to_chain,
                receiver: receiver,
                upload_gas_fee: upload_gas_fee
            }),
            body_message
        );
        emit Msg(rs);
        emit UploadFee(upload_gas_fee);
    }

    /**
     * @dev Allows a admin to withdraw the bridge fee.
     * @param amount The amount to be withdrawn.
     */
    function withdrawFee(uint amount) public onlyAdmin {
        require(amount <= address(this).balance, "not enough balance");

        Address.sendValue(payable(msg.sender), amount);
    }
}
"
    },
    "rainlink-contract-main/core/Comn.sol": {
      "content": "// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.20;

import "../BaseComn.sol";
import {Types} from "../comn/Types.sol";

/**
 * @title all sol extends from this
 * @dev Extends BaseComn with additional address constants
 */
abstract contract Comn is BaseComn {
    // xone
    address constant ValidatorAddr = address(0xfeBc13df64252cb83FbDAFa8d916867dAa30501a);

    // tbsc
    // address constant ValidatorAddr = address(0x237aeC76ED2bECC3e5df4f007F6E67CC2EAe68e9);

    // sepolia
    // address constant ValidatorAddr = address(0x1F1C9CFF1c78cE6d530b218dF61f25D7849A1791);

    // nile
    // address constant ValidatorAddr = address(0xa85E0F60586EbB70d05cE01D09B5750C04f8e046); //TRKTChDwwjFTi9mmL6iePHV6X2C42YN3TN

    // ETH chain
    Types.ChainType constant ChainType = Types.ChainType.ETH;

    // TRX chain
    // Types.ChainType constant ChainType = Types.ChainType.TRX;
}"
    },
    "rainlink-contract-main/comn/ComFunUtil.sol": {
      "content": "// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.20;

import {Types} from "./Types.sol";

library ComFunUtil {
    function isNotEmpty(address ad, string memory msgs) private pure {
        require(ad != address(0), msgs);
    }

    function isNotEmpty(uint ad, string memory msgs) private pure {
        require(ad != 0, msgs);
    }

    function combainChain(
        Types.Chain memory chain_
    ) internal pure returns (uint72) {
        uint72 c = chain_.chain_id;
        // must use uint72 to avoid u8 overflow
        uint72 chain_type = chain_.chain_type;
        c += chain_type << 64;
        return c;
    }

    function splitChain(uint a1) internal pure returns (Types.Chain memory c) {
        c.chain_id = uint64(a1);
        c.chain_type = uint8(a1 >> 64);
    }

    function addressToBytes32(address a) internal pure returns (bytes32 b) {
        return bytes32(uint(uint160(a)));
    }

    function bytes32ToAddress(bytes32 a) internal pure returns (address b) {
        return address(uint160(uint(a)));
    }

    function hexStr2bytes32(string memory data) internal pure returns (bytes32) {
        return bytes2bytes32(hexStr2bytes(data));
    }

    function bytes2bytes32(bytes memory data) internal pure returns (bytes32) {
        uint len = data.length;
        if (len > 32) {
            revert("data len is overflow 32");
        }

        uint rs = 0;
        for (uint i = 0; i < len; i++) {
            rs = rs << 8;
            rs += uint8(data[i]);
        }

        return bytes32(rs);
    }

    // convert hex string to bytes
    function hexStr2bytes(
        string memory data
    ) internal pure returns (bytes memory) {
        bytes memory a = bytes(data);
        if (a.length % 2 != 0) {
            revert("hex string len is invalid");
        }
        uint8[] memory b = new uint8[](a.length);

        for (uint i = 0; i < a.length; i++) {
            uint8 _a = uint8(a[i]);

            if (_a > 96) {
                b[i] = _a - 97 + 10;
            } else if (_a > 66) {
                b[i] = _a - 65 + 10;
            } else {
                b[i] = _a - 48;
            }
        }

        bytes memory c = new bytes(b.length / 2);
        for (uint _i = 0; _i < b.length; _i += 2) {
            c[_i / 2] = bytes1(b[_i] * 16 + b[_i + 1]);
        }

        return c;
    }

    function stringConcat(
        string memory a,
        string memory b,
        bytes memory d
    ) internal pure returns (string memory) {
        bytes memory a1 = bytes(a);
        bytes memory a2 = bytes(b);
        bytes memory a3;
        a3 = new bytes(a1.length + a2.length + d.length);
        uint k = 0;
        for (uint i = 0; i < a1.length; i++) {
            a3[k++] = a1[i];
        }

        for (uint i = 0; i < d.length; i++) {
            a3[k++] = d[i];
        }

        for (uint i = 0; i < a2.length; i++) {
            a3[k++] = a2[i];
        }

        return string(a3);
    }

    function currentTimestamp() internal view returns (uint256) {
        return block.timestamp;
    }
}
"
    },
    "rainlink-contract-main/comn/IValidator.sol": {
      "content": "// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.20;

interface IValidator {
    function batch_add_validators(
        bytes32[] memory signer_pk,
        uint threshold
    ) external;

    function batch_delete_validators(bytes32[] memory signer_pk) external returns (uint);

    function set_min_verify_threshold(uint v) external;

    function get_min_verify_threshold() external view returns (uint);

    function fetch_all_validators()
        external
        view
        returns (address[] memory, uint);

}
"
    },
    "rainlink-contract-main/comn/IMessager.sol": {
      "content": "// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.20;
import "./Types.sol";

interface IMessager {
    event Msg(Types.Message);
    event UploadFee(uint);

    function set_bridge_fee(uint v) external;

    function verify_msg(
        Types.Message memory messageDec,
        // uint16[] memory signer_index,
        bytes[] memory signature
    ) external returns (bool);

    function decode_msg(
        bytes memory message
    ) external pure returns (Types.Message memory);

    function decode_bridge_msg_body(
        bytes memory msg_body
    ) external pure returns (Types.BridgeMessageBody memory);

    // verify and consume it.
    function consume_bridge_msg(
        Types.Message memory messageDec,
        bytes[] memory signature
    ) external returns (bool);

    function emit_msg(
        uint8 msg_type,
        Types.Chain memory to_chain,
        bytes32 receiver,
        bytes memory message,
        uint128 upload_gas_fee // source p token.
    ) external payable;

    function withdrawFee(uint amount) external;
}
"
    },
    "rainlink-contract-main/comn/Types.sol": {
      "content": "// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.20;

// all data in this file we should remain static.
// as this file may be used when create empty StoreHouse. to avoid any data not being initialized. we should keet it static.

library Types {
    event Log(string);
    event Log(string, bytes);
    event Log(uint);
    event Log(string, uint);
    event Log(string, bytes32);
    event Log(string, bytes32, uint);
    event Log(string, address);

    struct PoolInfo {
        address token;
        uint amount; // actual remain amount.
        uint inAmount; // all in token = all in lock amount + all in stake amount.
        uint lockAmount; // actual locked by contract
        uint stakeAmount; // actual user stake into contract.
        uint rewardAmount; // reward for staker, will used in future. now all reward will added to stake amount.
        uint acc; // Q64.64
        uint last_apy; // Q64.64
        uint last_receive_rewards_time;
    }

    enum AmountType {
        locked,
        staked
    }

    enum TokenType {
        pool,
        mint
    }

    struct UserAmountInfo {
        address token;
        uint8 amountType; // 0 locked value. 1 staked value.
        uint amount;
        uint debt;
        uint remainReward;
        // for locked user. all amount = amount
        // for stake user all amount = amount*acc - debt + amount + remainReward
    }

    // for front end.
    struct UserAmountInfoForView {
        address token;
        uint8 amountType; // 0 locked value. 1 staked value.
        uint amount;
        uint debt;
        uint remainReward;
        uint acc;
        uint bonus;
        // for locked user. all amount = amount
        // for stake user all amount = amount*acc - debt + amount + remainReward
    }

    // for front end.
    struct UserAmountInfoForViewV2 {
        address token;
        uint8 amountType; // 0 locked value. 1 staked value.
        uint amount;
        uint debt;
        uint remainReward;
        uint acc;
        uint bonus;
        // for locked user. all amount = amount
        // for stake user all amount = amount*acc - debt + amount + remainReward
        uint earns;
    }

    struct FromSource {
        uint source_chain_id;
        bytes32 source_token;
    }

    struct RelationShipInfo {
        address dest_token;
        uint8 dest_token_type; // 0 for pool, 1 for new mint
    }

    struct SourceTokenInfo {
        uint8 initialized;
        uint8 decimals; // record the decimals for source token
    }

    struct CrossRelation {
        uint source_chain_id;
        bytes32 source_token;
        uint8 source_token_decimals;
        address dest_token;
        uint8 dest_token_type;
    }

    struct MessageMeta {
        // BridgeMessage bridgeMsg;
        // // other fields
        uint8 status; //
        uint[4] reserves;
    }

    struct Chain {
        uint8 chain_type;
        uint64 chain_id;
    }

    enum ChainType {
        ETH,
        TRX,
        SOL
    }

    struct Message {
        MessageHeader msg_header;
        bytes msg_body;
    }

    struct MessageHeader {
        uint8 msg_type; // 0 means bridge message
        uint64 nonce;
        Chain from_chain; //
        bytes32 sender;
        // address messager;
        Chain to_chain; //
        bytes32 receiver;
        uint128 upload_gas_fee;
    }

    struct BridgeMessageBody {
        // body
        bytes32 source_token;
        uint128 all_amount;
        // uint amount;
        // uint platform_fee;

        // uint upload_fee_price; // all amount = amount + platform_fee + upload_gas_fee * upload_fee_price
        bytes32 from_who;
        bytes32 to_who;
        bytes biz_data;
        // uint slipage;
    }

    struct ERC20Permit {
        address owner;
        address spender;
        uint256 value;
        uint256 deadline;
        uint8 v;
        bytes32 r;
        bytes32 s;
    }

    struct UserWithdrawData {
        address token;
        uint amount; // uni decimal.
        // string symbol;
    }

    struct UserWithdrawDataDetail {
        address token;
        string symbol;
        string name;
        uint8 decimal;
        uint amount;
    }

    struct ErrorObj {
        uint key;
        uint error_type;
        string sMsg;
        uint cMsg;
        bytes bMsg;
        string desc; // description
    }
}
"
    },
    "@openzeppelin/contracts@5.0.0/utils/Address.sol": {
      "content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/Address.sol)

pragma solidity ^0.8.20;

/**
 * @dev Collection of functions related to the address type
 */
library Address {
    /**
     * @dev The ETH balance of the account is not enough to perform the operation.
     */
    error AddressInsufficientBalance(address account);

    /**
     * @dev There's no code at `target` (it is not a contract).
     */
    error AddressEmptyCode(address target);

    /**
     * @dev A call to an address target failed. The target may have reverted.
     */
    error FailedInnerCall();

    /**
     * @dev Replacement for Solidity's `transfer`: sends `amount` wei to
     * `recipient`, forwarding all available gas and reverting on errors.
     *
     * https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
     * of certain opcodes, possibly making contracts go over the 2300 gas limit
     * imposed by `transfer`, making them unable to receive funds via
     * `transfer`. {sendValue} removes this limitation.
     *
     * https://consensys.net/diligence/blog/2019/09/stop-using-soliditys-transfer-now/[Learn more].
     *
     * IMPORTANT: because control is transferred to `recipient`, care must be
     * taken to not create reentrancy vulnerabilities. Consider using
     * {ReentrancyGuard} or the
     * https://solidity.readthedocs.io/en/v0.8.20/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
     */
    function sendValue(address payable recipient, uint256 amount) internal {
        if (address(this).balance < amount) {
            revert AddressInsufficientBalance(address(this));
        }

        (bool success, ) = recipient.call{value: amount}("");
        if (!success) {
            revert FailedInnerCall();
        }
    }

    /**
     * @dev Performs a Solidity function call using a low level `call`. A
     * plain `call` is an unsafe replacement for a function call: use this
     * function instead.
     *
     * If `target` reverts with a revert reason or custom error, it is bubbled
     * up by this function (like regular Solidity function calls). However, if
     * the call reverted with no returned reason, this function reverts with a
     * {FailedInnerCall} error.
     *
     * Returns the raw returned data. To convert to the expected return value,
     * use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
     *
     * Requirements:
     *
     * - `target` must be a contract.
     * - calling `target` with `data` must not revert.
     */
    function functionCall(address target, bytes memory data) internal returns (bytes memory) {
        return functionCallWithValue(target, data, 0);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but also transferring `value` wei to `target`.
     *
     * Requirements:
     *
     * - the calling contract must have an ETH balance of at least `value`.
     * - the called Solidity function must be `payable`.
     */
    function functionCallWithValue(address target, bytes memory data, uint256 value) internal returns (bytes memory) {
        if (address(this).balance < value) {
            revert AddressInsufficientBalance(address(this));
        }
        (bool success, bytes memory returndata) = target.call{value: value}(data);
        return verifyCallResultFromTarget(target, success, returndata);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a static call.
     */
    function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
        (bool success, bytes memory returndata) = target.staticcall(data);
        return verifyCallResultFromTarget(target, success, returndata);
    }

    /**
     * @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
     * but performing a delegate call.
     */
    function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
        (bool success, bytes memory returndata) = target.delegatecall(data);
        return verifyCallResultFromTarget(target, success, returndata);
    }

    /**
     * @dev Tool to verify that a low level call to smart-contract was successful, and reverts if the target
     * was not a contract or bubbling up the revert reason (falling back to {FailedInnerCall}) in case of an
     * unsuccessful call.
     */
    function verifyCallResultFromTarget(
        address target,
        bool success,
        bytes memory returndata
    ) internal view returns (bytes memory) {
        if (!success) {
            _revert(returndata);
        } else {
            // only check if target is a contract if the call was successful and the return data is empty
            // otherwise we already know that it was a contract
            if (returndata.length == 0 && target.code.length == 0) {
                revert AddressEmptyCode(target);
            }
            return returndata;
        }
    }

    /**
     * @dev Tool to verify that a low level call was successful, and reverts if it wasn't, either by bubbling the
     * revert reason or with a default {FailedInnerCall} error.
     */
    function verifyCallResult(bool success, bytes memory returndata) internal pure returns (bytes memory) {
        if (!success) {
            _revert(returndata);
        } else {
            return returndata;
        }
    }

    /**
     * @dev Reverts with returndata if present. Otherwise reverts with {FailedInnerCall}.
     */
    function _revert(bytes memory returndata) private pure {
        // Look for revert reason and bubble it up if present
        if (returndata.length > 0) {
            // The easiest way to bubble the revert reason is using memory via assembly
            /// @solidity memory-safe-assembly
            assembly {
                let returndata_size := mload(returndata)
                revert(add(32, returndata), returndata_size)
            }
        } else {
            revert FailedInnerCall();
        }
    }
}
"
    },
    "@openzeppelin/contracts@5.0.0/utils/cryptography/ECDSA.sol": {
      "content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/cryptography/ECDSA.sol)

pragma solidity ^0.8.20;

/**
 * @dev Elliptic Curve Digital Signature Algorithm (ECDSA) operations.
 *
 * These functions can be used to verify that a message was signed by the holder
 * of the private keys of a given address.
 */
library ECDSA {
    enum RecoverError {
        NoError,
        InvalidSignature,
        InvalidSignatureLength,
        InvalidSignatureS
    }

    /**
     * @dev The signature derives the `address(0)`.
     */
    error ECDSAInvalidSignature();

    /**
     * @dev The signature has an invalid length.
     */
    error ECDSAInvalidSignatureLength(uint256 length);

    /**
     * @dev The signature has an S value that is in the upper half order.
     */
    error ECDSAInvalidSignatureS(bytes32 s);

    /**
     * @dev Returns the address that signed a hashed message (`hash`) with `signature` or an error. This will not
     * return address(0) without also returning an error description. Errors are documented using an enum (error type)
     * and a bytes32 providing additional information about the error.
     *
     * If no error is returned, then the address can be used for verification purposes.
     *
     * The `ecrecover` EVM precompile allows for malleable (non-unique) signatures:
     * this function rejects them by requiring the `s` value to be in the lower
     * half order, and the `v` value to be either 27 or 28.
     *
     * IMPORTANT: `hash` _must_ be the result of a hash operation for the
     * verification to be secure: it is possible to craft signatures that
     * recover to arbitrary addresses for non-hashed data. A safe way to ensure
     * this is by receiving a hash of the original message (which may otherwise
     * be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it.
     *
     * Documentation for signature generation:
     * - with https://web3js.readthedocs.io/en/v1.3.4/web3-eth-accounts.html#sign[Web3.js]
     * - with https://docs.ethers.io/v5/api/signer/#Signer-signMessage[ethers]
     */
    function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError, bytes32) {
        if (signature.length == 65) {
            bytes32 r;
            bytes32 s;
            uint8 v;
            // ecrecover takes the signature parameters, and the only way to get them
            // currently is to use assembly.
            /// @solidity memory-safe-assembly
            assembly {
                r := mload(add(signature, 0x20))
                s := mload(add(signature, 0x40))
                v := byte(0, mload(add(signature, 0x60)))
            }
            return tryRecover(hash, v, r, s);
        } else {
            return (address(0), RecoverError.InvalidSignatureLength, bytes32(signature.length));
        }
    }

    /**
     * @dev Returns the address that signed a hashed message (`hash`) with
     * `signature`. This address can then be used for verification purposes.
     *
     * The `ecrecover` EVM precompile allows for malleable (non-unique) signatures:
     * this function rejects them by requiring the `s` value to be in the lower
     * half order, and the `v` value to be either 27 or 28.
     *
     * IMPORTANT: `hash` _must_ be the result of a hash operation for the
     * verification to be secure: it is possible to craft signatures that
     * recover to arbitrary addresses for non-hashed data. A safe way to ensure
     * this is by receiving a hash of the original message (which may otherwise
     * be too long), and then calling {MessageHashUtils-toEthSignedMessageHash} on it.
     */
    function recover(bytes32 hash, bytes memory signature) internal pure returns (address) {
        (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, signature);
        _throwError(error, errorArg);
        return recovered;
    }

    /**
     * @dev Overload of {ECDSA-tryRecover} that receives the `r` and `vs` short-signature fields separately.
     *
     * See https://eips.ethereum.org/EIPS/eip-2098[EIP-2098 short signatures]
     */
    function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError, bytes32) {
        unchecked {
            bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff);
            // We do not check for an overflow here since the shift operation results in 0 or 1.
            uint8 v = uint8((uint256(vs) >> 255) + 27);
            return tryRecover(hash, v, r, s);
        }
    }

    /**
     * @dev Overload of {ECDSA-recover} that receives the `r and `vs` short-signature fields separately.
     */
    function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) {
        (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, r, vs);
        _throwError(error, errorArg);
        return recovered;
    }

    /**
     * @dev Overload of {ECDSA-tryRecover} that receives the `v`,
     * `r` and `s` signature fields separately.
     */
    function tryRecover(
        bytes32 hash,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) internal pure returns (address, RecoverError, bytes32) {
        // EIP-2 still allows signature malleability for ecrecover(). Remove this possibility and make the signature
        // unique. Appendix F in the Ethereum Yellow paper (https://ethereum.github.io/yellowpaper/paper.pdf), defines
        // the valid range for s in (301): 0 < s < secp256k1n ÷ 2 + 1, and for v in (302): v ∈ {27, 28}. Most
        // signatures from current libraries generate a unique signature with an s-value in the lower half order.
        //
        // If your library generates malleable signatures, such as s-values in the upper range, calculate a new s-value
        // with 0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFEBAAEDCE6AF48A03BBFD25E8CD0364141 - s1 and flip v from 27 to 28 or
        // vice versa. If your library also generates signatures with 0/1 for v instead 27/28, add 27 to v to accept
        // these malleable signatures as well.
        if (uint256(s) > 0x7FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF5D576E7357A4501DDFE92F46681B20A0) {
            return (address(0), RecoverError.InvalidSignatureS, s);
        }

        // If the signature is valid (and not malleable), return the signer address
        address signer = ecrecover(hash, v, r, s);
        if (signer == address(0)) {
            return (address(0), RecoverError.InvalidSignature, bytes32(0));
        }

        return (signer, RecoverError.NoError, bytes32(0));
    }

    /**
     * @dev Overload of {ECDSA-recover} that receives the `v`,
     * `r` and `s` signature fields separately.
     */
    function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address) {
        (address recovered, RecoverError error, bytes32 errorArg) = tryRecover(hash, v, r, s);
        _throwError(error, errorArg);
        return recovered;
    }

    /**
     * @dev Optionally reverts with the corresponding custom error according to the `error` argument provided.
     */
    function _throwError(RecoverError error, bytes32 errorArg) private pure {
        if (error == RecoverError.NoError) {
            return; // no error: do nothing
        } else if (error == RecoverError.InvalidSignature) {
            revert ECDSAInvalidSignature();
        } else if (error == RecoverError.InvalidSignatureLength) {
            revert ECDSAInvalidSignatureLength(uint256(errorArg));
        } else if (error == RecoverError.InvalidSignatureS) {
            revert ECDSAInvalidSignatureS(errorArg);
        }
    }
}
"
    },
    "rainlink-contract-main/BaseComn.sol": {
      "content": "// SPDX-License-Identifier: BUSL-1.1
pragma solidity ^0.8.20;

import "./comn/IAdmin.sol";
import {StorageSlot} from "@openzeppelin/contracts@5.0.0/utils/StorageSlot.sol";

/**
 * @title BaseComn
 * @dev Contains the core constants and base functionality
 */
abstract contract BaseComn {
    bytes32 constant _ADMIN_SLOT =
        0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;

    modifier onlyMaster() {
        IAdmin(getAdminAddr()).mustMaster(msg.sender);
        _;
    }

    /**
     * @dev Throws if called by any account other than the admin.
     */
    modifier onlyAdmin() {
        IAdmin(getAdminAddr()).mustAdmin(msg.sender);
        _;
    }

    /**
     * @dev Returns the admin address from storage slot
     */
    function getAdminAddr() public view returns (address) {
        return StorageSlot.getAddressSlot(_ADMIN_SLOT).value;
    }
}
"
    },
    "@openzeppelin/contracts@5.0.0/utils/StorageSlot.sol": {
      "content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/StorageSlot.sol)
// This file was procedurally generated from scripts/generate/templates/StorageSlot.js.

pragma solidity ^0.8.20;

/**
 * @dev Library for reading and writing primitive types to specific storage slots.
 *
 * Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.
 * This library helps with reading and writing to such slots without the need for inline assembly.
 *
 * The functions in this library return Slot structs that contain a `value` member that can be used to read or write.
 *
 * Example usage to set ERC1967 implementation slot:
 * ```solidity
 * contract ERC1967 {
 *     bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
 *
 *     function _getImplementation() internal view returns (address) {
 *         return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
 *     }
 *
 *     function _setImplementation(address newImplementation) internal {
 *         require(newImplementation.code.length > 0);
 *         StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
 *     }
 * }
 * ```
 */
library StorageSlot {
    struct AddressSlot {
        address value;
    }

    struct BooleanSlot {
        bool value;
    }

    struct Bytes32Slot {
        bytes32 value;
    }

    struct Uint256Slot {
        uint256 value;
    }

    struct StringSlot {
        string value;
    }

    struct BytesSlot {
        bytes value;
    }

    /**
     * @dev Returns an `AddressSlot` with member `value` located at `slot`.
     */
    function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `BooleanSlot` with member `value` located at `slot`.
     */
    function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `Bytes32Slot` with member `value` located at `slot`.
     */
    function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `Uint256Slot` with member `value` located at `slot`.
     */
    function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `StringSlot` with member `value` located at `slot`.
     */
    function getStringSlot(bytes32 slot) internal pure returns (StringSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `StringSlot` representation of the string storage pointer `store`.
     */
    function getStringSlot(string storage store) internal pure returns (StringSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := store.slot
        }
    }

    /**
     * @dev Returns an `BytesSlot` with member `value` located at `slot`.
     */
    function getBytesSlot(bytes32 slot) internal pure returns (BytesSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := slot
        }
    }

    /**
     * @dev Returns an `BytesSlot` representation of the bytes storage pointer `store`.
     */
    function getBytesSlot(bytes storage store) internal pure returns (BytesSlot storage r) {
        /// @solidity memory-safe-assembly
        assembly {
            r.slot := store.slot
        }
    }
}
"
    },
    "rainlink-contract-main/comn/IAdmin.sol": {
      "content": "// SPDX-License-Identifier: GPL-3.0

pragma solidity ^0.8.0;

/**
 * @dev Interface for Admin
 */
interface IAdmin {
    function mustMaster(address addr) external view;
    function mustAdmin(address addr) external view;
    function isMaster(address addr) external view returns (bool);
    function isAdmin(address addr) external view returns (bool);
}
"
    }
  },
  "settings": {
    "optimizer": {
      "enabled": true,
      "runs": 200
    },
    "outputSelection": {
      "*": {
        "*": [
          "evm.bytecode",
          "evm.deployedBytecode",
          "devdoc",
          "userdoc",
          "metadata",
          "abi"
        ]
      }
    },
    "remappings": [],
    "evmVersion": "london"
  }
}}

Tags:
Proxy, Upgradeable, Factory|addr:0x0e601df837efe9cc2429fedb607634f4b0914126|verified:true|block:23403305|tx:0x21b2479bdb98127fd11d5a29367183e092300e80500cc62e4891f5835e7b43e0|first_check:1758371507

Submitted on: 2025-09-20 14:31:49

Comments

Log in to comment.

No comments yet.