Sepolia Testnet

Contract

0x821697D678f950Eb39229B707180197Be8A7F7F3

Overview

ETH Balance

0.09999999977098 ETH

Multichain Info

N/A
Transaction Hash
Method
Block
From
To
Submit Data63214452024-07-16 13:31:2480 days ago1721136684IN
0x821697D6...Be8A7F7F3
0 ETH0.000209273.79642304
Submit Data63214452024-07-16 13:31:2480 days ago1721136684IN
0x821697D6...Be8A7F7F3
0 ETH0.000209273.79642304
Submit Data63214452024-07-16 13:31:2480 days ago1721136684IN
0x821697D6...Be8A7F7F3
0 ETH0.001759263.79642304
Submit Data63214422024-07-16 13:30:2480 days ago1721136624IN
0x821697D6...Be8A7F7F3
0 ETH0.000172813.13497962
Submit Data63214422024-07-16 13:30:2480 days ago1721136624IN
0x821697D6...Be8A7F7F3
0 ETH0.001452713.13497962
Submit Data63214402024-07-16 13:29:4880 days ago1721136588IN
0x821697D6...Be8A7F7F3
0 ETH0.00016432.9805943
Submit Data63214402024-07-16 13:29:4880 days ago1721136588IN
0x821697D6...Be8A7F7F3
0 ETH0.00138122.9805943
Submit Data63214382024-07-16 13:29:1280 days ago1721136552IN
0x821697D6...Be8A7F7F3
0 ETH0.001306282.81890659
Submit Data63212712024-07-16 12:51:4880 days ago1721134308IN
0x821697D6...Be8A7F7F3
0 ETH0.001923834.14554414
Submit Data63212692024-07-16 12:51:2480 days ago1721134284IN
0x821697D6...Be8A7F7F3
0 ETH0.001971154.2476293
Submit Data63212672024-07-16 12:51:0080 days ago1721134260IN
0x821697D6...Be8A7F7F3
0 ETH0.00220914.28216356
Submit Data63182922024-07-16 1:20:1281 days ago1721092812IN
0x821697D6...Be8A7F7F3
0 ETH0.003343368.70016953
Submit Data63182912024-07-16 1:20:0081 days ago1721092800IN
0x821697D6...Be8A7F7F3
0 ETH0.003735368.56538619
Submit Data63179052024-07-15 23:50:3681 days ago1721087436IN
0x821697D6...Be8A7F7F3
0 ETH0.003211827.91935599
Register API63169622024-07-15 20:07:2481 days ago1721074044IN
0x821697D6...Be8A7F7F3
0 ETH0.000550232.51122402
Register API63139792024-07-15 8:35:0081 days ago1721032500IN
0x821697D6...Be8A7F7F3
0 ETH0.0075529231.97329435
Submit Data63035252024-07-13 15:23:1283 days ago1720884192IN
0x821697D6...Be8A7F7F3
0 ETH0.003532098.70895044
Submit Data63035242024-07-13 15:22:4883 days ago1720884168IN
0x821697D6...Be8A7F7F3
0 ETH0.000442048.41915699
Submit Data63035242024-07-13 15:22:4883 days ago1720884168IN
0x821697D6...Be8A7F7F3
0 ETH0.003414568.41915699
Submit Data63035202024-07-13 15:21:3683 days ago1720884096IN
0x821697D6...Be8A7F7F3
0 ETH0.000393627.49853711
Submit Data63035202024-07-13 15:21:3683 days ago1720884096IN
0x821697D6...Be8A7F7F3
0 ETH0.003041097.49853711
Submit Data63035182024-07-13 15:21:0083 days ago1720884060IN
0x821697D6...Be8A7F7F3
0 ETH0.002991766.99398183
Submit Data62982742024-07-12 19:44:3684 days ago1720813476IN
0x821697D6...Be8A7F7F3
0 ETH0.00268516.62081571
Submit Data62982722024-07-12 19:43:4884 days ago1720813428IN
0x821697D6...Be8A7F7F3
0 ETH0.00286047.05285145
Submit Data62982692024-07-12 19:43:1284 days ago1720813392IN
0x821697D6...Be8A7F7F3
0 ETH0.002880717.1029251
View all transactions

Latest 25 internal transactions (View All)

Advanced mode:
Parent Transaction Hash Block From To
63182922024-07-16 1:20:1281 days ago1721092812
0x821697D6...Be8A7F7F3
0 ETH
63182912024-07-16 1:20:0081 days ago1721092800
0x821697D6...Be8A7F7F3
0 ETH
63179052024-07-15 23:50:3681 days ago1721087436
0x821697D6...Be8A7F7F3
0 ETH
63035252024-07-13 15:23:1283 days ago1720884192
0x821697D6...Be8A7F7F3
0 ETH
63035242024-07-13 15:22:4883 days ago1720884168
0x821697D6...Be8A7F7F3
0 ETH
63035202024-07-13 15:21:3683 days ago1720884096
0x821697D6...Be8A7F7F3
0 ETH
63035182024-07-13 15:21:0083 days ago1720884060
0x821697D6...Be8A7F7F3
0 ETH
62982742024-07-12 19:44:3684 days ago1720813476
0x821697D6...Be8A7F7F3
0 ETH
62982722024-07-12 19:43:4884 days ago1720813428
0x821697D6...Be8A7F7F3
0 ETH
62982692024-07-12 19:43:1284 days ago1720813392
0x821697D6...Be8A7F7F3
0 ETH
62982662024-07-12 19:42:3684 days ago1720813356
0x821697D6...Be8A7F7F3
0 ETH
62982632024-07-12 19:42:0084 days ago1720813320
0x821697D6...Be8A7F7F3
0 ETH
62982612024-07-12 19:41:2484 days ago1720813284
0x821697D6...Be8A7F7F3
0 ETH
62982592024-07-12 19:40:4884 days ago1720813248
0x821697D6...Be8A7F7F3
0 ETH
62982572024-07-12 19:40:2484 days ago1720813224
0x821697D6...Be8A7F7F3
0 ETH
62982532024-07-12 19:39:3684 days ago1720813176
0x821697D6...Be8A7F7F3
0 ETH
62982502024-07-12 19:39:0084 days ago1720813140
0x821697D6...Be8A7F7F3
0 ETH
62982462024-07-12 19:38:1284 days ago1720813092
0x821697D6...Be8A7F7F3
0 ETH
62982442024-07-12 19:37:3684 days ago1720813056
0x821697D6...Be8A7F7F3
0 ETH
62982422024-07-12 19:37:1284 days ago1720813032
0x821697D6...Be8A7F7F3
0 ETH
62982392024-07-12 19:36:2484 days ago1720812984
0x821697D6...Be8A7F7F3
0 ETH
62982362024-07-12 19:35:4884 days ago1720812948
0x821697D6...Be8A7F7F3
0 ETH
62982332024-07-12 19:35:0084 days ago1720812900
0x821697D6...Be8A7F7F3
0 ETH
62982292024-07-12 19:34:1284 days ago1720812852
0x821697D6...Be8A7F7F3
0 ETH
62982232024-07-12 19:32:2484 days ago1720812744
0x821697D6...Be8A7F7F3
0 ETH
View All Internal Transactions
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
DataFeedDAO

Compiler Version
v0.8.24+commit.e11b9ed9

Optimization Enabled:
Yes with 500 runs

Other Settings:
paris EvmVersion

Contract Source Code (Solidity Standard Json-Input format)

File 1 of 10 : DataFeedDAO.sol
// SPDX-License-Identifier: GPL-3.0

pragma solidity ^0.8.4;

import "./SubStringUtils.sol";
import "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
import "@reclaimprotocol/verifier-solidity-sdk/contracts/Reclaim.sol";
import "@reclaimprotocol/verifier-solidity-sdk/contracts/Addresses.sol";

contract DataFeedDAO is ReentrancyGuard {
    using SubStringUtils for string;

    Reclaim public reclaimSDK;

    struct DataInfo {
        string content;
        address submitter;
        uint submissionTime;
    }

    struct APIData {
        string apiName;
        string apiDescription;
        uint currentTick;
        uint updateCoolDown;
        uint submissionReward;
        uint dataFreshnessWindow;
        uint contributorsCount;
        mapping(uint => DataInfo) data;
    }

    string[] private apis;
    mapping(string => APIData) private apiData;
    mapping(string => uint) private deposits;
    mapping(string => mapping(address => uint)) private contributions;

    event Funded(address by, string apiUrl, uint value);

    constructor(Reclaim _reclaimSDK) {
        reclaimSDK = _reclaimSDK;
    }

    function depositFund(string memory apiUrl) external payable {
        deposits[apiUrl] += msg.value;
        emit Funded(msg.sender, apiUrl, msg.value);
    }

    function registerAPI(
        string memory _apiName,
        string memory _apiDescription,
        string memory _url,
        uint _updateCoolDown,
        uint _submissionReward,
        uint _dataFreshnessWindow
    ) external {
        apiData[_url].apiName = _apiName;
        apiData[_url].apiDescription = _apiDescription;
        apiData[_url].updateCoolDown = _updateCoolDown;
        apiData[_url].submissionReward = _submissionReward;
        apiData[_url].dataFreshnessWindow = _dataFreshnessWindow;
        apiData[_url].currentTick = 0;

        apis.push(_url);
    }

    function submitData(
        string memory _url,
        string memory _data,
        Reclaim.Proof memory proof
    ) external nonReentrant {
        APIData storage apidata = apiData[_url];
        require(
            proof.signedClaim.claim.timestampS >
                block.timestamp - apidata.dataFreshnessWindow,
            "Outdated data cannot be submitted."
        );
        if (apidata.currentTick > 0) {
            require(
                apidata.data[apidata.currentTick - 1].submissionTime +
                    apidata.updateCoolDown <
                    block.timestamp,
                "Too early to submit new data."
            );
        }

        require(
            address(this).balance >= apidata.submissionReward,
            "Balance not enough in the contract."
        );

        string memory parameters = proof.claimInfo.parameters;

        reclaimSDK.verifyProof(proof);
        checkDataValidity(parameters, _url, _data);

        apidata.data[apidata.currentTick].content = _data;
        apidata.data[apidata.currentTick].submissionTime = block.timestamp;
        apidata.data[apidata.currentTick].submitter = msg.sender;
        apidata.currentTick++;
        if (contributions[_url][msg.sender] == 0) {
            apidata.contributorsCount++;
        }
        contributions[_url][msg.sender]++;
        (bool result, ) = msg.sender.call{value: apidata.submissionReward}("");
        require(result);
    }

    function getAPIUrlfromID(uint id) external view returns (string memory) {
        require(id < apis.length, "Invalid id");
        return apis[id];
    }

    function getAPIListLength() external view returns (uint) {
        return apis.length;
    }

    function getAPIData(
        string memory url,
        uint tickOffset
    ) external view returns (string memory) {
        require(apiData[url].currentTick >= 1, "Data doesn't exist");
        return
            apiData[url]
                .data[apiData[url].currentTick - tickOffset - 1]
                .content;
    }

    function getAPIInfo(
        string memory url
    ) external view returns (string memory, string memory, uint, uint, uint, uint, uint, address, uint) {
        APIData storage api = apiData[url];
        address lastSubmitter;
        uint lastSubmissionTime;
        if (api.currentTick > 0) {
            lastSubmitter = api.data[api.currentTick-1].submitter;
            lastSubmissionTime = api.data[api.currentTick-1].submissionTime;
        }
        return (
            api.apiName,
            api.apiDescription,
            api.updateCoolDown,
            api.submissionReward,
            api.dataFreshnessWindow,
            api.currentTick,
            api.contributorsCount,
            lastSubmitter,
            lastSubmissionTime
        );
    }

    function getDepositedFund(string memory apiURL) external view returns (uint256) {
        return deposits[apiURL];
    }

    function checkDataValidity(
        string memory parameters,
        string memory _url,
        string memory _data
    ) private pure {
        // Checks for url match
        require(
            parameters.findSubstring(
                string(abi.encodePacked('"url":"', _url, '"'))
            ) != -1,
            "Invalid URL!"
        );

        // Checks for data match
        uint dataStartIndex = uint(parameters.findSubstring('"value":"') + 9);
        require(
            keccak256(
                bytes(parameters.substring(dataStartIndex, dataStartIndex + bytes(_data).length))
            ) == keccak256(bytes(_data)),
            "Data mismatch!"
        );
    }
}

File 2 of 10 : ECDSA.sol
// 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);
        }
    }
}

File 3 of 10 : ReentrancyGuard.sol
// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (utils/ReentrancyGuard.sol)

pragma solidity ^0.8.20;

/**
 * @dev Contract module that helps prevent reentrant calls to a function.
 *
 * Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
 * available, which can be applied to functions to make sure there are no nested
 * (reentrant) calls to them.
 *
 * Note that because there is a single `nonReentrant` guard, functions marked as
 * `nonReentrant` may not call one another. This can be worked around by making
 * those functions `private`, and then adding `external` `nonReentrant` entry
 * points to them.
 *
 * TIP: If you would like to learn more about reentrancy and alternative ways
 * to protect against it, check out our blog post
 * https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
 */
abstract contract ReentrancyGuard {
    // Booleans are more expensive than uint256 or any type that takes up a full
    // word because each write operation emits an extra SLOAD to first read the
    // slot's contents, replace the bits taken up by the boolean, and then write
    // back. This is the compiler's defense against contract upgrades and
    // pointer aliasing, and it cannot be disabled.

    // The values being non-zero value makes deployment a bit more expensive,
    // but in exchange the refund on every call to nonReentrant will be lower in
    // amount. Since refunds are capped to a percentage of the total
    // transaction's gas, it is best to keep them low in cases like this one, to
    // increase the likelihood of the full refund coming into effect.
    uint256 private constant NOT_ENTERED = 1;
    uint256 private constant ENTERED = 2;

    uint256 private _status;

    /**
     * @dev Unauthorized reentrant call.
     */
    error ReentrancyGuardReentrantCall();

    constructor() {
        _status = NOT_ENTERED;
    }

    /**
     * @dev Prevents a contract from calling itself, directly or indirectly.
     * Calling a `nonReentrant` function from another `nonReentrant`
     * function is not supported. It is possible to prevent this from happening
     * by making the `nonReentrant` function external, and making it call a
     * `private` function that does the actual work.
     */
    modifier nonReentrant() {
        _nonReentrantBefore();
        _;
        _nonReentrantAfter();
    }

    function _nonReentrantBefore() private {
        // On the first call to nonReentrant, _status will be NOT_ENTERED
        if (_status == ENTERED) {
            revert ReentrancyGuardReentrantCall();
        }

        // Any calls to nonReentrant after this point will fail
        _status = ENTERED;
    }

    function _nonReentrantAfter() private {
        // By storing the original value once again, a refund is triggered (see
        // https://eips.ethereum.org/EIPS/eip-2200)
        _status = NOT_ENTERED;
    }

    /**
     * @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
     * `nonReentrant` function in the call stack.
     */
    function _reentrancyGuardEntered() internal view returns (bool) {
        return _status == ENTERED;
    }
}

File 4 of 10 : Addresses.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/**
 * Reclaim's addresses
 */

library Addresses {
    address public constant BASE_MAINNET =
        0xACE04E6DeB9567C1B8F37D113F2Da9E690Fc128d;
    address public constant BNB_MAINNET =
        0x1bbb0896aC6F4E32a89157C73Fb830325a441cb9;
    address public constant POLYGON_MAINNET =
        0xEA11e7aBC9E4260747C11b1B9A25F65364a35A27;
    address public constant ARBITRUM_MAINNET =
        0xe79A453bD088F4A58656b315a7C1f8Ea3473CCf1;
    address public constant OPTIMISM_MAINNET =
        0xe79A453bD088F4A58656b315a7C1f8Ea3473CCf1;
    address public constant OPTIMISM_GOERLI_TESTNET =
        0x2f0306D698685BEf7ff50745BFF7178F0d117ba8;
    address public constant LINEA_TESTNET =
        0xf223E215B2c9A2E5FE1B2971d5694684b2E734C1;
    address public constant PLOYGON_MUMBAI_TESTNET =
        0xd6534f52CEB3d0139b915bc0C3278a94687fA5C7;
}

File 5 of 10 : BytesUtils.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/**
 * Utilities for bytes manipulation & conversion
 */
library BytesUtils {
	function bytesToUInt(bytes memory data, uint offset) internal pure returns (uint) {
		require(offset + 4 <= data.length, "Offset + 4 must be within data bounds");

		uint32 result;
		assembly {
			// Load the 32 bits (4 bytes) from the data at the given offset into the result variable
			result := mload(add(add(data, 0x4), offset))
		}

		return result;
	}
}

File 6 of 10 : Claims.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

import "@openzeppelin/contracts/utils/cryptography/ECDSA.sol";
import "./StringUtils.sol";

/**
 * Library to assist with requesting,
 * serialising & verifying credentials
 */
library Claims {
	/** Data required to describe a claim */
	struct CompleteClaimData {
		bytes32 identifier;
		address owner;
		uint32 timestampS;
		uint32 epoch;
	}

	struct ClaimInfo {
		string provider;
		string parameters;
		string context;
	}

	/** Claim with signatures & signer */
	struct SignedClaim {
		CompleteClaimData claim;
		bytes[] signatures;
	}

	/**
	 * Asserts that the claim is signed by the expected witnesses
	 */
	function assertValidSignedClaim(
		SignedClaim memory self,
		address[] memory expectedWitnessAddresses
	) internal pure {
		require(self.signatures.length > 0, "No signatures");
		address[] memory signedWitnesses = recoverSignersOfSignedClaim(self);
		for (uint256 i = 0; i < expectedWitnessAddresses.length; i++) {
			bool found = false;
			for (uint256 j = 0; j < signedWitnesses.length; j++) {
				if (signedWitnesses[j] == expectedWitnessAddresses[i]) {
					found = true;
					break;
				}
			}
			require(found, "Missing witness signature");
		}
	}

	/**
	 * @dev recovers the signer of the claim
	 */
	function recoverSignersOfSignedClaim(
		SignedClaim memory self
	) internal pure returns (address[] memory) {
		bytes memory serialised = serialise(self.claim);
		address[] memory signers = new address[](self.signatures.length);
		for (uint256 i = 0; i < self.signatures.length; i++) {
			signers[i] = verifySignature(serialised, self.signatures[i]);
		}

		return signers;
	}

	/**
	 * @dev serialises the credential into a string;
	 * the string is used to verify the signature
	 *
	 * the serialisation is the same as done by the TS library
	 */
	function serialise(
		CompleteClaimData memory self
	) internal pure returns (bytes memory) {
		return
			abi.encodePacked(
				StringUtils.bytes2str(abi.encodePacked(self.identifier)),
				"\n",
				StringUtils.address2str(self.owner),
				"\n",
				StringUtils.uint2str(self.timestampS),
				"\n",
				StringUtils.uint2str(self.epoch)
			);
	}

	/**
	 * @dev returns the address of the user that generated the signature
	 */
	function verifySignature(
		bytes memory content,
		bytes memory signature
	) internal pure returns (address signer) {
		bytes32 signedHash = keccak256(
			abi.encodePacked(
				"\x19Ethereum Signed Message:\n",
				StringUtils.uint2str(content.length),
				content
			)
		);
		return ECDSA.recover(signedHash, signature);
	}

	function hashClaimInfo(ClaimInfo memory claimInfo) internal pure returns (bytes32) {
		bytes memory serialised = abi.encodePacked(
			claimInfo.provider,
			"\n",
			claimInfo.parameters,
			"\n",
			claimInfo.context
		);
		return keccak256(serialised);
	}
}

File 7 of 10 : Random.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

// implementation from: https://stackoverflow.com/a/67332959
// Utils for random number generation
library Random {
	/**
	 * @dev generates a random number from the given seed
	 * This will always return the same number for the same seed & block
	 */
	function random(uint256 seed) internal view returns (uint) {
		return uint(keccak256(abi.encodePacked(block.difficulty, block.timestamp, seed)));
	}
}

File 8 of 10 : Reclaim.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

import "./Claims.sol";
import "./Random.sol";
import "./StringUtils.sol";
import "./BytesUtils.sol";

// import "hardhat/console.sol";


/**
 * Reclaim Beacon contract
 */
contract Reclaim {
	struct Witness {
		/** ETH address of the witness */
		address addr;
		/** Host to connect to the witness */
		string host;
	}

	struct Epoch {
		/** Epoch number */
		uint32 id;
		/** when the epoch changed */
		uint32 timestampStart;
		/** when the epoch will change */
		uint32 timestampEnd;
		/** Witnesses for this epoch */
		Witness[] witnesses;
		/**
		 * Minimum number of witnesses
		 * required to create a claim
		 * */
		uint8 minimumWitnessesForClaimCreation;
	}

	struct Proof {
		Claims.ClaimInfo claimInfo;
		Claims.SignedClaim signedClaim;
	}

	/** list of all epochs */
	Epoch[] public epochs;

	/**
	 * duration of each epoch.
	 * is not a hard duration, but useful for
	 * caching purposes
	 * */
	uint32 public epochDurationS; // 1 day

	/**
	 * current epoch.
	 * starts at 1, so that the first epoch is 1
	 * */
	uint32 public currentEpoch;


	event EpochAdded(Epoch epoch);

	address public owner;

	/**
	 * @notice Calls initialize on the base contracts
	 *
	 * @dev This acts as a constructor for the upgradeable proxy contract
	 */
	constructor() {
		epochDurationS = 1 days;
		currentEpoch = 0;
		owner = msg.sender;
	}

	modifier onlyOwner () {
		require(owner == msg.sender, "Only Owner");
		_;
	}
	// epoch functions ---

	/**
	 * Fetch an epoch
	 * @param epoch the epoch number to fetch;
	 * pass 0 to fetch the current epoch
	 */
	function fetchEpoch(uint32 epoch) public view returns (Epoch memory) {
		if (epoch == 0) {
			return epochs[epochs.length - 1];
		}
		return epochs[epoch - 1];
	}

	/**
	 * Get the witnesses that'll sign the claim
	 */
	function fetchWitnessesForClaim(
		uint32 epoch,
		bytes32 identifier,
		uint32 timestampS
	) public view returns (Witness[] memory) {
		Epoch memory epochData = fetchEpoch(epoch);
		bytes memory completeInput = abi.encodePacked(
			// hex encode bytes
			StringUtils.bytes2str(
				// convert bytes32 to bytes
				abi.encodePacked(identifier)
			),
			"\n",
			StringUtils.uint2str(epoch),
			"\n",
			StringUtils.uint2str(epochData.minimumWitnessesForClaimCreation),
			"\n",
			StringUtils.uint2str(timestampS)
		);
		bytes memory completeHash = abi.encodePacked(keccak256(completeInput));

		Witness[] memory witnessesLeftList = epochData.witnesses;
		Witness[] memory selectedWitnesses = new Witness[](
			epochData.minimumWitnessesForClaimCreation
		);
		uint witnessesLeft = witnessesLeftList.length;

		uint byteOffset = 0;
		for (uint32 i = 0; i < epochData.minimumWitnessesForClaimCreation; i++) {
			uint randomSeed = BytesUtils.bytesToUInt(completeHash, byteOffset);
			uint witnessIndex = randomSeed % witnessesLeft;
			selectedWitnesses[i] = witnessesLeftList[witnessIndex];
			// remove the witness from the list of witnesses
			// we've utilised witness at index "idx"
			// we of course don't want to pick the same witness twice
			// so we remove it from the list of witnesses
			// and reduce the number of witnesses left to pick from
			// since solidity doesn't support "pop()" in memory arrays
			// we swap the last element with the element we want to remove
			witnessesLeftList[witnessIndex] = epochData.witnesses[witnessesLeft - 1];
			byteOffset = (byteOffset + 4) % completeHash.length;
			witnessesLeft -= 1;
		}

		return selectedWitnesses;
	}

	/**
	 * Call the function to assert
	 * the validity of several claims proofs
	 */
	function verifyProof(Proof memory proof) public view {
		// create signed claim using claimData and signature.
		require(proof.signedClaim.signatures.length > 0, "No signatures");
		Claims.SignedClaim memory signed = Claims.SignedClaim(
			proof.signedClaim.claim,
			proof.signedClaim.signatures
		);

		// check if the hash from the claimInfo is equal to the infoHash in the claimData
		bytes32 hashed = Claims.hashClaimInfo(proof.claimInfo);
		require(proof.signedClaim.claim.identifier == hashed);

		// fetch witness list from fetchEpoch(_epoch).witnesses
		Witness[] memory expectedWitnesses = fetchWitnessesForClaim(
			proof.signedClaim.claim.epoch,
			proof.signedClaim.claim.identifier,
			proof.signedClaim.claim.timestampS
		);
		address[] memory signedWitnesses = Claims.recoverSignersOfSignedClaim(signed);
		// check if the number of signatures is equal to the number of witnesses
		require(
			signedWitnesses.length == expectedWitnesses.length,
			"Number of signatures not equal to number of witnesses"
		);

		// Update awaited: more checks on whose signatures can be considered.
		for (uint256 i = 0; i < signed.signatures.length; i++) {
			bool found = false;
			for (uint j = 0; j < expectedWitnesses.length; j++) {
				if (signedWitnesses[i] == expectedWitnesses[j].addr) {
					found = true;
					break;
				}
			}
			require(found, "Signature not appropriate");
		}

		//@TODO: verify zkproof
	}

	// admin functions ---

	/**
	 * @dev Add a new epoch
	 */
	function addNewEpoch(
		Witness[] calldata witnesses,
		uint8 requisiteWitnessesForClaimCreate
	) external onlyOwner {
		if (epochDurationS == 0) {
			epochDurationS = 1 days;
		}
		if (epochs.length > 0) {
			epochs[epochs.length - 1].timestampEnd = uint32(block.timestamp);
		}

		currentEpoch += 1;
		Epoch storage epoch = epochs.push();
		epoch.id = currentEpoch;
		epoch.timestampStart = uint32(block.timestamp);
		epoch.timestampEnd = uint32(block.timestamp + epochDurationS);
		epoch.minimumWitnessesForClaimCreation = requisiteWitnessesForClaimCreate;

		for (uint256 i = 0; i < witnesses.length; i++) {
			epoch.witnesses.push(witnesses[i]);
		}

		emit EpochAdded(epochs[epochs.length - 1]);
	}

	// internal code -----

	function uintDifference(uint256 a, uint256 b) internal pure returns (uint256) {
		if (a > b) {
			return a - b;
		}

		return b - a;
	}
}

File 9 of 10 : StringUtils.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;

/**
 * Utilities for string manipulation & conversion
 */
library StringUtils {
	function address2str(address x) internal pure returns (string memory) {
		bytes memory s = new bytes(40);
		for (uint i = 0; i < 20; i++) {
			bytes1 b = bytes1(uint8(uint(uint160(x)) / (2 ** (8 * (19 - i)))));
			bytes1 hi = bytes1(uint8(b) / 16);
			bytes1 lo = bytes1(uint8(b) - 16 * uint8(hi));
			s[2 * i] = getChar(hi);
			s[2 * i + 1] = getChar(lo);
		}
		return string(abi.encodePacked("0x", s));
	}

	function bytes2str(bytes memory buffer) internal pure returns (string memory) {
		// Fixed buffer size for hexadecimal convertion
		bytes memory converted = new bytes(buffer.length * 2);
		bytes memory _base = "0123456789abcdef";

		for (uint256 i = 0; i < buffer.length; i++) {
			converted[i * 2] = _base[uint8(buffer[i]) / _base.length];
			converted[i * 2 + 1] = _base[uint8(buffer[i]) % _base.length];
		}

		return string(abi.encodePacked("0x", converted));
	}

	function getChar(bytes1 b) internal pure returns (bytes1 c) {
		if (uint8(b) < 10) return bytes1(uint8(b) + 0x30);
		else return bytes1(uint8(b) + 0x57);
	}

	function bool2str(bool _b) internal pure returns (string memory _uintAsString) {
		if (_b) {
			return "true";
		} else {
			return "false";
		}
	}

	function uint2str(uint _i) internal pure returns (string memory _uintAsString) {
		if (_i == 0) {
			return "0";
		}
		uint j = _i;
		uint len;
		while (j != 0) {
			len++;
			j /= 10;
		}
		bytes memory bstr = new bytes(len);
		uint k = len;
		while (_i != 0) {
			k = k - 1;
			uint8 temp = (48 + uint8(_i - (_i / 10) * 10));
			bytes1 b1 = bytes1(temp);
			bstr[k] = b1;
			_i /= 10;
		}
		return string(bstr);
	}

	function areEqual(
		string calldata _a,
		string storage _b
	) internal pure returns (bool) {
		return keccak256(abi.encodePacked((_a))) == keccak256(abi.encodePacked((_b)));
	}

	function areEqual(string memory _a, string memory _b) internal pure returns (bool) {
		return keccak256(abi.encodePacked((_a))) == keccak256(abi.encodePacked((_b)));
	}

	function toLower(string memory str) internal pure returns (string memory) {
		bytes memory bStr = bytes(str);
		bytes memory bLower = new bytes(bStr.length);
		for (uint i = 0; i < bStr.length; i++) {
			// Uppercase character...
			if ((uint8(bStr[i]) >= 65) && (uint8(bStr[i]) <= 90)) {
				// So we add 32 to make it lowercase
				bLower[i] = bytes1(uint8(bStr[i]) + 32);
			} else {
				bLower[i] = bStr[i];
			}
		}
		return string(bLower);
	}

	function substring(
		string memory str,
		uint startIndex,
		uint endIndex
	) internal pure returns (string memory) {
		bytes memory strBytes = bytes(str);
		bytes memory result = new bytes(endIndex - startIndex);
		for (uint i = startIndex; i < endIndex; i++) {
			result[i - startIndex] = strBytes[i];
		}
		return string(result);
	}
}

File 10 of 10 : SubStringUtils.sol
// SPDX-License-Identifier: GPL-3.0

pragma solidity ^0.8.4;

library SubStringUtils {
	function findSubstring(string memory originalString, string memory subString) internal pure returns (int) {
        bytes memory hBytes = bytes(originalString);
        bytes memory nBytes = bytes(subString);
        uint256 lenOriginalString = hBytes.length;
        uint256 lenSubString = nBytes.length;

        for (uint256 i = lenOriginalString - lenSubString; i > 0; i--) {
            bool found = true;
            for (uint256 j = 0; j < lenSubString; j++) {
                if (hBytes[i + j]!= nBytes[j]) {
                    found = false;
                    break;
                }
            }
            if (found) {
                return int(i);
            }
        }
        return -1;
    }

    function substring(string memory str, uint startIndex, uint endIndex) internal pure returns (string memory) {
        bytes memory strBytes = bytes(str);
        bytes memory result = new bytes(endIndex - startIndex);
        for (uint i = startIndex; i < endIndex; i++) {
            result[i - startIndex] = strBytes[i];
        }
        return string(result);
    }
}

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

Contract ABI

[{"inputs":[{"internalType":"contract Reclaim","name":"_reclaimSDK","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"ReentrancyGuardReentrantCall","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"by","type":"address"},{"indexed":false,"internalType":"string","name":"apiUrl","type":"string"},{"indexed":false,"internalType":"uint256","name":"value","type":"uint256"}],"name":"Funded","type":"event"},{"inputs":[{"internalType":"string","name":"apiUrl","type":"string"}],"name":"depositFund","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"string","name":"url","type":"string"},{"internalType":"uint256","name":"tickOffset","type":"uint256"}],"name":"getAPIData","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"url","type":"string"}],"name":"getAPIInfo","outputs":[{"internalType":"string","name":"","type":"string"},{"internalType":"string","name":"","type":"string"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"uint256","name":"","type":"uint256"},{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getAPIListLength","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"id","type":"uint256"}],"name":"getAPIUrlfromID","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"apiURL","type":"string"}],"name":"getDepositedFund","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"reclaimSDK","outputs":[{"internalType":"contract Reclaim","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"string","name":"_apiName","type":"string"},{"internalType":"string","name":"_apiDescription","type":"string"},{"internalType":"string","name":"_url","type":"string"},{"internalType":"uint256","name":"_updateCoolDown","type":"uint256"},{"internalType":"uint256","name":"_submissionReward","type":"uint256"},{"internalType":"uint256","name":"_dataFreshnessWindow","type":"uint256"}],"name":"registerAPI","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"string","name":"_url","type":"string"},{"internalType":"string","name":"_data","type":"string"},{"components":[{"components":[{"internalType":"string","name":"provider","type":"string"},{"internalType":"string","name":"parameters","type":"string"},{"internalType":"string","name":"context","type":"string"}],"internalType":"struct Claims.ClaimInfo","name":"claimInfo","type":"tuple"},{"components":[{"components":[{"internalType":"bytes32","name":"identifier","type":"bytes32"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint32","name":"timestampS","type":"uint32"},{"internalType":"uint32","name":"epoch","type":"uint32"}],"internalType":"struct Claims.CompleteClaimData","name":"claim","type":"tuple"},{"internalType":"bytes[]","name":"signatures","type":"bytes[]"}],"internalType":"struct Claims.SignedClaim","name":"signedClaim","type":"tuple"}],"internalType":"struct Reclaim.Proof","name":"proof","type":"tuple"}],"name":"submitData","outputs":[],"stateMutability":"nonpayable","type":"function"}]

608060405234801561001057600080fd5b506040516118e73803806118e783398101604081905261002f91610059565b6001600081905580546001600160a01b0319166001600160a01b0392909216919091179055610089565b60006020828403121561006b57600080fd5b81516001600160a01b038116811461008257600080fd5b9392505050565b61184f806100986000396000f3fe6080604052600436106100865760003560e01c80638eebd30b116100595780638eebd30b14610138578063a27f21f914610158578063e849430614610178578063f8e0132914610198578063ff049772146101cd57600080fd5b806320cfd6901461008b5780632eca590c146100a057806339c0f252146100d35780637dc8a02814610100575b600080fd5b61009e610099366004610faf565b6101e2565b005b3480156100ac57600080fd5b506100c06100bb366004610faf565b610254565b6040519081526020015b60405180910390f35b3480156100df57600080fd5b506100f36100ee366004610fec565b61027c565b6040516100ca9190611055565b34801561010c57600080fd5b50600154610120906001600160a01b031681565b6040516001600160a01b0390911681526020016100ca565b34801561014457600080fd5b5061009e610153366004611068565b61036f565b34801561016457600080fd5b506100f361017336600461110c565b6104a9565b34801561018457600080fd5b5061009e6101933660046112cb565b61061c565b3480156101a457600080fd5b506101b86101b3366004610faf565b610986565b6040516100ca9998979695949392919061141b565b3480156101d957600080fd5b506002546100c0565b346004826040516101f39190611485565b9081526020016040518091039020600082825461021091906114b7565b90915550506040517fdfa6994609259e6bd6b9688065fbb398e795c7ea01635ffb9b45c4e656b31a8890610249903390849034906114ca565b60405180910390a150565b60006004826040516102669190611485565b9081526020016040518091039020549050919050565b60025460609082106102c25760405162461bcd60e51b815260206004820152600a602482015269125b9d985b1a59081a5960b21b60448201526064015b60405180910390fd5b600282815481106102d5576102d56114fc565b9060005260206000200180546102ea90611512565b80601f016020809104026020016040519081016040528092919081815260200182805461031690611512565b80156103635780601f1061033857610100808354040283529160200191610363565b820191906000526020600020905b81548152906001019060200180831161034657829003601f168201915b50505050509050919050565b856003856040516103809190611485565b9081526040519081900360200190209061039a908261159c565b50846003856040516103ac9190611485565b908152602001604051809103902060010190816103c9919061159c565b50826003856040516103db9190611485565b908152602001604051809103902060030181905550816003856040516104019190611485565b908152602001604051809103902060040181905550806003856040516104279190611485565b908152602001604051809103902060050181905550600060038560405161044e9190611485565b90815260405190819003602001902060029081019190915580546001810182556000919091527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace016104a0858261159c565b50505050505050565b606060016003846040516104bd9190611485565b908152602001604051809103902060020154101561051d5760405162461bcd60e51b815260206004820152601260248201527f4461746120646f65736e2774206578697374000000000000000000000000000060448201526064016102b9565b60038360405161052d9190611485565b908152602001604051809103902060070160006001846003876040516105539190611485565b90815260200160405180910390206002015461056f919061165c565b610579919061165c565b8152602001908152602001600020600001805461059590611512565b80601f01602080910402602001604051908101604052809291908181526020018280546105c190611512565b801561060e5780601f106105e35761010080835404028352916020019161060e565b820191906000526020600020905b8154815290600101906020018083116105f157829003601f168201915b505050505090505b92915050565b610624610b8c565b60006003846040516106369190611485565b90815260200160405180910390209050806005015442610656919061165c565b6020830151516040015163ffffffff16116106be5760405162461bcd60e51b815260206004820152602260248201527f4f7574646174656420646174612063616e6e6f74206265207375626d69747465604482015261321760f11b60648201526084016102b9565b60028101541561074e57428160030154826007016000600185600201546106e5919061165c565b81526020019081526020016000206002015461070191906114b7565b1061074e5760405162461bcd60e51b815260206004820152601d60248201527f546f6f206561726c7920746f207375626d6974206e657720646174612e00000060448201526064016102b9565b80600401544710156107ae5760405162461bcd60e51b815260206004820152602360248201527f42616c616e6365206e6f7420656e6f75676820696e2074686520636f6e74726160448201526231ba1760e91b60648201526084016102b9565b8151602001516001546040516354b0734f60e11b81526001600160a01b039091169063a960e69e906107e490869060040161166f565b60006040518083038186803b1580156107fc57600080fd5b505afa158015610810573d6000803e3d6000fd5b5050505061081f818686610bb6565b60028201546000908152600783016020526040902061083e858261159c565b506002808301805460009081526007850160205260408082204294019390935581548152918220600101805473ffffffffffffffffffffffffffffffffffffffff19163317905580549161089183611786565b91905055506005856040516108a69190611485565b9081526040805160209281900383019020336000908152925281205490036108e0576006820180549060006108da83611786565b91905055505b6005856040516108f09190611485565b90815260408051602092819003830190203360009081529252812080549161091783611786565b9091555050600482015460405160009133918381818185875af1925050503d8060008114610961576040519150601f19603f3d011682016040523d82523d6000602084013e610966565b606091505b505090508061097457600080fd5b5050506109816001600055565b505050565b60608060008060008060008060008060038b6040516109a59190611485565b90815260200160405180910390209050600080600083600201541115610a2f57826007016000600185600201546109dc919061165c565b815260200190815260200160002060010160009054906101000a90046001600160a01b0316915082600701600060018560020154610a1a919061165c565b81526020019081526020016000206002015490505b8260000183600101846003015485600401548660050154876002015488600601548888888054610a5e90611512565b80601f0160208091040260200160405190810160405280929190818152602001828054610a8a90611512565b8015610ad75780601f10610aac57610100808354040283529160200191610ad7565b820191906000526020600020905b815481529060010190602001808311610aba57829003601f168201915b50505050509850878054610aea90611512565b80601f0160208091040260200160405190810160405280929190818152602001828054610b1690611512565b8015610b635780601f10610b3857610100808354040283529160200191610b63565b820191906000526020600020905b815481529060010190602001808311610b4657829003601f168201915b505050505097509b509b509b509b509b509b509b509b509b505050509193959799909294969850565b600260005403610baf57604051633ee5aeb560e01b815260040160405180910390fd5b6002600055565b610be182604051602001610bca919061179f565b60408051601f198184030181529190528490610cdb565b19610c1d5760405162461bcd60e51b815260206004820152600c60248201526b496e76616c69642055524c2160a01b60448201526064016102b9565b6000610c5360405180604001604052806009815260200168113b30b63ab2911d1160b91b81525085610cdb90919063ffffffff16565b610c5e9060096117da565b90508180519060200120610c8182845184610c7991906114b7565b879190610d9f565b8051906020012014610cd55760405162461bcd60e51b815260206004820152600e60248201527f44617461206d69736d617463682100000000000000000000000000000000000060448201526064016102b9565b50505050565b81518151600091849184919084610cf2828461165c565b90505b8015610d9057600160005b83811015610d6957858181518110610d1a57610d1a6114fc565b01602001516001600160f81b03191687610d3483866114b7565b81518110610d4457610d446114fc565b01602001516001600160f81b03191614610d615760009150610d69565b600101610d00565b508015610d7d575094506106169350505050565b5080610d8881611802565b915050610cf5565b50600019979650505050505050565b6060836000610dae858561165c565b67ffffffffffffffff811115610dc657610dc6610e7a565b6040519080825280601f01601f191660200182016040528015610df0576020820181803683370190505b509050845b84811015610e7057828181518110610e0f57610e0f6114fc565b01602001516001600160f81b03191682610e29888461165c565b81518110610e3957610e396114fc565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600101610df5565b5095945050505050565b634e487b7160e01b600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715610eb357610eb3610e7a565b60405290565b6040516080810167ffffffffffffffff81118282101715610eb357610eb3610e7a565b6040516060810167ffffffffffffffff81118282101715610eb357610eb3610e7a565b604051601f8201601f1916810167ffffffffffffffff81118282101715610f2857610f28610e7a565b604052919050565b600067ffffffffffffffff831115610f4a57610f4a610e7a565b610f5d601f8401601f1916602001610eff565b9050828152838383011115610f7157600080fd5b828260208301376000602084830101529392505050565b600082601f830112610f9957600080fd5b610fa883833560208501610f30565b9392505050565b600060208284031215610fc157600080fd5b813567ffffffffffffffff811115610fd857600080fd5b610fe484828501610f88565b949350505050565b600060208284031215610ffe57600080fd5b5035919050565b60005b83811015611020578181015183820152602001611008565b50506000910152565b60008151808452611041816020860160208601611005565b601f01601f19169290920160200192915050565b602081526000610fa86020830184611029565b60008060008060008060c0878903121561108157600080fd5b863567ffffffffffffffff8082111561109957600080fd5b6110a58a838b01610f88565b975060208901359150808211156110bb57600080fd5b6110c78a838b01610f88565b965060408901359150808211156110dd57600080fd5b506110ea89828a01610f88565b945050606087013592506080870135915060a087013590509295509295509295565b6000806040838503121561111f57600080fd5b823567ffffffffffffffff81111561113657600080fd5b61114285828601610f88565b95602094909401359450505050565b803563ffffffff8116811461116557600080fd5b919050565b600082601f83011261117b57600080fd5b8135602067ffffffffffffffff8083111561119857611198610e7a565b8260051b6111a7838201610eff565b93845285810183019383810190888611156111c157600080fd5b84880192505b85831015611212578235848111156111df5760008081fd5b8801603f81018a136111f15760008081fd5b6112028a8783013560408401610f30565b83525091840191908401906111c7565b98975050505050505050565b600081830360a081121561123157600080fd5b611239610e90565b9150608081121561124957600080fd5b50611252610eb9565b8235815260208301356001600160a01b038116811461127057600080fd5b602082015261128160408401611151565b604082015261129260608401611151565b60608201528152608082013567ffffffffffffffff8111156112b357600080fd5b6112bf8482850161116a565b60208301525092915050565b6000806000606084860312156112e057600080fd5b833567ffffffffffffffff808211156112f857600080fd5b61130487838801610f88565b9450602086013591508082111561131a57600080fd5b61132687838801610f88565b9350604086013591508082111561133c57600080fd5b908501906040828803121561135057600080fd5b611358610e90565b82358281111561136757600080fd5b83016060818a03121561137957600080fd5b611381610edc565b81358481111561139057600080fd5b61139c8b828501610f88565b8252506020820135848111156113b157600080fd5b6113bd8b828501610f88565b6020830152506040820135848111156113d557600080fd5b6113e18b828501610f88565b6040830152508252506020830135828111156113fc57600080fd5b6114088982860161121e565b6020830152508093505050509250925092565b600061012080835261142f8184018d611029565b90508281036020840152611443818c611029565b604084019a909a5250506060810196909652608086019490945260a085019290925260c08401526001600160a01b031660e08301526101009091015292915050565b60008251611497818460208701611005565b9190910192915050565b634e487b7160e01b600052601160045260246000fd5b80820180821115610616576106166114a1565b6001600160a01b03841681526060602082015260006114ec6060830185611029565b9050826040830152949350505050565b634e487b7160e01b600052603260045260246000fd5b600181811c9082168061152657607f821691505b60208210810361154657634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115610981576000816000526020600020601f850160051c810160208610156115755750805b601f850160051c820191505b8181101561159457828155600101611581565b505050505050565b815167ffffffffffffffff8111156115b6576115b6610e7a565b6115ca816115c48454611512565b8461154c565b602080601f8311600181146115ff57600084156115e75750858301515b600019600386901b1c1916600185901b178555611594565b600085815260208120601f198616915b8281101561162e5788860151825594840194600190910190840161160f565b508582101561164c5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b81810381811115610616576106166114a1565b600060208083528351604082850152805160608086015261169360c0860182611029565b905082820151605f19808784030160808801526116b08383611029565b925060408401519350808784030160a088015250506116cf8183611029565b91505081850151601f1985830301604086015260a082018151805184526001600160a01b03858201511685850152604081015163ffffffff808216604087015280606084015116606087015250505083820151915060a0608084015280825180835260c08501915060c08160051b8601019250858401935060005b818110156117785760bf19868503018352611766848651611029565b9487019493509186019160010161174a565b509198975050505050505050565b600060018201611798576117986114a1565b5060010190565b66113ab936111d1160c91b815281516000906117c2816007850160208701611005565b601160f91b6007939091019283015250600801919050565b80820182811260008312801582168215821617156117fa576117fa6114a1565b505092915050565b600081611811576118116114a1565b50600019019056fea2646970667358221220b66f7853dae4d771202658baf9c1ac8a7ded862fa83a3258fb53992fb3c2924f64736f6c63430008180033000000000000000000000000460e28f1dbb4ac13e7f6e8d8e97de5bc54c7435e

Deployed Bytecode

0x6080604052600436106100865760003560e01c80638eebd30b116100595780638eebd30b14610138578063a27f21f914610158578063e849430614610178578063f8e0132914610198578063ff049772146101cd57600080fd5b806320cfd6901461008b5780632eca590c146100a057806339c0f252146100d35780637dc8a02814610100575b600080fd5b61009e610099366004610faf565b6101e2565b005b3480156100ac57600080fd5b506100c06100bb366004610faf565b610254565b6040519081526020015b60405180910390f35b3480156100df57600080fd5b506100f36100ee366004610fec565b61027c565b6040516100ca9190611055565b34801561010c57600080fd5b50600154610120906001600160a01b031681565b6040516001600160a01b0390911681526020016100ca565b34801561014457600080fd5b5061009e610153366004611068565b61036f565b34801561016457600080fd5b506100f361017336600461110c565b6104a9565b34801561018457600080fd5b5061009e6101933660046112cb565b61061c565b3480156101a457600080fd5b506101b86101b3366004610faf565b610986565b6040516100ca9998979695949392919061141b565b3480156101d957600080fd5b506002546100c0565b346004826040516101f39190611485565b9081526020016040518091039020600082825461021091906114b7565b90915550506040517fdfa6994609259e6bd6b9688065fbb398e795c7ea01635ffb9b45c4e656b31a8890610249903390849034906114ca565b60405180910390a150565b60006004826040516102669190611485565b9081526020016040518091039020549050919050565b60025460609082106102c25760405162461bcd60e51b815260206004820152600a602482015269125b9d985b1a59081a5960b21b60448201526064015b60405180910390fd5b600282815481106102d5576102d56114fc565b9060005260206000200180546102ea90611512565b80601f016020809104026020016040519081016040528092919081815260200182805461031690611512565b80156103635780601f1061033857610100808354040283529160200191610363565b820191906000526020600020905b81548152906001019060200180831161034657829003601f168201915b50505050509050919050565b856003856040516103809190611485565b9081526040519081900360200190209061039a908261159c565b50846003856040516103ac9190611485565b908152602001604051809103902060010190816103c9919061159c565b50826003856040516103db9190611485565b908152602001604051809103902060030181905550816003856040516104019190611485565b908152602001604051809103902060040181905550806003856040516104279190611485565b908152602001604051809103902060050181905550600060038560405161044e9190611485565b90815260405190819003602001902060029081019190915580546001810182556000919091527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace016104a0858261159c565b50505050505050565b606060016003846040516104bd9190611485565b908152602001604051809103902060020154101561051d5760405162461bcd60e51b815260206004820152601260248201527f4461746120646f65736e2774206578697374000000000000000000000000000060448201526064016102b9565b60038360405161052d9190611485565b908152602001604051809103902060070160006001846003876040516105539190611485565b90815260200160405180910390206002015461056f919061165c565b610579919061165c565b8152602001908152602001600020600001805461059590611512565b80601f01602080910402602001604051908101604052809291908181526020018280546105c190611512565b801561060e5780601f106105e35761010080835404028352916020019161060e565b820191906000526020600020905b8154815290600101906020018083116105f157829003601f168201915b505050505090505b92915050565b610624610b8c565b60006003846040516106369190611485565b90815260200160405180910390209050806005015442610656919061165c565b6020830151516040015163ffffffff16116106be5760405162461bcd60e51b815260206004820152602260248201527f4f7574646174656420646174612063616e6e6f74206265207375626d69747465604482015261321760f11b60648201526084016102b9565b60028101541561074e57428160030154826007016000600185600201546106e5919061165c565b81526020019081526020016000206002015461070191906114b7565b1061074e5760405162461bcd60e51b815260206004820152601d60248201527f546f6f206561726c7920746f207375626d6974206e657720646174612e00000060448201526064016102b9565b80600401544710156107ae5760405162461bcd60e51b815260206004820152602360248201527f42616c616e6365206e6f7420656e6f75676820696e2074686520636f6e74726160448201526231ba1760e91b60648201526084016102b9565b8151602001516001546040516354b0734f60e11b81526001600160a01b039091169063a960e69e906107e490869060040161166f565b60006040518083038186803b1580156107fc57600080fd5b505afa158015610810573d6000803e3d6000fd5b5050505061081f818686610bb6565b60028201546000908152600783016020526040902061083e858261159c565b506002808301805460009081526007850160205260408082204294019390935581548152918220600101805473ffffffffffffffffffffffffffffffffffffffff19163317905580549161089183611786565b91905055506005856040516108a69190611485565b9081526040805160209281900383019020336000908152925281205490036108e0576006820180549060006108da83611786565b91905055505b6005856040516108f09190611485565b90815260408051602092819003830190203360009081529252812080549161091783611786565b9091555050600482015460405160009133918381818185875af1925050503d8060008114610961576040519150601f19603f3d011682016040523d82523d6000602084013e610966565b606091505b505090508061097457600080fd5b5050506109816001600055565b505050565b60608060008060008060008060008060038b6040516109a59190611485565b90815260200160405180910390209050600080600083600201541115610a2f57826007016000600185600201546109dc919061165c565b815260200190815260200160002060010160009054906101000a90046001600160a01b0316915082600701600060018560020154610a1a919061165c565b81526020019081526020016000206002015490505b8260000183600101846003015485600401548660050154876002015488600601548888888054610a5e90611512565b80601f0160208091040260200160405190810160405280929190818152602001828054610a8a90611512565b8015610ad75780601f10610aac57610100808354040283529160200191610ad7565b820191906000526020600020905b815481529060010190602001808311610aba57829003601f168201915b50505050509850878054610aea90611512565b80601f0160208091040260200160405190810160405280929190818152602001828054610b1690611512565b8015610b635780601f10610b3857610100808354040283529160200191610b63565b820191906000526020600020905b815481529060010190602001808311610b4657829003601f168201915b505050505097509b509b509b509b509b509b509b509b509b505050509193959799909294969850565b600260005403610baf57604051633ee5aeb560e01b815260040160405180910390fd5b6002600055565b610be182604051602001610bca919061179f565b60408051601f198184030181529190528490610cdb565b19610c1d5760405162461bcd60e51b815260206004820152600c60248201526b496e76616c69642055524c2160a01b60448201526064016102b9565b6000610c5360405180604001604052806009815260200168113b30b63ab2911d1160b91b81525085610cdb90919063ffffffff16565b610c5e9060096117da565b90508180519060200120610c8182845184610c7991906114b7565b879190610d9f565b8051906020012014610cd55760405162461bcd60e51b815260206004820152600e60248201527f44617461206d69736d617463682100000000000000000000000000000000000060448201526064016102b9565b50505050565b81518151600091849184919084610cf2828461165c565b90505b8015610d9057600160005b83811015610d6957858181518110610d1a57610d1a6114fc565b01602001516001600160f81b03191687610d3483866114b7565b81518110610d4457610d446114fc565b01602001516001600160f81b03191614610d615760009150610d69565b600101610d00565b508015610d7d575094506106169350505050565b5080610d8881611802565b915050610cf5565b50600019979650505050505050565b6060836000610dae858561165c565b67ffffffffffffffff811115610dc657610dc6610e7a565b6040519080825280601f01601f191660200182016040528015610df0576020820181803683370190505b509050845b84811015610e7057828181518110610e0f57610e0f6114fc565b01602001516001600160f81b03191682610e29888461165c565b81518110610e3957610e396114fc565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600101610df5565b5095945050505050565b634e487b7160e01b600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715610eb357610eb3610e7a565b60405290565b6040516080810167ffffffffffffffff81118282101715610eb357610eb3610e7a565b6040516060810167ffffffffffffffff81118282101715610eb357610eb3610e7a565b604051601f8201601f1916810167ffffffffffffffff81118282101715610f2857610f28610e7a565b604052919050565b600067ffffffffffffffff831115610f4a57610f4a610e7a565b610f5d601f8401601f1916602001610eff565b9050828152838383011115610f7157600080fd5b828260208301376000602084830101529392505050565b600082601f830112610f9957600080fd5b610fa883833560208501610f30565b9392505050565b600060208284031215610fc157600080fd5b813567ffffffffffffffff811115610fd857600080fd5b610fe484828501610f88565b949350505050565b600060208284031215610ffe57600080fd5b5035919050565b60005b83811015611020578181015183820152602001611008565b50506000910152565b60008151808452611041816020860160208601611005565b601f01601f19169290920160200192915050565b602081526000610fa86020830184611029565b60008060008060008060c0878903121561108157600080fd5b863567ffffffffffffffff8082111561109957600080fd5b6110a58a838b01610f88565b975060208901359150808211156110bb57600080fd5b6110c78a838b01610f88565b965060408901359150808211156110dd57600080fd5b506110ea89828a01610f88565b945050606087013592506080870135915060a087013590509295509295509295565b6000806040838503121561111f57600080fd5b823567ffffffffffffffff81111561113657600080fd5b61114285828601610f88565b95602094909401359450505050565b803563ffffffff8116811461116557600080fd5b919050565b600082601f83011261117b57600080fd5b8135602067ffffffffffffffff8083111561119857611198610e7a565b8260051b6111a7838201610eff565b93845285810183019383810190888611156111c157600080fd5b84880192505b85831015611212578235848111156111df5760008081fd5b8801603f81018a136111f15760008081fd5b6112028a8783013560408401610f30565b83525091840191908401906111c7565b98975050505050505050565b600081830360a081121561123157600080fd5b611239610e90565b9150608081121561124957600080fd5b50611252610eb9565b8235815260208301356001600160a01b038116811461127057600080fd5b602082015261128160408401611151565b604082015261129260608401611151565b60608201528152608082013567ffffffffffffffff8111156112b357600080fd5b6112bf8482850161116a565b60208301525092915050565b6000806000606084860312156112e057600080fd5b833567ffffffffffffffff808211156112f857600080fd5b61130487838801610f88565b9450602086013591508082111561131a57600080fd5b61132687838801610f88565b9350604086013591508082111561133c57600080fd5b908501906040828803121561135057600080fd5b611358610e90565b82358281111561136757600080fd5b83016060818a03121561137957600080fd5b611381610edc565b81358481111561139057600080fd5b61139c8b828501610f88565b8252506020820135848111156113b157600080fd5b6113bd8b828501610f88565b6020830152506040820135848111156113d557600080fd5b6113e18b828501610f88565b6040830152508252506020830135828111156113fc57600080fd5b6114088982860161121e565b6020830152508093505050509250925092565b600061012080835261142f8184018d611029565b90508281036020840152611443818c611029565b604084019a909a5250506060810196909652608086019490945260a085019290925260c08401526001600160a01b031660e08301526101009091015292915050565b60008251611497818460208701611005565b9190910192915050565b634e487b7160e01b600052601160045260246000fd5b80820180821115610616576106166114a1565b6001600160a01b03841681526060602082015260006114ec6060830185611029565b9050826040830152949350505050565b634e487b7160e01b600052603260045260246000fd5b600181811c9082168061152657607f821691505b60208210810361154657634e487b7160e01b600052602260045260246000fd5b50919050565b601f821115610981576000816000526020600020601f850160051c810160208610156115755750805b601f850160051c820191505b8181101561159457828155600101611581565b505050505050565b815167ffffffffffffffff8111156115b6576115b6610e7a565b6115ca816115c48454611512565b8461154c565b602080601f8311600181146115ff57600084156115e75750858301515b600019600386901b1c1916600185901b178555611594565b600085815260208120601f198616915b8281101561162e5788860151825594840194600190910190840161160f565b508582101561164c5787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b81810381811115610616576106166114a1565b600060208083528351604082850152805160608086015261169360c0860182611029565b905082820151605f19808784030160808801526116b08383611029565b925060408401519350808784030160a088015250506116cf8183611029565b91505081850151601f1985830301604086015260a082018151805184526001600160a01b03858201511685850152604081015163ffffffff808216604087015280606084015116606087015250505083820151915060a0608084015280825180835260c08501915060c08160051b8601019250858401935060005b818110156117785760bf19868503018352611766848651611029565b9487019493509186019160010161174a565b509198975050505050505050565b600060018201611798576117986114a1565b5060010190565b66113ab936111d1160c91b815281516000906117c2816007850160208701611005565b601160f91b6007939091019283015250600801919050565b80820182811260008312801582168215821617156117fa576117fa6114a1565b505092915050565b600081611811576118116114a1565b50600019019056fea2646970667358221220b66f7853dae4d771202658baf9c1ac8a7ded862fa83a3258fb53992fb3c2924f64736f6c63430008180033

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

000000000000000000000000460e28f1dbb4ac13e7f6e8d8e97de5bc54c7435e

-----Decoded View---------------
Arg [0] : _reclaimSDK (address): 0x460E28f1DBb4ac13e7f6E8d8e97DE5bC54c7435e

-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000460e28f1dbb4ac13e7f6e8d8e97de5bc54c7435e


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
[ Download: CSV Export  ]
[ Download: CSV Export  ]

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.