Sepolia Testnet

Contract

0x1016B0e4A594500A11D829DE5F43F1dE4A8507cE

Overview

ETH Balance

0 ETH

Multichain Info

N/A
Transaction Hash
Method
Block
From
To
Submit Data62971892024-07-12 15:47:24154 days ago1720799244IN
0x1016B0e4...E4A8507cE
0 ETH0.002574656.84877365
Submit Data62971872024-07-12 15:47:00154 days ago1720799220IN
0x1016B0e4...E4A8507cE
0 ETH0.00257676.85400819
Submit Data62971722024-07-12 15:43:36154 days ago1720799016IN
0x1016B0e4...E4A8507cE
0 ETH0.000350146.67460298
Submit Data62971722024-07-12 15:43:36154 days ago1720799016IN
0x1016B0e4...E4A8507cE
0 ETH0.002509266.67460298
Submit Data62971692024-07-12 15:42:48154 days ago1720798968IN
0x1016B0e4...E4A8507cE
0 ETH0.002518196.69835394
Submit Data62971652024-07-12 15:42:00154 days ago1720798920IN
0x1016B0e4...E4A8507cE
0 ETH0.002542376.76267557
Submit Data62971512024-07-12 15:38:36154 days ago1720798716IN
0x1016B0e4...E4A8507cE
0 ETH0.002921357.77074689
Submit Data62971462024-07-12 15:37:36154 days ago1720798656IN
0x1016B0e4...E4A8507cE
0 ETH0.002904527.72598736
Submit Data62971112024-07-12 15:30:00154 days ago1720798200IN
0x1016B0e4...E4A8507cE
0 ETH0.002818117.49662356
Submit Data62971092024-07-12 15:29:24154 days ago1720798164IN
0x1016B0e4...E4A8507cE
0 ETH0.002724367.24677076
Submit Data62971062024-07-12 15:28:48154 days ago1720798128IN
0x1016B0e4...E4A8507cE
0 ETH0.002768897.36522943
Submit Data62971042024-07-12 15:28:24154 days ago1720798104IN
0x1016B0e4...E4A8507cE
0 ETH0.002877787.65511435
Submit Data62971022024-07-12 15:28:00154 days ago1720798080IN
0x1016B0e4...E4A8507cE
0 ETH0.002778557.39092214
Submit Data62971002024-07-12 15:27:36154 days ago1720798056IN
0x1016B0e4...E4A8507cE
0 ETH0.000397977.58638905
Submit Data62971002024-07-12 15:27:36154 days ago1720798056IN
0x1016B0e4...E4A8507cE
0 ETH0.002852047.58638905
Submit Data62970932024-07-12 15:26:12154 days ago1720797972IN
0x1016B0e4...E4A8507cE
0 ETH0.002566266.82623082
Submit Data62970892024-07-12 15:25:24154 days ago1720797924IN
0x1016B0e4...E4A8507cE
0 ETH0.002939387.81921915
Submit Data62968072024-07-12 14:25:12154 days ago1720794312IN
0x1016B0e4...E4A8507cE
0 ETH0.003565499.48416127
Submit Data62967402024-07-12 14:10:12154 days ago1720793412IN
0x1016B0e4...E4A8507cE
0 ETH0.003567829.49037095
Submit Data62967372024-07-12 14:09:36154 days ago1720793376IN
0x1016B0e4...E4A8507cE
0 ETH0.003448299.17241713
Submit Data62967342024-07-12 14:09:00154 days ago1720793340IN
0x1016B0e4...E4A8507cE
0 ETH0.0038162810.15189803
Submit Data62967312024-07-12 14:08:24154 days ago1720793304IN
0x1016B0e4...E4A8507cE
0 ETH0.0038990110.37133098
Submit Data62967292024-07-12 14:07:48154 days ago1720793268IN
0x1016B0e4...E4A8507cE
0 ETH0.003581439.52656518
Submit Data62967262024-07-12 14:07:12154 days ago1720793232IN
0x1016B0e4...E4A8507cE
0 ETH0.0038477510.2349645
Submit Data62967252024-07-12 14:07:00154 days ago1720793220IN
0x1016B0e4...E4A8507cE
0 ETH0.000487849.29956873
View all transactions

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
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 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":[],"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"}]

608060405234801561001057600080fd5b5060405161189338038061189383398101604081905261002f91610059565b6001600081905580546001600160a01b0319166001600160a01b0392909216919091179055610089565b60006020828403121561006b57600080fd5b81516001600160a01b038116811461008257600080fd5b9392505050565b6117fb806100986000396000f3fe60806040526004361061007b5760003560e01c8063a27f21f91161004e578063a27f21f914610123578063e849430614610143578063f8e0132914610163578063ff0497721461019857600080fd5b806320cfd6901461008057806339c0f252146100955780637dc8a028146100cb5780638eebd30b14610103575b600080fd5b61009361008e366004610f5b565b6101b6565b005b3480156100a157600080fd5b506100b56100b0366004610f98565b610228565b6040516100c29190611001565b60405180910390f35b3480156100d757600080fd5b506001546100eb906001600160a01b031681565b6040516001600160a01b0390911681526020016100c2565b34801561010f57600080fd5b5061009361011e366004611014565b61031b565b34801561012f57600080fd5b506100b561013e3660046110b8565b610455565b34801561014f57600080fd5b5061009361015e366004611277565b6105c8565b34801561016f57600080fd5b5061018361017e366004610f5b565b610932565b6040516100c2999897969594939291906113c7565b3480156101a457600080fd5b506002546040519081526020016100c2565b346004826040516101c79190611431565b908152602001604051809103902060008282546101e49190611463565b90915550506040517fdfa6994609259e6bd6b9688065fbb398e795c7ea01635ffb9b45c4e656b31a889061021d90339084903490611476565b60405180910390a150565b600254606090821061026e5760405162461bcd60e51b815260206004820152600a602482015269125b9d985b1a59081a5960b21b60448201526064015b60405180910390fd5b60028281548110610281576102816114a8565b906000526020600020018054610296906114be565b80601f01602080910402602001604051908101604052809291908181526020018280546102c2906114be565b801561030f5780601f106102e45761010080835404028352916020019161030f565b820191906000526020600020905b8154815290600101906020018083116102f257829003601f168201915b50505050509050919050565b8560038560405161032c9190611431565b908152604051908190036020019020906103469082611548565b50846003856040516103589190611431565b908152602001604051809103902060010190816103759190611548565b50826003856040516103879190611431565b908152602001604051809103902060030181905550816003856040516103ad9190611431565b908152602001604051809103902060040181905550806003856040516103d39190611431565b90815260200160405180910390206005018190555060006003856040516103fa9190611431565b90815260405190819003602001902060029081019190915580546001810182556000919091527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace0161044c8582611548565b50505050505050565b606060016003846040516104699190611431565b90815260200160405180910390206002015410156104c95760405162461bcd60e51b815260206004820152601260248201527f4461746120646f65736e277420657869737400000000000000000000000000006044820152606401610265565b6003836040516104d99190611431565b908152602001604051809103902060070160006001846003876040516104ff9190611431565b90815260200160405180910390206002015461051b9190611608565b6105259190611608565b81526020019081526020016000206000018054610541906114be565b80601f016020809104026020016040519081016040528092919081815260200182805461056d906114be565b80156105ba5780601f1061058f576101008083540402835291602001916105ba565b820191906000526020600020905b81548152906001019060200180831161059d57829003601f168201915b505050505090505b92915050565b6105d0610b38565b60006003846040516105e29190611431565b908152602001604051809103902090508060050154426106029190611608565b6020830151516040015163ffffffff161161066a5760405162461bcd60e51b815260206004820152602260248201527f4f7574646174656420646174612063616e6e6f74206265207375626d69747465604482015261321760f11b6064820152608401610265565b6002810154156106fa57428160030154826007016000600185600201546106919190611608565b8152602001908152602001600020600201546106ad9190611463565b106106fa5760405162461bcd60e51b815260206004820152601d60248201527f546f6f206561726c7920746f207375626d6974206e657720646174612e0000006044820152606401610265565b806004015447101561075a5760405162461bcd60e51b815260206004820152602360248201527f42616c616e6365206e6f7420656e6f75676820696e2074686520636f6e74726160448201526231ba1760e91b6064820152608401610265565b8151602001516001546040516354b0734f60e11b81526001600160a01b039091169063a960e69e9061079090869060040161161b565b60006040518083038186803b1580156107a857600080fd5b505afa1580156107bc573d6000803e3d6000fd5b505050506107cb818686610b62565b6002820154600090815260078301602052604090206107ea8582611548565b506002808301805460009081526007850160205260408082204294019390935581548152918220600101805473ffffffffffffffffffffffffffffffffffffffff19163317905580549161083d83611732565b91905055506005856040516108529190611431565b90815260408051602092819003830190203360009081529252812054900361088c5760068201805490600061088683611732565b91905055505b60058560405161089c9190611431565b9081526040805160209281900383019020336000908152925281208054916108c383611732565b9091555050600482015460405160009133918381818185875af1925050503d806000811461090d576040519150601f19603f3d011682016040523d82523d6000602084013e610912565b606091505b505090508061092057600080fd5b50505061092d6001600055565b505050565b60608060008060008060008060008060038b6040516109519190611431565b908152602001604051809103902090506000806000836002015411156109db57826007016000600185600201546109889190611608565b815260200190815260200160002060010160009054906101000a90046001600160a01b03169150826007016000600185600201546109c69190611608565b81526020019081526020016000206002015490505b8260000183600101846003015485600401548660050154876002015488600601548888888054610a0a906114be565b80601f0160208091040260200160405190810160405280929190818152602001828054610a36906114be565b8015610a835780601f10610a5857610100808354040283529160200191610a83565b820191906000526020600020905b815481529060010190602001808311610a6657829003601f168201915b50505050509850878054610a96906114be565b80601f0160208091040260200160405190810160405280929190818152602001828054610ac2906114be565b8015610b0f5780601f10610ae457610100808354040283529160200191610b0f565b820191906000526020600020905b815481529060010190602001808311610af257829003601f168201915b505050505097509b509b509b509b509b509b509b509b509b505050509193959799909294969850565b600260005403610b5b57604051633ee5aeb560e01b815260040160405180910390fd5b6002600055565b610b8d82604051602001610b76919061174b565b60408051601f198184030181529190528490610c87565b19610bc95760405162461bcd60e51b815260206004820152600c60248201526b496e76616c69642055524c2160a01b6044820152606401610265565b6000610bff60405180604001604052806009815260200168113b30b63ab2911d1160b91b81525085610c8790919063ffffffff16565b610c0a906009611786565b90508180519060200120610c2d82845184610c259190611463565b879190610d4b565b8051906020012014610c815760405162461bcd60e51b815260206004820152600e60248201527f44617461206d69736d61746368210000000000000000000000000000000000006044820152606401610265565b50505050565b81518151600091849184919084610c9e8284611608565b90505b8015610d3c57600160005b83811015610d1557858181518110610cc657610cc66114a8565b01602001516001600160f81b03191687610ce08386611463565b81518110610cf057610cf06114a8565b01602001516001600160f81b03191614610d0d5760009150610d15565b600101610cac565b508015610d29575094506105c29350505050565b5080610d34816117ae565b915050610ca1565b50600019979650505050505050565b6060836000610d5a8585611608565b67ffffffffffffffff811115610d7257610d72610e26565b6040519080825280601f01601f191660200182016040528015610d9c576020820181803683370190505b509050845b84811015610e1c57828181518110610dbb57610dbb6114a8565b01602001516001600160f81b03191682610dd58884611608565b81518110610de557610de56114a8565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600101610da1565b5095945050505050565b634e487b7160e01b600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715610e5f57610e5f610e26565b60405290565b6040516080810167ffffffffffffffff81118282101715610e5f57610e5f610e26565b6040516060810167ffffffffffffffff81118282101715610e5f57610e5f610e26565b604051601f8201601f1916810167ffffffffffffffff81118282101715610ed457610ed4610e26565b604052919050565b600067ffffffffffffffff831115610ef657610ef6610e26565b610f09601f8401601f1916602001610eab565b9050828152838383011115610f1d57600080fd5b828260208301376000602084830101529392505050565b600082601f830112610f4557600080fd5b610f5483833560208501610edc565b9392505050565b600060208284031215610f6d57600080fd5b813567ffffffffffffffff811115610f8457600080fd5b610f9084828501610f34565b949350505050565b600060208284031215610faa57600080fd5b5035919050565b60005b83811015610fcc578181015183820152602001610fb4565b50506000910152565b60008151808452610fed816020860160208601610fb1565b601f01601f19169290920160200192915050565b602081526000610f546020830184610fd5565b60008060008060008060c0878903121561102d57600080fd5b863567ffffffffffffffff8082111561104557600080fd5b6110518a838b01610f34565b9750602089013591508082111561106757600080fd5b6110738a838b01610f34565b9650604089013591508082111561108957600080fd5b5061109689828a01610f34565b945050606087013592506080870135915060a087013590509295509295509295565b600080604083850312156110cb57600080fd5b823567ffffffffffffffff8111156110e257600080fd5b6110ee85828601610f34565b95602094909401359450505050565b803563ffffffff8116811461111157600080fd5b919050565b600082601f83011261112757600080fd5b8135602067ffffffffffffffff8083111561114457611144610e26565b8260051b611153838201610eab565b938452858101830193838101908886111561116d57600080fd5b84880192505b858310156111be5782358481111561118b5760008081fd5b8801603f81018a1361119d5760008081fd5b6111ae8a8783013560408401610edc565b8352509184019190840190611173565b98975050505050505050565b600081830360a08112156111dd57600080fd5b6111e5610e3c565b915060808112156111f557600080fd5b506111fe610e65565b8235815260208301356001600160a01b038116811461121c57600080fd5b602082015261122d604084016110fd565b604082015261123e606084016110fd565b60608201528152608082013567ffffffffffffffff81111561125f57600080fd5b61126b84828501611116565b60208301525092915050565b60008060006060848603121561128c57600080fd5b833567ffffffffffffffff808211156112a457600080fd5b6112b087838801610f34565b945060208601359150808211156112c657600080fd5b6112d287838801610f34565b935060408601359150808211156112e857600080fd5b90850190604082880312156112fc57600080fd5b611304610e3c565b82358281111561131357600080fd5b83016060818a03121561132557600080fd5b61132d610e88565b81358481111561133c57600080fd5b6113488b828501610f34565b82525060208201358481111561135d57600080fd5b6113698b828501610f34565b60208301525060408201358481111561138157600080fd5b61138d8b828501610f34565b6040830152508252506020830135828111156113a857600080fd5b6113b4898286016111ca565b6020830152508093505050509250925092565b60006101208083526113db8184018d610fd5565b905082810360208401526113ef818c610fd5565b604084019a909a5250506060810196909652608086019490945260a085019290925260c08401526001600160a01b031660e08301526101009091015292915050565b60008251611443818460208701610fb1565b9190910192915050565b634e487b7160e01b600052601160045260246000fd5b808201808211156105c2576105c261144d565b6001600160a01b03841681526060602082015260006114986060830185610fd5565b9050826040830152949350505050565b634e487b7160e01b600052603260045260246000fd5b600181811c908216806114d257607f821691505b6020821081036114f257634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111561092d576000816000526020600020601f850160051c810160208610156115215750805b601f850160051c820191505b818110156115405782815560010161152d565b505050505050565b815167ffffffffffffffff81111561156257611562610e26565b6115768161157084546114be565b846114f8565b602080601f8311600181146115ab57600084156115935750858301515b600019600386901b1c1916600185901b178555611540565b600085815260208120601f198616915b828110156115da578886015182559484019460019091019084016115bb565b50858210156115f85787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b818103818111156105c2576105c261144d565b600060208083528351604082850152805160608086015261163f60c0860182610fd5565b905082820151605f198087840301608088015261165c8383610fd5565b925060408401519350808784030160a0880152505061167b8183610fd5565b91505081850151601f1985830301604086015260a082018151805184526001600160a01b03858201511685850152604081015163ffffffff808216604087015280606084015116606087015250505083820151915060a0608084015280825180835260c08501915060c08160051b8601019250858401935060005b818110156117245760bf19868503018352611712848651610fd5565b948701949350918601916001016116f6565b509198975050505050505050565b6000600182016117445761174461144d565b5060010190565b66113ab936111d1160c91b8152815160009061176e816007850160208701610fb1565b601160f91b6007939091019283015250600801919050565b80820182811260008312801582168215821617156117a6576117a661144d565b505092915050565b6000816117bd576117bd61144d565b50600019019056fea2646970667358221220e2bd47ccb5e0154fd4ccd06e2e2130d1d0b04ba76273142897cba9829583f82d64736f6c63430008180033000000000000000000000000460e28f1dbb4ac13e7f6e8d8e97de5bc54c7435e

Deployed Bytecode

0x60806040526004361061007b5760003560e01c8063a27f21f91161004e578063a27f21f914610123578063e849430614610143578063f8e0132914610163578063ff0497721461019857600080fd5b806320cfd6901461008057806339c0f252146100955780637dc8a028146100cb5780638eebd30b14610103575b600080fd5b61009361008e366004610f5b565b6101b6565b005b3480156100a157600080fd5b506100b56100b0366004610f98565b610228565b6040516100c29190611001565b60405180910390f35b3480156100d757600080fd5b506001546100eb906001600160a01b031681565b6040516001600160a01b0390911681526020016100c2565b34801561010f57600080fd5b5061009361011e366004611014565b61031b565b34801561012f57600080fd5b506100b561013e3660046110b8565b610455565b34801561014f57600080fd5b5061009361015e366004611277565b6105c8565b34801561016f57600080fd5b5061018361017e366004610f5b565b610932565b6040516100c2999897969594939291906113c7565b3480156101a457600080fd5b506002546040519081526020016100c2565b346004826040516101c79190611431565b908152602001604051809103902060008282546101e49190611463565b90915550506040517fdfa6994609259e6bd6b9688065fbb398e795c7ea01635ffb9b45c4e656b31a889061021d90339084903490611476565b60405180910390a150565b600254606090821061026e5760405162461bcd60e51b815260206004820152600a602482015269125b9d985b1a59081a5960b21b60448201526064015b60405180910390fd5b60028281548110610281576102816114a8565b906000526020600020018054610296906114be565b80601f01602080910402602001604051908101604052809291908181526020018280546102c2906114be565b801561030f5780601f106102e45761010080835404028352916020019161030f565b820191906000526020600020905b8154815290600101906020018083116102f257829003601f168201915b50505050509050919050565b8560038560405161032c9190611431565b908152604051908190036020019020906103469082611548565b50846003856040516103589190611431565b908152602001604051809103902060010190816103759190611548565b50826003856040516103879190611431565b908152602001604051809103902060030181905550816003856040516103ad9190611431565b908152602001604051809103902060040181905550806003856040516103d39190611431565b90815260200160405180910390206005018190555060006003856040516103fa9190611431565b90815260405190819003602001902060029081019190915580546001810182556000919091527f405787fa12a823e0f2b7631cc41b3ba8828b3321ca811111fa75cd3aa3bb5ace0161044c8582611548565b50505050505050565b606060016003846040516104699190611431565b90815260200160405180910390206002015410156104c95760405162461bcd60e51b815260206004820152601260248201527f4461746120646f65736e277420657869737400000000000000000000000000006044820152606401610265565b6003836040516104d99190611431565b908152602001604051809103902060070160006001846003876040516104ff9190611431565b90815260200160405180910390206002015461051b9190611608565b6105259190611608565b81526020019081526020016000206000018054610541906114be565b80601f016020809104026020016040519081016040528092919081815260200182805461056d906114be565b80156105ba5780601f1061058f576101008083540402835291602001916105ba565b820191906000526020600020905b81548152906001019060200180831161059d57829003601f168201915b505050505090505b92915050565b6105d0610b38565b60006003846040516105e29190611431565b908152602001604051809103902090508060050154426106029190611608565b6020830151516040015163ffffffff161161066a5760405162461bcd60e51b815260206004820152602260248201527f4f7574646174656420646174612063616e6e6f74206265207375626d69747465604482015261321760f11b6064820152608401610265565b6002810154156106fa57428160030154826007016000600185600201546106919190611608565b8152602001908152602001600020600201546106ad9190611463565b106106fa5760405162461bcd60e51b815260206004820152601d60248201527f546f6f206561726c7920746f207375626d6974206e657720646174612e0000006044820152606401610265565b806004015447101561075a5760405162461bcd60e51b815260206004820152602360248201527f42616c616e6365206e6f7420656e6f75676820696e2074686520636f6e74726160448201526231ba1760e91b6064820152608401610265565b8151602001516001546040516354b0734f60e11b81526001600160a01b039091169063a960e69e9061079090869060040161161b565b60006040518083038186803b1580156107a857600080fd5b505afa1580156107bc573d6000803e3d6000fd5b505050506107cb818686610b62565b6002820154600090815260078301602052604090206107ea8582611548565b506002808301805460009081526007850160205260408082204294019390935581548152918220600101805473ffffffffffffffffffffffffffffffffffffffff19163317905580549161083d83611732565b91905055506005856040516108529190611431565b90815260408051602092819003830190203360009081529252812054900361088c5760068201805490600061088683611732565b91905055505b60058560405161089c9190611431565b9081526040805160209281900383019020336000908152925281208054916108c383611732565b9091555050600482015460405160009133918381818185875af1925050503d806000811461090d576040519150601f19603f3d011682016040523d82523d6000602084013e610912565b606091505b505090508061092057600080fd5b50505061092d6001600055565b505050565b60608060008060008060008060008060038b6040516109519190611431565b908152602001604051809103902090506000806000836002015411156109db57826007016000600185600201546109889190611608565b815260200190815260200160002060010160009054906101000a90046001600160a01b03169150826007016000600185600201546109c69190611608565b81526020019081526020016000206002015490505b8260000183600101846003015485600401548660050154876002015488600601548888888054610a0a906114be565b80601f0160208091040260200160405190810160405280929190818152602001828054610a36906114be565b8015610a835780601f10610a5857610100808354040283529160200191610a83565b820191906000526020600020905b815481529060010190602001808311610a6657829003601f168201915b50505050509850878054610a96906114be565b80601f0160208091040260200160405190810160405280929190818152602001828054610ac2906114be565b8015610b0f5780601f10610ae457610100808354040283529160200191610b0f565b820191906000526020600020905b815481529060010190602001808311610af257829003601f168201915b505050505097509b509b509b509b509b509b509b509b509b505050509193959799909294969850565b600260005403610b5b57604051633ee5aeb560e01b815260040160405180910390fd5b6002600055565b610b8d82604051602001610b76919061174b565b60408051601f198184030181529190528490610c87565b19610bc95760405162461bcd60e51b815260206004820152600c60248201526b496e76616c69642055524c2160a01b6044820152606401610265565b6000610bff60405180604001604052806009815260200168113b30b63ab2911d1160b91b81525085610c8790919063ffffffff16565b610c0a906009611786565b90508180519060200120610c2d82845184610c259190611463565b879190610d4b565b8051906020012014610c815760405162461bcd60e51b815260206004820152600e60248201527f44617461206d69736d61746368210000000000000000000000000000000000006044820152606401610265565b50505050565b81518151600091849184919084610c9e8284611608565b90505b8015610d3c57600160005b83811015610d1557858181518110610cc657610cc66114a8565b01602001516001600160f81b03191687610ce08386611463565b81518110610cf057610cf06114a8565b01602001516001600160f81b03191614610d0d5760009150610d15565b600101610cac565b508015610d29575094506105c29350505050565b5080610d34816117ae565b915050610ca1565b50600019979650505050505050565b6060836000610d5a8585611608565b67ffffffffffffffff811115610d7257610d72610e26565b6040519080825280601f01601f191660200182016040528015610d9c576020820181803683370190505b509050845b84811015610e1c57828181518110610dbb57610dbb6114a8565b01602001516001600160f81b03191682610dd58884611608565b81518110610de557610de56114a8565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a905350600101610da1565b5095945050505050565b634e487b7160e01b600052604160045260246000fd5b6040805190810167ffffffffffffffff81118282101715610e5f57610e5f610e26565b60405290565b6040516080810167ffffffffffffffff81118282101715610e5f57610e5f610e26565b6040516060810167ffffffffffffffff81118282101715610e5f57610e5f610e26565b604051601f8201601f1916810167ffffffffffffffff81118282101715610ed457610ed4610e26565b604052919050565b600067ffffffffffffffff831115610ef657610ef6610e26565b610f09601f8401601f1916602001610eab565b9050828152838383011115610f1d57600080fd5b828260208301376000602084830101529392505050565b600082601f830112610f4557600080fd5b610f5483833560208501610edc565b9392505050565b600060208284031215610f6d57600080fd5b813567ffffffffffffffff811115610f8457600080fd5b610f9084828501610f34565b949350505050565b600060208284031215610faa57600080fd5b5035919050565b60005b83811015610fcc578181015183820152602001610fb4565b50506000910152565b60008151808452610fed816020860160208601610fb1565b601f01601f19169290920160200192915050565b602081526000610f546020830184610fd5565b60008060008060008060c0878903121561102d57600080fd5b863567ffffffffffffffff8082111561104557600080fd5b6110518a838b01610f34565b9750602089013591508082111561106757600080fd5b6110738a838b01610f34565b9650604089013591508082111561108957600080fd5b5061109689828a01610f34565b945050606087013592506080870135915060a087013590509295509295509295565b600080604083850312156110cb57600080fd5b823567ffffffffffffffff8111156110e257600080fd5b6110ee85828601610f34565b95602094909401359450505050565b803563ffffffff8116811461111157600080fd5b919050565b600082601f83011261112757600080fd5b8135602067ffffffffffffffff8083111561114457611144610e26565b8260051b611153838201610eab565b938452858101830193838101908886111561116d57600080fd5b84880192505b858310156111be5782358481111561118b5760008081fd5b8801603f81018a1361119d5760008081fd5b6111ae8a8783013560408401610edc565b8352509184019190840190611173565b98975050505050505050565b600081830360a08112156111dd57600080fd5b6111e5610e3c565b915060808112156111f557600080fd5b506111fe610e65565b8235815260208301356001600160a01b038116811461121c57600080fd5b602082015261122d604084016110fd565b604082015261123e606084016110fd565b60608201528152608082013567ffffffffffffffff81111561125f57600080fd5b61126b84828501611116565b60208301525092915050565b60008060006060848603121561128c57600080fd5b833567ffffffffffffffff808211156112a457600080fd5b6112b087838801610f34565b945060208601359150808211156112c657600080fd5b6112d287838801610f34565b935060408601359150808211156112e857600080fd5b90850190604082880312156112fc57600080fd5b611304610e3c565b82358281111561131357600080fd5b83016060818a03121561132557600080fd5b61132d610e88565b81358481111561133c57600080fd5b6113488b828501610f34565b82525060208201358481111561135d57600080fd5b6113698b828501610f34565b60208301525060408201358481111561138157600080fd5b61138d8b828501610f34565b6040830152508252506020830135828111156113a857600080fd5b6113b4898286016111ca565b6020830152508093505050509250925092565b60006101208083526113db8184018d610fd5565b905082810360208401526113ef818c610fd5565b604084019a909a5250506060810196909652608086019490945260a085019290925260c08401526001600160a01b031660e08301526101009091015292915050565b60008251611443818460208701610fb1565b9190910192915050565b634e487b7160e01b600052601160045260246000fd5b808201808211156105c2576105c261144d565b6001600160a01b03841681526060602082015260006114986060830185610fd5565b9050826040830152949350505050565b634e487b7160e01b600052603260045260246000fd5b600181811c908216806114d257607f821691505b6020821081036114f257634e487b7160e01b600052602260045260246000fd5b50919050565b601f82111561092d576000816000526020600020601f850160051c810160208610156115215750805b601f850160051c820191505b818110156115405782815560010161152d565b505050505050565b815167ffffffffffffffff81111561156257611562610e26565b6115768161157084546114be565b846114f8565b602080601f8311600181146115ab57600084156115935750858301515b600019600386901b1c1916600185901b178555611540565b600085815260208120601f198616915b828110156115da578886015182559484019460019091019084016115bb565b50858210156115f85787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b818103818111156105c2576105c261144d565b600060208083528351604082850152805160608086015261163f60c0860182610fd5565b905082820151605f198087840301608088015261165c8383610fd5565b925060408401519350808784030160a0880152505061167b8183610fd5565b91505081850151601f1985830301604086015260a082018151805184526001600160a01b03858201511685850152604081015163ffffffff808216604087015280606084015116606087015250505083820151915060a0608084015280825180835260c08501915060c08160051b8601019250858401935060005b818110156117245760bf19868503018352611712848651610fd5565b948701949350918601916001016116f6565b509198975050505050505050565b6000600182016117445761174461144d565b5060010190565b66113ab936111d1160c91b8152815160009061176e816007850160208701610fb1565b601160f91b6007939091019283015250600801919050565b80820182811260008312801582168215821617156117a6576117a661144d565b505092915050565b6000816117bd576117bd61144d565b50600019019056fea2646970667358221220e2bd47ccb5e0154fd4ccd06e2e2130d1d0b04ba76273142897cba9829583f82d64736f6c63430008180033

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  ]

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.