Source Code
Overview
SOPH Balance
More Info
ContractCreator
Multichain Info
N/A
Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
---|---|---|---|---|---|---|---|---|---|
Latest 3 internal transactions
Advanced mode:
Parent Transaction Hash | Block | From | To | |||
---|---|---|---|---|---|---|
844126 | 4 days ago | Contract Creation | 0 SOPH | |||
844126 | 4 days ago | 0 SOPH | ||||
844126 | 4 days ago | Contract Creation | 0 SOPH |
Loading...
Loading
This contract may be a proxy contract. Click on More Options and select Is this a proxy? to confirm and enable the "Read as Proxy" & "Write as Proxy" tabs.
Similar Match Source Code This contract matches the deployed Bytecode of the Source Code for Contract 0x52d965a9...0C57371ab The constructor portion of the code might be different and could alter the actual behaviour of the contract
Contract Name:
Reclaim
Compiler Version
v0.8.24+commit.e11b9ed9
ZkSolc Version
v1.5.12
Optimization Enabled:
Yes with Mode 3
Other Settings:
paris EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; import "./Claims.sol"; import "./Random.sol"; import "./StringUtils.sol"; import "./BytesUtils.sol"; import "./ProofStorage.sol"; // import "hardhat/console.sol"; /** * @title IProofStorage * @dev Interface for the ProofStorage contract that allows storing and retrieving proofs. * A proof is represented by a claim identifier and the corresponding proof data. */ // interface IProofStorage { // /** // * @dev Structure to store proof details. // * @param claimIdentifier A unique identifier for the claim. // * @param data The proof data associated with the claim. // */ // struct Proof { // bytes32 claimIdentifier; // Unique identifier for the claim // bytes data; // Data representing the proof for the claim // } // /** // * @dev Stores a proof in the contract. // * @param claimIdentifier The unique identifier for the claim. // * @param data The proof data to be stored. // * @notice This function is intended to be called by external contracts or addresses // * to store proofs in the implementing contract. // */ // function storeProof(bytes32 claimIdentifier, bytes memory data) external; // /** // * @dev Retrieves a stored proof by its claim identifier. // * @param claimIdentifier The unique identifier for the claim. // * @return The proof associated with the given claim identifier. // * @notice This function allows anyone to retrieve the proof data associated with a claim identifier. // */ // function getProof(bytes32 claimIdentifier) external view returns (Proof memory); // } /** * 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; /** * current epoch. * starts at 1, so that the first epoch is 1 * */ uint32 public currentEpoch; /** * Declaring an instance of the ProofStorage interface * */ ProofStorage public proofStorage; event EpochAdded(Epoch epoch); address public owner; /** * Constructor to initialize the Reclaim contract * @notice Calls initialize on the base contracts */ constructor() { epochDurationS = 1 days; currentEpoch = 0; owner = msg.sender; proofStorage = new ProofStorage(address(this)); } 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( StringUtils.bytes2str(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 * and store them on ProofStorage contract */ function verifyProof(Proof memory proof) public { // 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, "Claim identifier mismatch"); // 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"); for (uint256 i = 0; i < signedWitnesses.length; i++) { for (uint256 j = 0; j < signedWitnesses.length; j++) { if (i == j) continue; require(signedWitnesses[i] != signedWitnesses[j], "Duplicated Signatures Found"); } } // 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"); } // Storing the proof in the ProofStorage contract after verification proofStorage.storeProof(proof.signedClaim.claim.identifier, abi.encode(proof)); } // 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; } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; 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); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; // 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))); } }
// SPDX-License-Identifier: MIT pragma solidity ^0.8.24; import {ERC725Y} from "@erc725/smart-contracts/contracts/ERC725Y.sol"; /** * @title ProofStorage * @dev A contract that stores proofs, which are key-value pairs of claim identifiers and proof data. * This contract inherits from ERC725Y to leverage its key-value store functionalities. */ contract ProofStorage is ERC725Y { // Address of the Reclaim contract that is authorized to store proofs. address public Reclaim; /** * @dev Initializes the contract setting the owner of the ERC725Y key-value store. * @param newOwner The address of the new owner of the contract. */ constructor(address newOwner) ERC725Y(newOwner) {} /** * @dev Structure to store proof details. * @param claimIdentifier A unique identifier for the claim. * @param data The proof data associated with the claim. */ struct Proof { bytes32 claimIdentifier; bytes data; } // Event emitted when a proof is stored. event ProofStored(bytes32 indexed claimIdentifier, bytes data); /** * @dev Stores a proof in the contract. * This function can be called by external contracts or addresses. * @param claimIdentifier The unique identifier for the claim. * @param data The proof data to be stored. */ function storeProof(bytes32 claimIdentifier, bytes memory data) external { // Store the proof with ERC725 setData(claimIdentifier, data); // Emit the ProofStored event to log the storage operation emit ProofStored(claimIdentifier, data); } /** * @dev Retrieves a stored proof by its claim identifier. * @param claimIdentifier The unique identifier for the claim. * @return proof associated with the given claim identifier. */ function getProof(bytes32 claimIdentifier) external view returns (bytes memory) { // Return the proof corresponding to the claim identifier return getData(claimIdentifier); } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; /** * 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; } }
// SPDX-License-Identifier: MIT pragma solidity 0.8.24; /** * 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); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/cryptography/ECDSA.sol) pragma solidity ^0.8.0; import "../Strings.sol"; /** * @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, InvalidSignatureV // Deprecated in v4.8 } function _throwError(RecoverError error) private pure { if (error == RecoverError.NoError) { return; // no error: do nothing } else if (error == RecoverError.InvalidSignature) { revert("ECDSA: invalid signature"); } else if (error == RecoverError.InvalidSignatureLength) { revert("ECDSA: invalid signature length"); } else if (error == RecoverError.InvalidSignatureS) { revert("ECDSA: invalid signature 's' value"); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature` or error string. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode 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 {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] * * _Available since v4.3._ */ function tryRecover(bytes32 hash, bytes memory signature) internal pure returns (address, RecoverError) { 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); } } /** * @dev Returns the address that signed a hashed message (`hash`) with * `signature`. This address can then be used for verification purposes. * * The `ecrecover` EVM opcode 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 {toEthSignedMessageHash} on it. */ function recover(bytes32 hash, bytes memory signature) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, signature); _throwError(error); 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] * * _Available since v4.3._ */ function tryRecover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address, RecoverError) { bytes32 s = vs & bytes32(0x7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff); 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. * * _Available since v4.2._ */ function recover(bytes32 hash, bytes32 r, bytes32 vs) internal pure returns (address) { (address recovered, RecoverError error) = tryRecover(hash, r, vs); _throwError(error); return recovered; } /** * @dev Overload of {ECDSA-tryRecover} that receives the `v`, * `r` and `s` signature fields separately. * * _Available since v4.3._ */ function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s) internal pure returns (address, RecoverError) { // 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); } // 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); } return (signer, RecoverError.NoError); } /** * @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) = tryRecover(hash, v, r, s); _throwError(error); return recovered; } /** * @dev Returns an Ethereum Signed Message, created from a `hash`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 message) { // 32 is the length in bytes of hash, // enforced by the type signature above /// @solidity memory-safe-assembly assembly { mstore(0x00, "\x19Ethereum Signed Message:\n32") mstore(0x1c, hash) message := keccak256(0x00, 0x3c) } } /** * @dev Returns an Ethereum Signed Message, created from `s`. This * produces hash corresponding to the one signed with the * https://eth.wiki/json-rpc/API#eth_sign[`eth_sign`] * JSON-RPC method as part of EIP-191. * * See {recover}. */ function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19Ethereum Signed Message:\n", Strings.toString(s.length), s)); } /** * @dev Returns an Ethereum Signed Typed Data, created from a * `domainSeparator` and a `structHash`. This produces hash corresponding * to the one signed with the * https://eips.ethereum.org/EIPS/eip-712[`eth_signTypedData`] * JSON-RPC method as part of EIP-712. * * See {recover}. */ function toTypedDataHash(bytes32 domainSeparator, bytes32 structHash) internal pure returns (bytes32 data) { /// @solidity memory-safe-assembly assembly { let ptr := mload(0x40) mstore(ptr, "\x19\x01") mstore(add(ptr, 0x02), domainSeparator) mstore(add(ptr, 0x22), structHash) data := keccak256(ptr, 0x42) } } /** * @dev Returns an Ethereum Signed Data with intended validator, created from a * `validator` and `data` according to the version 0 of EIP-191. * * See {recover}. */ function toDataWithIntendedValidatorHash(address validator, bytes memory data) internal pure returns (bytes32) { return keccak256(abi.encodePacked("\x19\x00", validator, data)); } }
// SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.4; // modules import {OwnableUnset} from "./custom/OwnableUnset.sol"; import {ERC725YCore} from "./ERC725YCore.sol"; // errors import {OwnableCannotSetZeroAddressAsOwner} from "./errors.sol"; /** * @title Deployable implementation with `constructor` of ERC725Y, a generic data key/value store. * @author Fabian Vogelsteller <[email protected]> * @dev ERC725Y provides the ability to set arbitrary data key/value pairs that can be changed over time. * It is intended to standardise certain data key/value pairs to allow automated read and writes from/to the contract storage. */ contract ERC725Y is ERC725YCore { /** * @notice Deploying an ERC725Y smart contract and setting address `initialOwner` as the contract owner. * @dev Deploy a new ERC725Y contract with the provided `initialOwner` as the contract {owner}. * @param initialOwner the owner of the contract. * * @custom:requirements * - `initialOwner` CANNOT be the zero address. */ constructor(address initialOwner) payable { if (initialOwner == address(0)) { revert OwnableCannotSetZeroAddressAsOwner(); } OwnableUnset._setOwner(initialOwner); } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol) pragma solidity ^0.8.0; import "./math/Math.sol"; import "./math/SignedMath.sol"; /** * @dev String operations. */ library Strings { bytes16 private constant _SYMBOLS = "0123456789abcdef"; uint8 private constant _ADDRESS_LENGTH = 20; /** * @dev Converts a `uint256` to its ASCII `string` decimal representation. */ function toString(uint256 value) internal pure returns (string memory) { unchecked { uint256 length = Math.log10(value) + 1; string memory buffer = new string(length); uint256 ptr; /// @solidity memory-safe-assembly assembly { ptr := add(buffer, add(32, length)) } while (true) { ptr--; /// @solidity memory-safe-assembly assembly { mstore8(ptr, byte(mod(value, 10), _SYMBOLS)) } value /= 10; if (value == 0) break; } return buffer; } } /** * @dev Converts a `int256` to its ASCII `string` decimal representation. */ function toString(int256 value) internal pure returns (string memory) { return string(abi.encodePacked(value < 0 ? "-" : "", toString(SignedMath.abs(value)))); } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation. */ function toHexString(uint256 value) internal pure returns (string memory) { unchecked { return toHexString(value, Math.log256(value) + 1); } } /** * @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length. */ function toHexString(uint256 value, uint256 length) internal pure returns (string memory) { bytes memory buffer = new bytes(2 * length + 2); buffer[0] = "0"; buffer[1] = "x"; for (uint256 i = 2 * length + 1; i > 1; --i) { buffer[i] = _SYMBOLS[value & 0xf]; value >>= 4; } require(value == 0, "Strings: hex length insufficient"); return string(buffer); } /** * @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation. */ function toHexString(address addr) internal pure returns (string memory) { return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH); } /** * @dev Returns true if the two strings are equal. */ function equal(string memory a, string memory b) internal pure returns (bool) { return keccak256(bytes(a)) == keccak256(bytes(b)); } }
// SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.4; // interfaces import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; import {IERC725Y} from "./interfaces/IERC725Y.sol"; // modules import {ERC165} from "@openzeppelin/contracts/utils/introspection/ERC165.sol"; import {OwnableUnset} from "./custom/OwnableUnset.sol"; // constants import {_INTERFACEID_ERC725Y} from "./constants.sol"; import { ERC725Y_MsgValueDisallowed, ERC725Y_DataKeysValuesLengthMismatch, ERC725Y_DataKeysValuesEmptyArray } from "./errors.sol"; /** * @title Core implementation of ERC725Y sub-standard, a general data key/value store. * @author Fabian Vogelsteller <[email protected]> * @dev ERC725Y provides the ability to set arbitrary data key/value pairs that can be changed over time. * It is intended to standardise certain data key/value pairs to allow automated read and writes from/to the contract storage. */ abstract contract ERC725YCore is OwnableUnset, ERC165, IERC725Y { /** * @dev Map `bytes32` data keys to their `bytes` data values. */ mapping(bytes32 => bytes) internal _store; /** * @inheritdoc IERC725Y */ function getData( bytes32 dataKey ) public view virtual override returns (bytes memory dataValue) { dataValue = _getData(dataKey); } /** * @inheritdoc IERC725Y */ function getDataBatch( bytes32[] memory dataKeys ) public view virtual override returns (bytes[] memory dataValues) { dataValues = new bytes[](dataKeys.length); for (uint256 i = 0; i < dataKeys.length; ) { dataValues[i] = _getData(dataKeys[i]); // Increment the iterator in unchecked block to save gas unchecked { ++i; } } return dataValues; } /** * @inheritdoc IERC725Y * @custom:requirements * - SHOULD only be callable by the {owner}. * * @custom:warning * **Note for developers:** despite the fact that this function is set as `payable`, if the function is not intended to receive value * (= native tokens), **an additional check should be implemented to ensure that `msg.value` sent was equal to 0**. * * @custom:events {DataChanged} event. */ function setData( bytes32 dataKey, bytes memory dataValue ) public payable virtual override onlyOwner { if (msg.value != 0) revert ERC725Y_MsgValueDisallowed(); _setData(dataKey, dataValue); } /** * @inheritdoc IERC725Y * @custom:requirements * - SHOULD only be callable by the {owner} of the contract. * * @custom:warning * **Note for developers:** despite the fact that this function is set as `payable`, if the function is not intended to receive value * (= native tokens), **an additional check should be implemented to ensure that `msg.value` sent was equal to 0**. * * @custom:events {DataChanged} event **for each data key/value pair set**. */ function setDataBatch( bytes32[] memory dataKeys, bytes[] memory dataValues ) public payable virtual override onlyOwner { /// @dev do not allow to send value by default when setting data in ERC725Y if (msg.value != 0) revert ERC725Y_MsgValueDisallowed(); if (dataKeys.length != dataValues.length) { revert ERC725Y_DataKeysValuesLengthMismatch(); } if (dataKeys.length == 0) { revert ERC725Y_DataKeysValuesEmptyArray(); } for (uint256 i = 0; i < dataKeys.length; ) { _setData(dataKeys[i], dataValues[i]); // Increment the iterator in unchecked block to save gas unchecked { ++i; } } } /** * @dev Read the value stored under a specific `dataKey` inside the underlying ERC725Y storage, * represented as a mapping of `bytes32` data keys mapped to their `bytes` data values. * * ```solidity * mapping(bytes32 => bytes) _store * ``` * * @param dataKey A bytes32 data key to read the associated `bytes` value from the store. * @return dataValue The `bytes` value associated with the given `dataKey` in the ERC725Y storage. */ function _getData( bytes32 dataKey ) internal view virtual returns (bytes memory dataValue) { return _store[dataKey]; } /** * @dev Write a `dataValue` to the underlying ERC725Y storage, represented as a mapping of * `bytes32` data keys mapped to their `bytes` data values. * * ```solidity * mapping(bytes32 => bytes) _store * ``` * * @param dataKey A bytes32 data key to write the associated `bytes` value to the store. * @param dataValue The `bytes` value to associate with the given `dataKey` in the ERC725Y storage. * * @custom:events {DataChanged} event emitted after a successful `setData` call. */ function _setData( bytes32 dataKey, bytes memory dataValue ) internal virtual { _store[dataKey] = dataValue; emit DataChanged(dataKey, dataValue); } /** * @inheritdoc ERC165 */ function supportsInterface( bytes4 interfaceId ) public view virtual override(IERC165, ERC165) returns (bool) { return interfaceId == _INTERFACEID_ERC725Y || super.supportsInterface(interfaceId); } }
// SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.4; /** * @dev Reverts when trying to set `address(0)` as the contract owner when deploying the contract, * initializing it or transferring ownership of the contract. */ error OwnableCannotSetZeroAddressAsOwner(); /** * @dev Reverts when only the owner is allowed to call the function. * @param callerAddress The address that tried to make the call. */ error OwnableCallerNotTheOwner(address callerAddress); /** * @dev Reverts when trying to send more native tokens `value` than available in current `balance`. * @param balance The balance of native tokens of the ERC725X smart contract. * @param value The amount of native tokens sent via `ERC725X.execute(...)`/`ERC725X.executeBatch(...)` that is greater than the contract's `balance`. */ error ERC725X_InsufficientBalance(uint256 balance, uint256 value); /** * @dev Reverts when the `operationTypeProvided` is none of the default operation types available. * (CALL = 0; CREATE = 1; CREATE2 = 2; STATICCALL = 3; DELEGATECALL = 4) * @param operationTypeProvided The unrecognised operation type number provided to `ERC725X.execute(...)`/`ERC725X.executeBatch(...)`. */ error ERC725X_UnknownOperationType(uint256 operationTypeProvided); /** * @dev Reverts when trying to send native tokens (`value` / `values[]` parameter of {execute} or {executeBatch} functions) while making a `staticcall` (`operationType == 3`). * Sending native tokens via `staticcall` is not allowed because it is a state changing operation. */ error ERC725X_MsgValueDisallowedInStaticCall(); /** * @dev Reverts when trying to send native tokens (`value` / `values[]` parameter of {execute} or {executeBatch} functions) while making a `delegatecall` (`operationType == 4`). * Sending native tokens via `staticcall` is not allowed because `msg.value` is persisting. */ error ERC725X_MsgValueDisallowedInDelegateCall(); /** * @dev Reverts when passing a `to` address that is not `address(0)` (= address zero) while deploying a contract via {execute} or {executeBatch} functions. * This error can occur using either operation type 1 (`CREATE`) or 2 (`CREATE2`). */ error ERC725X_CreateOperationsRequireEmptyRecipientAddress(); /** * @dev Reverts when contract deployment failed via {execute} or {executeBatch} functions, * This error can occur using either operation type 1 (`CREATE`) or 2 (`CREATE2`). */ error ERC725X_ContractDeploymentFailed(); /** * @dev Reverts when no contract bytecode was provided as parameter when trying to deploy a contract via {execute} or {executeBatch}. * This error can occur using either operation type 1 (`CREATE`) or 2 (`CREATE2`). */ error ERC725X_NoContractBytecodeProvided(); /** * @dev Reverts when there is not the same number of elements in the `operationTypes`, `targets` addresses, `values`, and `datas` * array parameters provided when calling the {executeBatch} function. */ error ERC725X_ExecuteParametersLengthMismatch(); /** * @dev Reverts when one of the array parameter provided to the {executeBatch} function is an empty array. */ error ERC725X_ExecuteParametersEmptyArray(); /** * @dev Reverts when there is not the same number of elements in the `datakeys` and `dataValues` * array parameters provided when calling the {setDataBatch} function. */ error ERC725Y_DataKeysValuesLengthMismatch(); /** * @dev Reverts when one of the array parameter provided to {setDataBatch} function is an empty array. */ error ERC725Y_DataKeysValuesEmptyArray(); /** * @dev Reverts when sending value to the {setData} or {setDataBatch} function. */ error ERC725Y_MsgValueDisallowed();
// SPDX-License-Identifier: MIT pragma solidity ^0.8.4; // errors import { OwnableCannotSetZeroAddressAsOwner, OwnableCallerNotTheOwner } from "../errors.sol"; /** * @title OwnableUnset * @dev modified version of OpenZeppelin implementation, where: * - _setOwner(address) function is internal, so this function can be used in constructor * of contracts implementation (instead of using transferOwnership(address) * - the contract does not inherit from Context contract */ abstract contract OwnableUnset { address private _owner; event OwnershipTransferred( address indexed previousOwner, address indexed newOwner ); /** * @dev Returns the address of the current owner. */ function owner() public view virtual returns (address) { return _owner; } /** * @dev Throws if called by any account other than the owner. */ modifier onlyOwner() { _checkOwner(); _; } /** * @dev Leaves the contract without owner. It will not be possible to call * `onlyOwner` functions anymore. Can only be called by the current owner. * * NOTE: Renouncing ownership will leave the contract without an owner, * thereby removing any functionality that is only available to the owner. */ function renounceOwnership() public virtual onlyOwner { _setOwner(address(0)); } /** * @dev Transfers ownership of the contract to a new account (`newOwner`). * Can only be called by the current owner. */ function transferOwnership(address newOwner) public virtual onlyOwner { if (newOwner == address(0)) { revert OwnableCannotSetZeroAddressAsOwner(); } _setOwner(newOwner); } /** * @dev Throws if the sender is not the owner. */ function _checkOwner() internal view virtual { if (owner() != msg.sender) { revert OwnableCallerNotTheOwner(msg.sender); } } /** * @dev Changes the owner if `newOwner` and oldOwner are different * This pattern is useful in inheritance. */ function _setOwner(address newOwner) internal virtual { if (newOwner != owner()) { emit OwnershipTransferred(_owner, newOwner); _owner = newOwner; } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol) pragma solidity ^0.8.0; /** * @dev Standard signed math utilities missing in the Solidity language. */ library SignedMath { /** * @dev Returns the largest of two signed numbers. */ function max(int256 a, int256 b) internal pure returns (int256) { return a > b ? a : b; } /** * @dev Returns the smallest of two signed numbers. */ function min(int256 a, int256 b) internal pure returns (int256) { return a < b ? a : b; } /** * @dev Returns the average of two signed numbers without overflow. * The result is rounded towards zero. */ function average(int256 a, int256 b) internal pure returns (int256) { // Formula from the book "Hacker's Delight" int256 x = (a & b) + ((a ^ b) >> 1); return x + (int256(uint256(x) >> 255) & (a ^ b)); } /** * @dev Returns the absolute unsigned value of a signed value. */ function abs(int256 n) internal pure returns (uint256) { unchecked { // must be unchecked in order to support `n = type(int256).min` return uint256(n >= 0 ? n : -n); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol) pragma solidity ^0.8.0; /** * @dev Standard math utilities missing in the Solidity language. */ library Math { enum Rounding { Down, // Toward negative infinity Up, // Toward infinity Zero // Toward zero } /** * @dev Returns the largest of two numbers. */ function max(uint256 a, uint256 b) internal pure returns (uint256) { return a > b ? a : b; } /** * @dev Returns the smallest of two numbers. */ function min(uint256 a, uint256 b) internal pure returns (uint256) { return a < b ? a : b; } /** * @dev Returns the average of two numbers. The result is rounded towards * zero. */ function average(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b) / 2 can overflow. return (a & b) + (a ^ b) / 2; } /** * @dev Returns the ceiling of the division of two numbers. * * This differs from standard division with `/` in that it rounds up instead * of rounding down. */ function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) { // (a + b - 1) / b can overflow on addition, so we distribute. return a == 0 ? 0 : (a - 1) / b + 1; } /** * @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0 * @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv) * with further edits by Uniswap Labs also under MIT license. */ function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) { unchecked { // 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use // use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256 // variables such that product = prod1 * 2^256 + prod0. uint256 prod0; // Least significant 256 bits of the product uint256 prod1; // Most significant 256 bits of the product assembly { let mm := mulmod(x, y, not(0)) prod0 := mul(x, y) prod1 := sub(sub(mm, prod0), lt(mm, prod0)) } // Handle non-overflow cases, 256 by 256 division. if (prod1 == 0) { // Solidity will revert if denominator == 0, unlike the div opcode on its own. // The surrounding unchecked block does not change this fact. // See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic. return prod0 / denominator; } // Make sure the result is less than 2^256. Also prevents denominator == 0. require(denominator > prod1, "Math: mulDiv overflow"); /////////////////////////////////////////////// // 512 by 256 division. /////////////////////////////////////////////// // Make division exact by subtracting the remainder from [prod1 prod0]. uint256 remainder; assembly { // Compute remainder using mulmod. remainder := mulmod(x, y, denominator) // Subtract 256 bit number from 512 bit number. prod1 := sub(prod1, gt(remainder, prod0)) prod0 := sub(prod0, remainder) } // Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1. // See https://cs.stackexchange.com/q/138556/92363. // Does not overflow because the denominator cannot be zero at this stage in the function. uint256 twos = denominator & (~denominator + 1); assembly { // Divide denominator by twos. denominator := div(denominator, twos) // Divide [prod1 prod0] by twos. prod0 := div(prod0, twos) // Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one. twos := add(div(sub(0, twos), twos), 1) } // Shift in bits from prod1 into prod0. prod0 |= prod1 * twos; // Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such // that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for // four bits. That is, denominator * inv = 1 mod 2^4. uint256 inverse = (3 * denominator) ^ 2; // Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works // in modular arithmetic, doubling the correct bits in each step. inverse *= 2 - denominator * inverse; // inverse mod 2^8 inverse *= 2 - denominator * inverse; // inverse mod 2^16 inverse *= 2 - denominator * inverse; // inverse mod 2^32 inverse *= 2 - denominator * inverse; // inverse mod 2^64 inverse *= 2 - denominator * inverse; // inverse mod 2^128 inverse *= 2 - denominator * inverse; // inverse mod 2^256 // Because the division is now exact we can divide by multiplying with the modular inverse of denominator. // This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is // less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1 // is no longer required. result = prod0 * inverse; return result; } } /** * @notice Calculates x * y / denominator with full precision, following the selected rounding direction. */ function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) { uint256 result = mulDiv(x, y, denominator); if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) { result += 1; } return result; } /** * @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down. * * Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11). */ function sqrt(uint256 a) internal pure returns (uint256) { if (a == 0) { return 0; } // For our first guess, we get the biggest power of 2 which is smaller than the square root of the target. // // We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have // `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`. // // This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)` // → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))` // → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)` // // Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit. uint256 result = 1 << (log2(a) >> 1); // At this point `result` is an estimation with one bit of precision. We know the true value is a uint128, // since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at // every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision // into the expected uint128 result. unchecked { result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; result = (result + a / result) >> 1; return min(result, a / result); } } /** * @notice Calculates sqrt(a), following the selected rounding direction. */ function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = sqrt(a); return result + (rounding == Rounding.Up && result * result < a ? 1 : 0); } } /** * @dev Return the log in base 2, rounded down, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 128; } if (value >> 64 > 0) { value >>= 64; result += 64; } if (value >> 32 > 0) { value >>= 32; result += 32; } if (value >> 16 > 0) { value >>= 16; result += 16; } if (value >> 8 > 0) { value >>= 8; result += 8; } if (value >> 4 > 0) { value >>= 4; result += 4; } if (value >> 2 > 0) { value >>= 2; result += 2; } if (value >> 1 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 2, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log2(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log2(value); return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0); } } /** * @dev Return the log in base 10, rounded down, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >= 10 ** 64) { value /= 10 ** 64; result += 64; } if (value >= 10 ** 32) { value /= 10 ** 32; result += 32; } if (value >= 10 ** 16) { value /= 10 ** 16; result += 16; } if (value >= 10 ** 8) { value /= 10 ** 8; result += 8; } if (value >= 10 ** 4) { value /= 10 ** 4; result += 4; } if (value >= 10 ** 2) { value /= 10 ** 2; result += 2; } if (value >= 10 ** 1) { result += 1; } } return result; } /** * @dev Return the log in base 10, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log10(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log10(value); return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0); } } /** * @dev Return the log in base 256, rounded down, of a positive value. * Returns 0 if given 0. * * Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string. */ function log256(uint256 value) internal pure returns (uint256) { uint256 result = 0; unchecked { if (value >> 128 > 0) { value >>= 128; result += 16; } if (value >> 64 > 0) { value >>= 64; result += 8; } if (value >> 32 > 0) { value >>= 32; result += 4; } if (value >> 16 > 0) { value >>= 16; result += 2; } if (value >> 8 > 0) { result += 1; } } return result; } /** * @dev Return the log in base 256, following the selected rounding direction, of a positive value. * Returns 0 if given 0. */ function log256(uint256 value, Rounding rounding) internal pure returns (uint256) { unchecked { uint256 result = log256(value); return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0); } } }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol) pragma solidity ^0.8.0; /** * @dev Interface of the ERC165 standard, as defined in the * https://eips.ethereum.org/EIPS/eip-165[EIP]. * * Implementers can declare support of contract interfaces, which can then be * queried by others ({ERC165Checker}). * * For an implementation, see {ERC165}. */ interface IERC165 { /** * @dev Returns true if this contract implements the interface defined by * `interfaceId`. See the corresponding * https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section] * to learn more about how these ids are created. * * This function call must use less than 30 000 gas. */ function supportsInterface(bytes4 interfaceId) external view returns (bool); }
// SPDX-License-Identifier: CC0-1.0 pragma solidity ^0.8.0; // interfaces import {IERC165} from "@openzeppelin/contracts/utils/introspection/IERC165.sol"; /** * @title The interface for ERC725Y sub-standard, a generic data key/value store. * @dev ERC725Y provides the ability to set arbitrary data key/value pairs that can be changed over time. * It is intended to standardise certain data key/value pairs to allow automated read and writes from/to the contract storage. */ interface IERC725Y is IERC165 { /** * @notice The following data key/value pair has been changed in the ERC725Y storage: Data key: `dataKey`, data value: `dataValue`. * @dev Emitted when data at a specific `dataKey` was changed to a new value `dataValue`. * @param dataKey The data key for which a bytes value is set. * @param dataValue The value to set for the given data key. */ event DataChanged(bytes32 indexed dataKey, bytes dataValue); /** * @notice Reading the ERC725Y storage for data key `dataKey` returned the following value: `dataValue`. * @dev Get in the ERC725Y storage the bytes data stored at a specific data key `dataKey`. * @param dataKey The data key for which to retrieve the value. * @return dataValue The bytes value stored under the specified data key. */ function getData( bytes32 dataKey ) external view returns (bytes memory dataValue); /** * @notice Reading the ERC725Y storage for data keys `dataKeys` returned the following values: `dataValues`. * @dev Get in the ERC725Y storage the bytes data stored at multiple data keys `dataKeys`. * @param dataKeys The array of keys which values to retrieve * @return dataValues The array of data stored at multiple keys */ function getDataBatch( bytes32[] memory dataKeys ) external view returns (bytes[] memory dataValues); /** * @notice Setting the following data key value pair in the ERC725Y storage. Data key: `dataKey`, data value: `dataValue`. * * @dev Sets a single bytes value `dataValue` in the ERC725Y storage for a specific data key `dataKey`. * The function is marked as payable to enable flexibility on child contracts. For instance to implement * a fee mechanism for setting specific data. * * @param dataKey The data key for which to set a new value. * @param dataValue The new bytes value to set. */ function setData(bytes32 dataKey, bytes memory dataValue) external payable; /** * @notice Setting the following data key value pairs in the ERC725Y storage. Data keys: `dataKeys`, data values: `dataValues`. * * @dev Batch data setting function that behaves the same as {setData} but allowing to set multiple data key/value pairs in the ERC725Y storage in the same transaction. * * @param dataKeys An array of data keys to set bytes values for. * @param dataValues An array of bytes values to set for each `dataKeys`. */ function setDataBatch( bytes32[] memory dataKeys, bytes[] memory dataValues ) external payable; }
// SPDX-License-Identifier: MIT // OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol) pragma solidity ^0.8.0; import "./IERC165.sol"; /** * @dev Implementation of the {IERC165} interface. * * Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check * for the additional interface id that will be supported. For example: * * ```solidity * function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { * return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId); * } * ``` * * Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation. */ abstract contract ERC165 is IERC165 { /** * @dev See {IERC165-supportsInterface}. */ function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) { return interfaceId == type(IERC165).interfaceId; } }
// SPDX-License-Identifier: Apache-2.0 pragma solidity ^0.8.0; // ERC165 INTERFACE IDs bytes4 constant _INTERFACEID_ERC725X = 0x7545acac; bytes4 constant _INTERFACEID_ERC725Y = 0x629aa694; // ERC725X OPERATION TYPES uint256 constant OPERATION_0_CALL = 0; uint256 constant OPERATION_1_CREATE = 1; uint256 constant OPERATION_2_CREATE2 = 2; uint256 constant OPERATION_3_STATICCALL = 3; uint256 constant OPERATION_4_DELEGATECALL = 4;
{ "evmVersion": "paris", "optimizer": { "enabled": true, "mode": "3" }, "outputSelection": { "*": { "*": [ "abi" ] } }, "detectMissingLibraries": false, "forceEVMLA": false, "enableEraVMExtensions": false, "libraries": {} }
Contract ABI
API[{"inputs":[],"stateMutability":"nonpayable","type":"constructor"},{"anonymous":false,"inputs":[{"components":[{"internalType":"uint32","name":"id","type":"uint32"},{"internalType":"uint32","name":"timestampStart","type":"uint32"},{"internalType":"uint32","name":"timestampEnd","type":"uint32"},{"components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"string","name":"host","type":"string"}],"internalType":"struct Reclaim.Witness[]","name":"witnesses","type":"tuple[]"},{"internalType":"uint8","name":"minimumWitnessesForClaimCreation","type":"uint8"}],"indexed":false,"internalType":"struct Reclaim.Epoch","name":"epoch","type":"tuple"}],"name":"EpochAdded","type":"event"},{"inputs":[{"components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"string","name":"host","type":"string"}],"internalType":"struct Reclaim.Witness[]","name":"witnesses","type":"tuple[]"},{"internalType":"uint8","name":"requisiteWitnessesForClaimCreate","type":"uint8"}],"name":"addNewEpoch","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"currentEpoch","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"epochDurationS","outputs":[{"internalType":"uint32","name":"","type":"uint32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"","type":"uint256"}],"name":"epochs","outputs":[{"internalType":"uint32","name":"id","type":"uint32"},{"internalType":"uint32","name":"timestampStart","type":"uint32"},{"internalType":"uint32","name":"timestampEnd","type":"uint32"},{"internalType":"uint8","name":"minimumWitnessesForClaimCreation","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"epoch","type":"uint32"}],"name":"fetchEpoch","outputs":[{"components":[{"internalType":"uint32","name":"id","type":"uint32"},{"internalType":"uint32","name":"timestampStart","type":"uint32"},{"internalType":"uint32","name":"timestampEnd","type":"uint32"},{"components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"string","name":"host","type":"string"}],"internalType":"struct Reclaim.Witness[]","name":"witnesses","type":"tuple[]"},{"internalType":"uint8","name":"minimumWitnessesForClaimCreation","type":"uint8"}],"internalType":"struct Reclaim.Epoch","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"epoch","type":"uint32"},{"internalType":"bytes32","name":"identifier","type":"bytes32"},{"internalType":"uint32","name":"timestampS","type":"uint32"}],"name":"fetchWitnessesForClaim","outputs":[{"components":[{"internalType":"address","name":"addr","type":"address"},{"internalType":"string","name":"host","type":"string"}],"internalType":"struct Reclaim.Witness[]","name":"","type":"tuple[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"proofStorage","outputs":[{"internalType":"contract ProofStorage","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"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":"verifyProof","outputs":[],"stateMutability":"nonpayable","type":"function"}]
Deployed Bytecode
0x0002000000000002000900000000000200010000000103550000006003100270000003c80030019d0000008004000039000000400040043f0000000100200190000000390000c13d000003c802300197000000040020008c000001770000413d000000000301043b000000e003300270000003d20030009c0000008e0000a13d000003d30030009c000000f20000a13d000003d40030009c0000014f0000613d000003d50030009c000001620000613d000003d60030009c000001770000c13d000000240020008c000001770000413d0000000002000416000000000002004b000001770000c13d0000000401100370000000000101043b000000000200041a000000000021004b000001770000813d0f1809d60000040f0000000202100039000000000202041a000000000101041a0000002003100270000003c803300197000000400400043d000000200540003900000000003504350000004003100270000003c80330019700000040054000390000000000350435000000ff0220018f00000060034000390000000000230435000003c8011001970000000000140435000003c80040009c000003c8040080410000004001400210000003de011001c700000f190001042e0000000001000416000000000001004b000001770000c13d0000000102000039000000000102041a000003c901100197000003ca011001c7000000000012041b0000000201000039000000000201041a000003cb022001970000000003000411000000000232019f000000000021041b000003c701000041000000a40010043f0000000001000410000001040010043f000003cc010000410000000002000414000000800010043f000000840000043f0000006001000039000000c40010043f0000002001000039000000e40010043f000003c80020009c000003c802008041000000c001200210000003cd011001c700008006020000390f180f0e0000040f00000001002001900000006d0000613d00000000020000310000000103200367000000000101043b000000000001004b0000000002000019000000700000613d0000004001100210000003ce011001970000000103000039000000000203041a000003cf02200197000000000112019f000000000013041b000000200100003900000100001004430000012000000443000003d00100004100000f190001042e0000006002100270000003c802200197000000000301034f0000001f0520018f000003d106200198000000400100043d00000000046100190000007b0000613d000000000703034f0000000008010019000000007907043c0000000008980436000000000048004b000000770000c13d000000000005004b000000880000613d000000000363034f0000000305500210000000000604043300000000065601cf000000000656022f000000000303043b0000010005500089000000000353022f00000000035301cf000000000363019f00000000003404350000006002200210000003c80010009c000003c8010080410000004001100210000000000121019f00000f1a00010430000003d90030009c0000009a0000213d000003dc0030009c000000fd0000613d000003dd0030009c000001770000c13d0000000001000416000000000001004b000001770000c13d0000000101000039000000000101041a0000015e0000013d000003da0030009c0000011d0000613d000003db0030009c000001770000c13d000000440020008c000001770000413d0000000003000416000000000003004b000001770000c13d0000000403100370000000000303043b000400000003001d000003df0030009c000001770000213d00000004030000290000002303300039000000000023004b000001770000813d00000004030000290000000403300039000000000331034f000000000303043b000300000003001d000003df0030009c000001770000213d0000000403000029000900240030003d000000030300002900000005033002100000000903300029000000000023004b000001770000213d0000002401100370000000000101043b000800000001001d000000ff0010008c000001770000213d0000000201000039000000000101041a000003e4011001970000000002000411000000000021004b000002a70000c13d0000000104000039000000000104041a000003c800100198000000cc0000c13d0000040a01100197000003ca011001c7000000000014041b000000000200041a000000000002004b000000e80000613d000700000002001d000000000000043f0000040b0100004100000000001004430000000001000414000003c80010009c000003c801008041000000c0011002100000040c011001c70000800b020000390f180f130000040f0000000100200190000009640000613d000000000101043b00000040011002100000040d01100197000000070200002900000003022000c90000040e0220009a000000000302041a0000040f03300197000000000113019f000000000012041b0000000104000039000000000104041a0000002002100270000003c802200197000003c80020009c000002b10000c13d000003ef01000041000000000010043f0000001101000039000000040010043f000003f00100004100000f1a00010430000003d70030009c000001580000613d000003d80030009c000001770000c13d0000000001000416000000000001004b000001770000c13d0000000101000039000000000101041a0000004001100270000001540000013d000000640020008c000001770000413d0000000002000416000000000002004b000001770000c13d0000000402100370000000000402043b000003c80040009c000001770000213d0000004402100370000000000302043b000003c80030009c000001770000213d0000002401100370000000000201043b00000000010400190f1809e30000040f0000002002000039000000400300043d000900000003001d00000000022304360f1809a70000040f00000009020000290000000001210049000003c80010009c000003c8010080410000006001100210000003c80020009c000003c8020080410000004002200210000000000121019f00000f190001042e000000240020008c000001770000413d0000000002000416000000000002004b000001770000c13d0000000401100370000000000101043b000003c80010009c000001770000213d0f180d9d0000040f0000002002000039000000400400043d000800000004001d0000000002240436000900000001001d0000000035010434000003c80550019700000000005204350000000002030433000003c8032001970000004002400039000000000032043500000040021000390000000002020433000003c80320019700000060024000390000000000320435000000600210003900000000010204330000008002400039000000a0030000390000000000320435000000c0024000390f1809a70000040f000000090200002900000080022000390000000002020433000000ff0220018f0000000804000029000000a00340003900000000002304350000000001410049000003c80040009c000003c8040080410000004002400210000003c80010009c000003c8010080410000006001100210000000000121019f00000f190001042e0000000001000416000000000001004b000001770000c13d0000000201000039000000000101041a000003e401100197000000800010043f000004070100004100000f190001042e0000000001000416000000000001004b000001770000c13d0000000101000039000000000101041a0000002001100270000003c801100197000000800010043f000004070100004100000f190001042e000000240020008c000001770000413d0000000003000416000000000003004b000001770000c13d0000000403100370000000000303043b000003df0030009c000001770000213d0000000004320049000003e00040009c000001770000213d000000440040008c000001770000413d000000c005000039000000400050043f0000000404300039000000000641034f000000000606043b000003df0060009c000001790000a13d000000000100001900000f1a0001043000000000063600190000000007620049000003e00070009c000001770000213d000000640070008c000001770000413d0000012007000039000000400070043f0000000408600039000000000981034f000000000909043b000003df0090009c000001770000213d000000000b6900190000002309b00039000000000029004b000001770000813d000000040ab000390000000009a1034f000000000909043b000003df0090009c000002ba0000213d0000001f0c9000390000041a0cc001970000003f0cc000390000041a0cc00197000003e100c0009c000002ba0000213d000000240bb00039000001200cc000390000004000c0043f000001200090043f000000000bb9001900000000002b004b000001770000213d000000200aa000390009000000a103530000041a0c9001980000001f0d90018f000001400ac00039000001a80000613d000001400e000039000000090f00035f00000000fb0f043c000000000ebe04360000000000ae004b000001a40000c13d00000000000d004b000001b50000613d000000090bc0035f000000030cd00210000000000d0a0433000000000dcd01cf000000000dcd022f000000000b0b043b000001000cc00089000000000bcb022f000000000bcb01cf000000000bdb019f0000000000ba043500000140099000390000000000090435000000c00070043f0000002007800039000000000871034f000000000808043b000003df0080009c000001770000213d000000000a6800190000002308a00039000000000028004b000001770000813d000000040ba000390000000008b1034f000000000808043b000003df0080009c000002ba0000213d0000001f098000390000041a099001970000003f099000390000041a0c900197000000400900043d000000000cc9001900000000009c004b000000000d000039000000010d004039000003df00c0009c000002ba0000213d0000000100d00190000002ba0000c13d000000240aa000390000004000c0043f000000000c890436000000000aa8001900000000002a004b000001770000213d000000200ab000390009000000a103530008041a0080019c0000001f0e80018f000000080bc00029000001e50000613d000000090f00035f000000000a0c001900000000fd0f043c000000000ada04360000000000ba004b000001e10000c13d00000000000e004b000001f30000613d000000080d000029000000090ad0035f000000030de00210000000000e0b0433000000000ede01cf000000000ede022f000000000a0a043b000001000dd00089000000000ada022f000000000ada01cf000000000aea019f0000000000ab043500000000088c00190000000000080435000000e00090043f0000002007700039000000000771034f000000000707043b000003df0070009c000001770000213d00000000086700190000002306800039000000000026004b000001770000813d0000000409800039000000000691034f000000000606043b000003df0060009c000002ba0000213d0000001f076000390000041a077001970000003f077000390000041a0a700197000000400700043d000000000aa7001900000000007a004b000000000b000039000000010b004039000003df00a0009c000002ba0000213d0000000100b00190000002ba0000c13d000000240b8000390000004000a0043f0000000008670436000000000ab6001900000000002a004b000001770000213d0000002009900039000000000a91034f0000041a0b6001980000001f0c60018f0000000009b80019000002230000613d000000000d0a034f000000000e08001900000000df0d043c000000000efe043600000000009e004b0000021f0000c13d00000000000c004b000002300000613d000000000aba034f000000030bc00210000000000c090433000000000cbc01cf000000000cbc022f000000000a0a043b000001000bb00089000000000aba022f000000000aba01cf000000000aca019f0000000000a9043500000000066800190000000000060435000001000070043f000000800050043f0000002403300039000000000331034f000000000303043b000003df0030009c000001770000213d00000000053400190000000003520049000003e00030009c000001770000213d000000a00030008c000001770000413d000000400300043d000900000003001d000003e20030009c000002ba0000213d00000009030000290000004004300039000000400040043f000003e30030009c000002ba0000213d0000000903000029000000c006300039000000400060043f000000000651034f000000000606043b00000000006404350000002006500039000000000761034f000000000707043b000003e40070009c000001770000213d0000000903000029000000600830003900000000007804350000002006600039000000000761034f000000000707043b000003c80070009c000001770000213d0000000903000029000000800830003900000000007804350000002006600039000000000761034f000000000707043b000003c80070009c000001770000213d00000009030000290000000004430436000800000004001d000000a00430003900000000007404350000002004600039000000000441034f000000000404043b000003df0040009c000001770000213d00000000055400190000001f04500039000000000024004b000001770000813d000000000451034f000000000904043b000003df0090009c000002ba0000213d00000005089002100000003f04800039000003e504400197000000400300043d0000000006430019000700000003001d000000000036004b00000000040000390000000104004039000003df0060009c000002ba0000213d0000000100400190000002ba0000c13d000000400060043f0000000703000029000000000093043500000020075000390000000008780019000000000028004b000001770000213d000000000009004b000004600000c13d0000000802000029000000070100002900000000001204350000000901000029000000a00010043f000000400100043d000700000001001d00000000010204330000000002010433000000000002004b000004ab0000c13d000000070300002900000044013000390000040602000041000000000021043500000024013000390000000d020000390000000000210435000003ea010000410000000000130435000000040130003900000020020000390000000000210435000003c80030009c000003c8030080410000004001300210000003eb011001c700000f1a00010430000003ea01000041000000800010043f0000002001000039000000840010043f0000000a01000039000000a40010043f0000040801000041000000c40010043f000004090100004100000f1a00010430000004100310019700000020012002100000040a0110009a0000041102100197000000000232019f000000000024041b000000000200041a000004120020009c000002c00000413d000003ef01000041000000000010043f0000004101000039000000040010043f000003f00100004100000f1a000104300000000103200039000000000030041b000000000000043f000000200110027000000003022000c9000600000002001d000004130320009a000000000203041a0000040a02200197000000000112019f000700000003001d000000000013041b0000040b0100004100000000001004430000000001000414000003c80010009c000003c801008041000000c0011002100000040c011001c70000800b020000390f180f130000040f0000000100200190000009640000613d0000000704000029000000000204041a0000041002200197000000000101043b00000020031002100000041103300197000000000232019f000000000024041b0000000103000039000000000303041a000003c803300197000000000013001a000000ec0000413d00000000011300190000040f0220019700000040011002100000040d01100197000000000121019f0000000702000029000000000012041b0000000601000029000004140110009a000000000201041a0000041b0220019700000008022001af000000000021041b000000030000006b0000033e0000c13d000000000100041a000000000001004b000000ec0000613d000000400500043d0000002002000039000000000225043600000003061000c90000040e0160009a000000000101041a0000008003500039000000a0040000390000000000430435000003c80310019700000000003204350000004002100270000003c802200197000000600350003900000000002304350000002001100270000003c80110019700000040025000390000000000120435000900000005001d000000c001500039000200000006001d000004170260009a000000000302041a000800000003001d0000000000310435000000000020043f0000000001000414000003c80010009c000003c801008041000000c00110021000000416011001c700008010020000390f180f130000040f0000000100200190000001770000613d0000000902000029000000e004200039000000080300002900000005023002100000000009420019000000000003004b0000040d0000c13d0000000201000029000004180110009a000000000101041a000000ff0110018f0000000903000029000000a00230003900000000001204350000000001390049000003c80010009c000003c8010080410000006001100210000003c80030009c000003c8030080410000004002300210000000000121019f0000000002000414000003c80020009c000003c802008041000000c002200210000000000112019f000003e8011001c70000800d02000039000000010300003900000419040000410f180f0e0000040f0000000100200190000001770000613d000000000100001900000f190001042e000000060100002900020415001000a200000000040000190000034a0000013d000000010160021000000001011001bf00000006040000290000000505000029000000000015041b0000000104400039000000030040006c000002f30000813d000600000004001d000000050140021000000009011000290000000101100367000000000501043b00000004010000290000000001100079000000630110008a000003e602500197000003e603100197000000000432013f000000000032004b0000000002000019000003e602004041000000000015004b0000000001000019000003e601008041000003e60040009c000000000201c019000000000002004b000001770000c13d000800000005001d0000000202000029000000000102041a000003df0010009c000002ba0000213d000700000001001d0000000101100039000000000012041b000000000020043f0000000001000414000003c80010009c000003c801008041000000c00110021000000416011001c700008010020000390f180f130000040f00000001002001900000000803000029000001770000613d00000009023000290000000103000367000000000423034f000000000404043b000003e40040009c000001770000213d00000007050000290000000105500210000000000101043b0000000001510019000000000501041a000003cb05500197000000000445019f000000000041041b0000002004200039000000000543034f000000000400003100000000062400490000001f0660008a000000000505043b000003e607500197000003e608600197000000000987013f000000000087004b0000000007000019000003e607004041000000000065004b0000000006000019000003e606008041000003e60090009c000000000706c019000000000007004b000001770000c13d0000000002250019000000000323034f000000000603043b000003df0060009c000001770000213d00000000036400490000002007200039000003e602300197000003e604700197000000000524013f000000000024004b0000000002000019000003e602004041000000000037004b0000000003000019000003e603002041000003e60050009c000000000203c019000000000002004b000001770000c13d0000000105100039000000000105041a000000010210019000000001031002700000007f0330618f0000001f0030008c00000000010000390000000101002039000000000012004b0000045a0000c13d000000200030008c000800000006001d000500000005001d000700000007001d000003d40000413d000100000003001d000000000050043f0000000001000414000003c80010009c000003c801008041000000c00110021000000416011001c700008010020000390f180f130000040f000000070700002900000008060000290000000100200190000001770000613d0000001f026000390000000502200270000000200060008c0000000002004019000000000301043b00000001010000290000001f01100039000000050110027000000000011300190000000002230019000000000012004b0000000505000029000003d40000813d000000000002041b0000000102200039000000000012004b000003d00000413d000000200060008c000003f20000413d000000000050043f0000000001000414000003c80010009c000003c801008041000000c00110021000000416011001c700008010020000390f180f130000040f000000070700002900000008060000290000000100200190000001770000613d0000041a02600198000000000101043b000004000000613d000000010400036700000000030000190000000005730019000000000554034f000000000505043b000000000051041b00000001011000390000002003300039000000000023004b000003e70000413d000000000062004b000003420000813d000004030000013d000000000006004b0000000604000029000003f80000613d0000000101700367000000000101043b000003f90000013d000000000100001900000003026002100000041c0220027f0000041c02200167000000000121016f0000000102600210000000000121019f000003460000013d0000000003000019000000000062004b000003420000813d0000000302600210000000f80220018f0000041c0220027f0000041c0220016700000000037300190000000103300367000000000303043b000000000223016f000000000021041b000003420000013d0000000005040019000000000601043b000000400700003900000000080000190000041d0000013d0000041b012001970000006002900039000000000012043500000000000a004b00000020010000390000000001006039000000000921001900000002066000390000000108800039000000080080006c000003210000813d000000090190006a000000e00110008a0000000005150436000000000106041a00000020029000390000000000720435000003e40110019700000000001904350000000101600039000000000201041a0000000103200190000000010a2002700000007f0aa0618f0000001f00a0008c00000000040000390000000104002039000000000442013f00000001004001900000045a0000c13d00000040049000390000000000a40435000000000003004b000004120000613d00030000000a001d000400000009001d000500000008001d000600000006001d000700000005001d000000000010043f0000000001000414000003c80010009c000003c801008041000000c00110021000000416011001c700008010020000390f180f130000040f0000000100200190000001770000613d000000040200002900000060022000390000000309000029000000000009004b00000006060000290000000508000029000004560000613d000000000301043b000000000100001900000040070000390000000004210019000000000503041a000000000054043500000001033000390000002001100039000000000091004b0000044d0000413d0000000705000029000004180000013d000000000100001900000007050000290000004007000039000004180000013d000003ef01000041000000000010043f0000002201000039000000040010043f000003f00100004100000f1a000104300000000709000029000004690000013d00000020099000390000000003a4001900000000000304350000000000b904350000002007700039000000000087004b0000028b0000813d000000000471034f000000000404043b000003df0040009c000001770000213d000000000c5400190000003f04c00039000000000024004b0000000006000019000003e606008041000003e604400197000000000004004b000000000a000019000003e60a004041000003e60040009c000000000a06c01900000000000a004b000001770000c13d000000200dc000390000000004d1034f000000000a04043b000003df00a0009c000002ba0000213d0000001f04a000390000041a044001970000003f044000390000041a04400197000000400b00043d000000000e4b00190000000000be004b00000000040000390000000104004039000003df00e0009c000002ba0000213d0000000100400190000002ba0000c13d0000004006c000390000004000e0043f0000000004ab043600000000066a0019000000000026004b000001770000213d0000002006d00039000000000661034f0000041a0fa00198000000000df400190000049d0000613d000000000e06034f000000000c04001900000000e30e043c000000000c3c04360000000000dc004b000004990000c13d0000001f0ca00190000004620000613d0000000003f6034f0000000306c00210000000000c0d0433000000000c6c01cf000000000c6c022f000000000303043b0000010006600089000000000363022f00000000036301cf0000000003c3019f00000000003d0435000004620000013d0000000702000029000003e20020009c000002ba0000213d0000000902000029000000000202043300000007040000290000004003400039000000400030043f0000000002240436000800000002001d0000000000120435000000400100043d0000002002100039000000800300043d00000000560304340000004003300039000000000403043300000000050504330000000063060434000000000003004b000004c80000613d000000000700001900000000082700190000000009760019000000000909043300000000009804350000002007700039000000000037004b000004c10000413d0000000006230019000000000006043500000000061300190000002008600039000003e707000041000000000078043500000021086000390000000095050434000000000005004b000004da0000613d000000000a000019000000000b8a0019000000000ca90019000000000c0c04330000000000cb0435000000200aa0003900000000005a004b000004d30000413d0000000008850019000000000008043500000000066500190000002108600039000000000078043500000022066000390000000074040434000000000004004b000004eb0000613d00000000080000190000000009680019000000000a870019000000000a0a04330000000000a904350000002008800039000000000048004b000004e40000413d00000000066400190000000000060435000000000335001900000000034300190000000204300039000000000041043500000041033000390000041a043001970000000003140019000000000043004b00000000040000390000000104004039000003df0030009c000002ba0000213d0000000100400190000002ba0000c13d000000400030043f000003c80020009c000003c80200804100000040022002100000000001010433000003c80010009c000003c8010080410000006001100210000000000121019f0000000002000414000003c80020009c000003c802008041000000c002200210000000000112019f000003e8011001c700008010020000390f180f130000040f0000000100200190000001770000613d000000000201043b000000a00100043d00000000010104330000000003010433000000000023004b000006150000c13d0000004003100039000000000303043300000060011000390000000001010433000003c801100197000003c8033001970f1809e30000040f000000070200002900000000020204330000000056020434000000400300043d0000002004300039000000000064043500000020060000390000000000630435000600000001001d000003e20030009c000002ba0000213d0000004006300039000000400060043f00000000070304330000000101700210000000000007004b000005310000613d00000000077100d9000000020070008c000000ec0000c13d000003df0010009c000002ba0000213d0000001f071000390000041a087001970000003f078000390000041a077001970000000007670019000003df0070009c000002ba0000213d000000400070043f0000000000160435000000600730003900000000010000310000000101100367000000000008004b000005460000613d0000000008870019000000000901034f000000000a070019000000009b09043c000000000aba043600000000008a004b000005420000c13d000000400800043d000003e20080009c000002ba0000213d0000004009800039000000400090043f00000010090000390000000009980436000003ec0a0000410000000000a90435000000000a03043300000000000a004b0000058b0000613d000000000a000019000000000b08043300000000000b004b000006260000613d000000000c4a0019000000000d0c0433000000f80dd00270000000000dbd00d90000000000db004b000009650000a13d000000000d9d0019000000010ba00210000000000d0d043300000000000a004b000005640000613d000000000eab00d90000000200e0008c000000ec0000c13d000000000e0604330000000000be004b000009650000a13d000000000e7b0019000000000f0e0433000003ed0ff00197000003ee0dd00197000000000ddf019f0000000000de0435000000000d0304330000000000ad004b000009650000a13d000000000d08043300000000000d004b000006260000613d000000000c0c0433000000f80cc0027000000000c0dc00d9000000000c9c0019000000000c0c043300000000000a004b0000057d0000613d000000000dab00d90000000200d0008c000000ec0000c13d000000010bb001bf000000000d0604330000000000bd004b000009650000a13d000000000b7b0019000000000d0b0433000003ed0dd00197000003ee0cc00197000000000ccd019f0000000000cb0435000000010aa00039000000000b0304330000000000ba004b000005530000413d000000400400043d0000002003400039000003f1080000410000000000830435000700000004001d00000022084000390000000006060433000000000006004b0000059c0000613d0000000009000019000000000a890019000000000b790019000000000b0b04330000000000ba04350000002009900039000000000069004b000005950000413d0000000006860019000000000006043500000007080000290000000006860049000000200760008a00000000007804350000001f066000390000041a066001970000000007860019000000000067004b00000000060000390000000106004039000003df0070009c000002ba0000213d0000000100600190000002ba0000c13d000000400070043f000003f20070009c000002ba0000213d0000000005050433000003e4055001970000006006700039000000400060043f00000028080000390000000008870436000000000901034f000000000a080019000000009b09043c000000000aba043600000000006a004b000005b70000c13d000000000600001900000003096002100000009809900089000000000995022f000000f00a90018f000000ff0b90018f0000000009ab0049000000ff0090008c000000ec0000213d000000010a600210000000000c0704330000000000ac004b000009650000a13d000000000c8a0019000000f40db002100000009f00b0008c000003f40b000041000003f30b002041000000000bdb0019000003f50bb00197000000000d0c0433000003ed0dd00197000000000bbd019f0000000000bc0435000003f40b0000410000000a0090008c000005d90000413d000003f30b000041000000a80090008c000000ec0000213d000000010aa001bf000000000c0704330000000000ac004b000009650000a13d000000f80990021000000000099b0019000000000a8a0019000000000b0a0433000003ed0bb0019700000000099b019f00000000009a0435000000130060008c0000000106600039000005bc0000413d000000400600043d0000002005600039000003f109000041000000000095043500000022096000390000000007070433000000000007004b000005f70000613d000000000a000019000000000b9a0019000000000c8a0019000000000c0c04330000000000cb0435000000200aa0003900000000007a004b000005f00000413d000000000797001900000000000704350000000007670049000000200870008a00000000008604350000001f077000390000041a077001970000000008670019000000000078004b00000000070000390000000107004039000003df0080009c000002ba0000213d0000000100700190000002ba0000c13d000000400080043f00000040072000390000000007070433000003c80970019800000020078000390000062c0000c13d000003e20080009c000002ba0000213d0000004009800039000000400090043f000003f409000041000000000097043500000001090000390000000000980435000006650000013d000000400100043d0000004402100039000003e9030000410000000000320435000000240210003900000019030000390000000000320435000003ea020000410000000000210435000000040210003900000020030000390000000000320435000003c80010009c000003c8010080410000004001100210000003eb011001c700000f1a00010430000003ef01000041000000000010043f0000001201000039000000040010043f000003f00100004100000f1a00010430000000000c090019000000000a000019000000000b0a0019000000010aa0003a000000ec0000613d0000000900c0008c0000000a0cc0011a0000062e0000213d000003f600b0009c000002ba0000213d0000041a0bb001970000005f0cb000390000041a0dc00197000000000c8d00190000000000dc004b000000000d000039000000010d004039000003df00c0009c000002ba0000213d0000000100d00190000002ba0000c13d0000004000c0043f0000000000a80435000000200bb000390000041a0cb001980000001f0bb0018f0000064e0000613d000000000cc70019000000000d01034f000000000e07001900000000df0d043c000000000efe04360000000000ce004b0000064a0000c13d00000000000b004b00000000000a004b000000ec0000613d0000000acb90011a0000000a0db000c900000000009d004b000000ec0000213d000000000000004b000000ec0000c13d000000010aa0008a000000000d0804330000000000ad004b000009650000a13d000000000d7a0019000000000e0d0433000003ed0ee00197000000f80cc00210000000000cec019f000003f70cc0009a0000000000cd0435000000090090008c00000000090b00190000064f0000213d00000060022000390000000002020433000003c809200198000006740000c13d000000400200043d000003e20020009c000002ba0000213d0000004009200039000000400090043f0000002009200039000003f40a0000410000000000a9043500000001090000390000000000920435000006ae0000013d000000000b090019000000000a00001900000000020a0019000000010aa0003a000000ec0000613d0000000900b0008c0000000a0bb0011a000006760000213d000003f60020009c000002ba0000213d0000041a0c2001970000005f02c000390000041a0b200197000000400200043d000000000bb2001900000000002b004b000000000d000039000000010d004039000003df00b0009c000002ba0000213d0000000100d00190000002ba0000c13d0000004000b0043f000000000ba20436000000200cc000390000041a0dc001980000001f0cc0018f000006970000613d000000000ddb0019000000000e01034f000000000f0b001900000000e40e043c000000000f4f04360000000000df004b000006930000c13d00000000000c004b00000000000a004b000000ec0000613d0000000adc90011a0000000a04c000c9000000000094004b000000ec0000213d000000000000004b000000ec0000c13d000000010aa0008a00000000040204330000000000a4004b000009650000a13d0000000004ba0019000000000e040433000003ed0ee00197000000f80dd00210000000000ded019f000003f70dd0009a0000000000d40435000000090090008c00000000090c0019000006980000213d000000400400043d000200000004001d000900200040003d00000007040000290000000004040433000000000004004b000006bd0000613d0000000009000019000000090a900029000000000b390019000000000b0b04330000000000ba04350000002009900039000000000049004b000006b60000413d0000000904400029000003e703000041000000000034043500000001044000390000000006060433000000000006004b000006cc0000613d0000000009000019000000000a490019000000000b590019000000000b0b04330000000000ba04350000002009900039000000000069004b000006c50000413d0000000004460019000000000034043500000001034000390000000004080433000000000004004b000006da0000613d000000000500001900000000063500190000000008570019000000000808043300000000008604350000002005500039000000000045004b000006d30000413d0000000003340019000003e704000041000000000043043500000001033000390000000042020434000000000002004b000006e90000613d000000000500001900000000063500190000000007540019000000000707043300000000007604350000002005500039000000000025004b000006e20000413d0000000002320019000000000002043500000002040000290000000002420049000000200320008a00000000003404350000001f022000390000041a022001970000000003420019000000000023004b00000000020000390000000102004039000300000003001d000003df0030009c000002ba0000213d0000000100200190000002ba0000c13d0000000302000029000000400020043f000000080200002900000000020204330000000002020433000003df0020009c000002ba0000213d00000005032002100000003f04300039000003e5044001970000000304400029000003df0040009c000002ba0000213d000000400040043f00000003040000290000000002240436000700000002001d0000001f0230018f000000000003004b000007140000613d00000007040000290000000003340019000000001501043c0000000004540436000000000034004b000007100000c13d000000000002004b000000080100002900000000020104330000000001020433000000000001004b0000000001000019000007fb0000613d000500000000001d00000005010000290001000500100218000000010120002900000020011000390000000001010433000400000001001d00000002010000290000000001010433000000000001004b000007610000613d000000000301001900000000040000190000000002040019000000010440003a000000ec0000613d000000090030008c0000000a0330011a000007280000213d000003f60020009c000002ba0000213d0000041a052001970000005f025000390000041a03200197000000400200043d0000000003320019000000000023004b00000000060000390000000106004039000003df0030009c000002ba0000213d0000000100600190000002ba0000c13d000000400030043f000000000342043600000020055000390000041a06500198000007490000613d0000000006630019000000000700003100000001077003670000000008030019000000007907043c0000000008980436000000000068004b000007450000c13d0000001f00500190000000000004004b000000ec0000613d0000000a6510011a0000000a075000c9000000000017004b000000ec0000213d000000000000004b000000ec0000c13d000000010440008a0000000007020433000000000047004b000009650000a13d00000000073400190000000008070433000003ed08800197000000f806600210000000000686019f000003f70660009a0000000000670435000000090010008c00000000010500190000074a0000213d0000076b0000013d000000400200043d000003e20020009c000002ba0000213d0000004001200039000000400010043f0000002003200039000003f401000041000000000013043500000001010000390000000000120435000000400100043d0000002004100039000003f80500004100000000005404350000003a051000390000000002020433000000000002004b0000077b0000613d000000000600001900000000075600190000000008360019000000000808043300000000008704350000002006600039000000000026004b000007740000413d0000000003520019000000000003043500000002050000290000000005050433000000000005004b000007890000613d000000000600001900000000073600190000000908600029000000000808043300000000008704350000002006600039000000000056004b000007820000413d0000000003350019000000000003043500000000022500190000001a03200039000000000031043500000059022000390000041a032001970000000002130019000000000032004b00000000030000390000000103004039000003df0020009c000002ba0000213d0000000100300190000002ba0000c13d000000400020043f000003c80040009c000003c80400804100000040024002100000000001010433000003c80010009c000003c8010080410000006001100210000000000121019f0000000002000414000003c80020009c000003c802008041000000c002200210000000000112019f000003e8011001c700008010020000390f180f130000040f0000000100200190000001770000613d000000400200043d000000000101043b00000004030000290000000034030434000000410040008c000008090000c13d000000040400002900000040044000390000000004040433000003fa0040009c000008190000213d00000004050000290000006005500039000000000505043300000000030304330000006006200039000000000046043500000040042000390000000000340435000000f803500270000000200420003900000000003404350000000000120435000000000000043f000003c80020009c000003c80200804100000040012002100000000002000414000003c80020009c000003c802008041000000c002200210000000000112019f000003de011001c700000001020000390f180f130000040f0000006003100270000003c803300197000000200030008c000000200500003900000000050340190000002004500190000007db0000613d000000000601034f0000000007000019000000006806043c0000000007870436000000000047004b000007d70000c13d0000001f05500190000007e80000613d000000000641034f0000000305500210000000000704043300000000075701cf000000000757022f000000000606043b0000010005500089000000000656022f00000000055601cf000000000575019f000000000054043500000001002001900000082c0000613d000000000100043d000003e401100198000008460000613d00000003020000290000000002020433000000050020006c000009650000a13d0000000103000029000000070230002900000000001204350000000503000029000500010030003d000000080100002900000000020104330000000001020433000000050010006b0000071c0000413d0000000302000029000000000202043300000006030000290000000003030433000000000032004b0000084d0000c13d000000000002004b000008610000c13d000000000001004b000008960000613d000000400100043d00000044021000390000040203000041000006180000013d0000004401200039000003f903000041000000000031043500000024012000390000001f030000390000000000310435000003ea010000410000000000120435000000040120003900000020030000390000000000310435000003c80020009c000003c8020080410000004001200210000003eb011001c700000f1a000104300000006401200039000003fc0300004100000000003104350000004401200039000003fd030000410000000000310435000000240120003900000022030000390000000000310435000003ea010000410000000000120435000000040120003900000020030000390000000000310435000003c80020009c000003c8020080410000004001200210000003fe011001c700000f1a000104300000001f0530018f000003d106300198000000400200043d0000000004620019000008370000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000048004b000008330000c13d000000000005004b000008440000613d000000000161034f0000000305500210000000000604043300000000065601cf000000000656022f000000000101043b0000010005500089000000000151022f00000000015101cf000000000161019f00000000001404350000006001300210000009a20000013d000000400100043d0000004402100039000003fb030000410000000000320435000000240210003900000018030000390000061b0000013d000000400100043d0000006402100039000003ff030000410000000000320435000000440210003900000400030000410000000000320435000000240210003900000035030000390000000000320435000003ea020000410000000000210435000000040210003900000020030000390000000000320435000003c80010009c000003c8010080410000004001100210000003fe011001c700000f1a000104300000000003000019000008660000013d0000000103300039000000000023004b0000087d0000813d0000000504300210000000070440002900000000050000190000086d0000013d0000000105500039000000000025004b000008630000813d000000000053004b0000086a0000613d0000000506500210000000070660002900000000060604330000000007040433000000000676013f000003e4006001980000086a0000c13d000000400100043d00000044021000390000040103000041000000000032043500000024021000390000001b030000390000061b0000013d000000000001004b000008960000613d000000060300002900000020033000390000000004000019000000000042004b000009650000a13d00000005054002100000000705500029000000000505043300000000060000190000000507600210000000000773001900000000070704330000000007070433000000000757013f000003e400700198000008930000613d0000000106600039000000000026004b000008880000413d000008050000013d0000000104400039000000000014004b000008820000413d000000a00100043d00000000010104330000000001010433000700000001001d0000000101000039000000000101041a000000400800043d00000020038000390000002002000039000900000003001d00000000002304350000004003800039000000800200043d000000400400003900000000004304350000000034020434000000800580003900000060060000390000000000650435000000e00780003900000000650404340000000000570435000800000008001d0000010004800039000000000005004b000008b80000613d000000000700001900000000084700190000000009760019000000000909043300000000009804350000002007700039000000000057004b000008b10000413d000000000645001900000000000604350000001f055000390000041a0550019700000000030304330000000806000029000000a00660003900000080075000390000000000760435000000000645001900000000540304340000000003460436000000000004004b000008ce0000613d000000000600001900000000073600190000000008650019000000000808043300000000008704350000002006600039000000000046004b000008c70000413d000000000534001900000000000504350000001f044000390000041a04400197000000000534001900000008040000290000000003450049000000800330008a00000040022000390000000002020433000000c004400039000000000034043500000000430204340000000002350436000000000003004b000008e60000613d000000000500001900000000062500190000000007540019000000000707043300000000007604350000002005500039000000000035004b000008df0000413d000000000423001900000000000404350000001f033000390000041a03300197000000000223001900000008040000290000000003420049000000400330008a0000006004400039000000a00500043d00000000003404350000000043050434000000006503043400000000055204360000000006060433000003e406600197000000000065043500000040053000390000000005050433000003c8055001970000004006200039000000000056043500000060033000390000000003030433000003c8033001970000006005200039000000000035043500000000030404330000008004200039000000a0050000390000000000540435000000a00520003900000000040304330000000000450435000000c00520003900000005064002100000000007560019000000000004004b0000096b0000c13d00000008040000290000000002470049000000200320008a00000000003404350000001f022000390000041a032001970000000002430019000000000032004b00000000030000390000000103004039000003df0020009c000002ba0000213d0000000100300190000002ba0000c13d0000004001100270000003e403100197000000400020043f00000403010000410000000000100443000600000003001d00000004003004430000000001000414000003c80010009c000003c801008041000000c00110021000000404011001c700008002020000390f180f130000040f0000000100200190000009640000613d000000000101043b000000000001004b000001770000613d000000400300043d000000240130003900000040020000390000000000210435000004050100004100000000001304350000000401300039000000070200002900000000002104350000000801000029000000000101043300000044023000390000000000120435000800000003001d0000006402300039000000000001004b000009470000613d000000000300001900000000042300190000000905300029000000000505043300000000005404350000002003300039000000000013004b000009400000413d0000001f031000390000041a03300197000000000121001900000000000104350000006401300039000003c80010009c000003c80100804100000060011002100000000802000029000003c80020009c000003c8020080410000004002200210000000000121019f0000000002000414000003c80020009c000003c802008041000000c002200210000000000112019f00000006020000290f180f0e0000040f0000000100200190000009870000613d0000000801000029000003df0010009c000002ba0000213d0000000801000029000000400010043f000000000100001900000f190001042e000000000001042f000003ef01000041000000000010043f0000003201000039000000040010043f000003f00100004100000f1a000104300000000006000019000009750000013d0000001f098000390000041a099001970000000008780019000000000008043500000000077900190000000106600039000000000046004b0000090d0000813d0000000008270049000000c00880008a00000000058504360000002003300039000000000803043300000000980804340000000007870436000000000008004b0000096d0000613d000000000a000019000000000b7a0019000000000ca90019000000000c0c04330000000000cb0435000000200aa0003900000000008a004b0000097f0000413d0000096d0000013d00000060061002700000001f0460018f000003d105600198000000400200043d0000000003520019000009930000613d000000000701034f0000000008020019000000007907043c0000000008980436000000000038004b0000098f0000c13d000003c806600197000000000004004b000009a10000613d000000000151034f0000000304400210000000000503043300000000054501cf000000000545022f000000000101043b0000010004400089000000000141022f00000000014101cf000000000151019f00000000001304350000006001600210000003c80020009c000003c8020080410000004002200210000000000112019f00000f1a0001043000000000040104330000000000420435000000050340021000000000033200190000002003300039000000000004004b000009d40000613d000000400500003900000000070000190000000008020019000009ba0000013d000000000a39001900000000000a04350000001f099000390000041a0990019700000000033900190000000107700039000000000047004b000009d40000813d0000000009230049000000200990008a000000200880003900000000009804350000002001100039000000000901043300000000a9090434000003e4099001970000000009930436000000000a0a04330000000000590435000000400b30003900000000a90a043400000000009b04350000006003300039000000000009004b000009b20000613d000000000b000019000000000c3b0019000000000dba0019000000000d0d04330000000000dc0435000000200bb0003900000000009b004b000009cc0000413d000009b20000013d0000000001030019000000000001042d000000000200041a000000000012004b000009dd0000a13d00000003011000c9000004130110009a000000000000043f000000000001042d000003ef01000041000000000010043f0000003201000039000000040010043f000003f00100004100000f1a00010430000f000000000002000200000003001d000300000002001d000000400200043d0000041d0020009c00000d7b0000813d000000a003200039000000400030043f0000006003200039000000600400003900000000004304350000008003200039000000000003043500000040032000390000000000030435000000200320003900000000000304350000000000020435000000000200041a000003c801100198000800000001001d00000a9c0000613d000000010110008a000000000012004b00000d690000a13d000000400200043d000500000002001d0000041e0020009c00000d7b0000213d00000003051000c90000000504000029000000a001400039000000400010043f000004130150009a000000000101041a0000004002100270000003c80220019700000040034000390000000000230435000003c80210019700000000022404360000002001100270000003c8011001970000000000120435000100000005001d000004150150009a000000000401041a000003df0040009c00000d7b0000213d00000005024002100000003f02200039000003e502200197000000400300043d0000000002230019000400000003001d000000000032004b00000000030000390000000103004039000003df0020009c00000d7b0000213d000000010030019000000d7b0000c13d000000400020043f000600000004001d00000004020000290000000000420435000000000010043f0000000001000414000003c80010009c000003c801008041000000c00110021000000416011001c700008010020000390f180f130000040f000000010020019000000d9b0000613d0000000605000029000000000005004b000000200f00008a000000080e00002900000a950000613d000000000601043b00000000070000190000000408000029000000400900043d000003e20090009c00000d7b0000213d0000004001900039000000400010043f000000000106041a000003e401100197000000000a1904360000000101600039000000000201041a0000000103200190000000010c2002700000007f0cc0618f0000001f00c0008c00000000040000390000000104002039000000000442013f000000010040019000000d810000c13d000000400b00043d0000000004cb0436000000000003004b00000a770000613d000700000004001d000d0000000c001d00090000000b001d000a0000000a001d000b00000009001d000e00000008001d000f00000007001d000c00000006001d000000000010043f0000000001000414000003c80010009c000003c801008041000000c00110021000000416011001c700008010020000390f180f130000040f000000010020019000000d9b0000613d0000000d0c00002900000000000c004b000000080e00002900000006050000290000000f070000290000000e0800002900000a7d0000613d000000000201043b0000000001000019000000200f00008a0000000c060000290000000b090000290000000a0a000029000000090b000029000000070d0000290000000003d10019000000000402041a0000000000430435000000010220003900000020011000390000000000c1004b00000a6f0000413d00000a830000013d0000041b01200197000000000014043500000000000c004b0000002001000039000000000100603900000a830000013d0000000001000019000000200f00008a0000000c060000290000000b090000290000000a0a000029000000090b0000290000003f011000390000000002f1016f0000000001b20019000000000021004b00000000020000390000000102004039000003df0010009c00000d7b0000213d000000010020019000000d7b0000c13d0000002008800039000000400010043f0000000000ba0435000000000098043500000002066000390000000107700039000000000057004b00000a370000413d00000005020000290000006001200039000000040300002900000000003104350000000101000029000004140110009a00000b3c0000013d000000000002004b00000d6f0000613d000000400100043d000500000001001d0000041e0010009c00000d7b0000213d00000003052000c90000000504000029000000a001400039000000400010043f0000040e0150009a000000000101041a0000004002100270000003c80220019700000040034000390000000000230435000003c80210019700000000022404360000002001100270000003c8011001970000000000120435000100000005001d000004170150009a000000000401041a000003df0040009c00000d7b0000213d00000005024002100000003f02200039000003e502200197000000400300043d0000000002230019000400000003001d000000000032004b00000000030000390000000103004039000003df0020009c00000d7b0000213d000000010030019000000d7b0000c13d000000400020043f000600000004001d00000004020000290000000000420435000000000010043f0000000001000414000003c80010009c000003c801008041000000c00110021000000416011001c700008010020000390f180f130000040f000000010020019000000d9b0000613d0000000605000029000000000005004b000000200f00008a000000080e00002900000b360000613d000000000601043b00000000070000190000000408000029000000400900043d000003e20090009c00000d7b0000213d0000004001900039000000400010043f000000000106041a000003e401100197000000000a1904360000000101600039000000000201041a0000000103200190000000010c2002700000007f0cc0618f0000001f00c0008c00000000040000390000000104002039000000000043004b00000d810000c13d000000400b00043d0000000004cb0436000000000003004b00000b180000613d000700000004001d000d0000000c001d00090000000b001d000a0000000a001d000b00000009001d000e00000008001d000f00000007001d000c00000006001d000000000010043f0000000001000414000003c80010009c000003c801008041000000c00110021000000416011001c700008010020000390f180f130000040f000000010020019000000d9b0000613d0000000d0c00002900000000000c004b000000080e00002900000006050000290000000f070000290000000e0800002900000b1e0000613d000000000201043b0000000001000019000000200f00008a0000000c060000290000000b090000290000000a0a000029000000090b000029000000070d0000290000000003d10019000000000402041a0000000000430435000000010220003900000020011000390000000000c1004b00000b100000413d00000b240000013d0000041b01200197000000000014043500000000000c004b0000002001000039000000000100603900000b240000013d0000000001000019000000200f00008a0000000c060000290000000b090000290000000a0a000029000000090b0000290000003f011000390000000002f1016f0000000001b20019000000000021004b00000000020000390000000102004039000003df0010009c00000d7b0000213d000000010020019000000d7b0000c13d0000002008800039000000400010043f0000000000ba0435000000000098043500000002066000390000000107700039000000000057004b00000ad90000413d00000005020000290000006001200039000000040300002900000000003104350000000101000029000004180110009a000500000002001d0000008002200039000000000101041a000000ff0110018f000f00000002001d00000000001204350000002001000039000000400200043d000000000312043600000003010000290000000000130435000003e20020009c00000d7b0000213d0000004004200039000000400040043f00000000050204330000000101500210000000000005004b00000b540000613d00000000055100d9000000020050008c00000d6f0000c13d000003df0010009c00000d7b0000213d0000001f051000390000000006f5016f0000003f056000390000000005f5016f0000000005450019000003df0050009c00000d7b0000213d000000400050043f0000000000140435000000600520003900000000010000310000000101100367000000000006004b00000b690000613d0000000006650019000000000701034f0000000008050019000000007907043c0000000008980436000000000068004b00000b650000c13d000000400600043d000003e20060009c00000d7b0000213d0000004007600039000000400070043f00000010070000390000000007760436000003ec0800004100000000008704350000000008020433000000000008004b00000bae0000613d00000000080000190000000009060433000000000009004b00000d750000613d000000000a380019000000000b0a0433000000f80bb00270000000000b9b00d90000000000b9004b00000d690000a13d000000000b7b00190000000109800210000000000b0b0433000000000008004b00000b870000613d000000000c8900d90000000200c0008c00000d6f0000c13d000000000c04043300000000009c004b00000d690000a13d000000000c590019000000000d0c0433000003ed0dd00197000003ee0bb00197000000000bbd019f0000000000bc0435000000000b02043300000000008b004b00000d690000a13d000000000b06043300000000000b004b00000d750000613d000000000a0a0433000000f80aa0027000000000a0ba00d9000000000a7a0019000000000a0a0433000000000008004b00000ba00000613d000000000b8900d90000000200b0008c00000d6f0000c13d00000001099001bf000000000b04043300000000009b004b00000d690000a13d0000000009590019000000000b090433000003ed0bb00197000003ee0aa00197000000000aab019f0000000000a9043500000001088000390000000009020433000000000098004b00000b760000413d000000400300043d0000002002300039000003f106000041000000000062043500000022063000390000000004040433000000000004004b00000bbe0000613d000000000700001900000000086700190000000009570019000000000909043300000000009804350000002007700039000000000047004b00000bb70000413d000000000464001900000000000404350000000004340049000000200540008a00000000005304350000001f044000390000000004f4016f0000000005340019000000000045004b00000000040000390000000104004039000003df0050009c00000d7b0000213d000000010040019000000d7b0000c13d000000400050043f00000000000e004b000000200450003900000c0b0000613d00000000080e001900000000060000190000000007060019000000010660003a00000d6f0000613d000000090080008c0000000a0880011a00000bd30000213d000003f60070009c00000d7b0000213d0000000007f7016f0000005f087000390000000009f8016f0000000008590019000000000098004b00000000090000390000000109004039000003df0080009c00000d7b0000213d000000010090019000000d7b0000c13d000000400080043f000000000065043500000020077000390000000008f701700000001f0770018f00000bf30000613d0000000008840019000000000901034f000000000a040019000000009b09043c000000000aba043600000000008a004b00000bef0000c13d000000000007004b000000000006004b00000d6f0000613d0000000a87e0011a0000000a097000c90000000000e9004b00000d6f0000213d000000000000004b00000d6f0000c13d000000010660008a0000000009050433000000000069004b00000d690000a13d0000000009460019000000000a090433000003ed0aa00197000000f8088002100000000008a8019f000003f70880009a00000000008904350000000900e0008c000000000e07001900000bf40000213d00000c130000013d000003e20050009c00000d7b0000213d0000004006500039000000400060043f000003f4060000410000000000640435000000010600003900000000006504350000000f060000290000000006060433000000ff0760019000000c8e0000613d000000000907001900000000080000190000000006080019000000010880003a00000d6f0000613d000000090090008c0000000a0990011a00000c190000213d000003f60060009c00000d7b0000213d000000000af6016f0000005f06a000390000000009f6016f000000400600043d0000000009960019000000000069004b000000000b000039000000010b004039000003df0090009c00000d7b0000213d0000000100b0019000000d7b0000c13d000000400090043f0000000009860436000000200aa00039000000000bfa01700000001f0aa0018f00000c3a0000613d000000000bb90019000000000c01034f000000000d09001900000000ce0c043c000000000ded04360000000000bd004b00000c360000c13d00000000000a004b000000000008004b00000d6f0000613d0000000aba70011a0000000a0ca000c900000000007c004b00000d6f0000213d000000000000004b00000d6f0000c13d000000010880008a000000000c06043300000000008c004b00000d690000a13d000000000c980019000000000d0c0433000003ed0dd00197000000f80bb00210000000000bdb019f000003f70bb0009a0000000000bc0435000000090070008c00000000070a001900000c3b0000213d0000000207000029000003c80870019800000c9b0000613d000000000a08001900000000090000190000000007090019000000010990003a00000d6f0000613d0000000900a0008c0000000a0aa0011a00000c560000213d000003f60070009c00000d7b0000213d000000000bf7016f0000005f07b00039000000000af7016f000000400700043d000000000aa7001900000000007a004b000000000c000039000000010c004039000003df00a0009c00000d7b0000213d0000000100c0019000000d7b0000c13d0000004000a0043f000000000a970436000000200bb00039000000000cfb01700000001f0bb0018f00000c760000613d000000000cca0019000000000d0a0019000000001e01043c000000000ded04360000000000cd004b00000c720000c13d00000000000b004b000000000009004b00000d6f0000613d0000000ab180011a0000000a0c1000c900000000008c004b00000d6f0000213d000000000000004b00000d6f0000c13d000000010990008a000000000c07043300000000009c004b00000d690000a13d000000000ca90019000000000d0c0433000003ed0dd00197000000f80bb00210000000000bdb019f000003f70bb0009a0000000000bc0435000000090080008c000000000801001900000c770000213d00000ca50000013d000000400600043d000003e20060009c00000d7b0000213d0000004007600039000000400070043f0000002007600039000003f4080000410000000000870435000000010700003900000000007604350000000207000029000003c80870019800000c540000c13d000000400700043d000003e20070009c00000d7b0000213d0000004001700039000000400010043f0000002001700039000003f408000041000000000081043500000001010000390000000000170435000000400100043d00000020081000390000000003030433000000000003004b00000cb20000613d0000000009000019000000000a890019000000000b290019000000000b0b04330000000000ba04350000002009900039000000000039004b00000cab0000413d0000000003830019000003e702000041000000000023043500000001033000390000000005050433000000000005004b00000cc10000613d0000000009000019000000000a390019000000000b940019000000000b0b04330000000000ba04350000002009900039000000000059004b00000cba0000413d0000000003350019000000000023043500000001023000390000000043060434000000000003004b00000ccf0000613d000000000500001900000000062500190000000009540019000000000909043300000000009604350000002005500039000000000035004b00000cc80000413d0000000002230019000003e703000041000000000032043500000001022000390000000043070434000000000003004b00000cde0000613d000000000500001900000000062500190000000007540019000000000707043300000000007604350000002005500039000000000035004b00000cd70000413d000000000223001900000000000204350000000002120049000000200320008a00000000003104350000001f022000390000000003f2016f0000000002130019000000000032004b00000000030000390000000103004039000003df0020009c00000d7b0000213d000000010030019000000d7b0000c13d000000400020043f000003c80080009c000003c80800804100000040028002100000000001010433000003c80010009c000003c8010080410000006001100210000000000121019f0000000002000414000003c80020009c000003c802008041000000c002200210000000000112019f000003e8011001c700008010020000390f180f130000040f000000010020019000000d9b0000613d000000000101043b000000400200043d0000002003200039000000000013043500000020010000390000000000120435000003e20020009c00000d7b0000213d0000004001200039000000400010043f0000000f030000290000000003030433000000ff0530018f00000005065002100000003f0360003900003fe00330018f0000000007130019000003df0070009c00000d7b0000213d000000050300002900000060033000390000000004030433000000400070043f0000000000510435000000000005004b000000600520003900000d2a0000613d0000000007000019000000600a000039000000400800043d000003e20080009c00000d7b0000213d0000004009800039000000400090043f00000020098000390000000000a904350000000000080435000000000975001900000000008904350000002007700039000000000067004b00000d1d0000413d0000000f060000290000000006060433000000ff0060019000000d680000613d0000002006400039000000000b0404330000000008000019000000000a00001900000000090b00190000042100a0009c00000d6f0000213d000000040aa00039000000000c0204330000000000ca004b00000d870000213d000000000009004b00000d750000613d000000000c2a0019000000000c0c0433000003c80cc0019700000000c09c00d90000000000cb004b00000d690000a13d000000000b01043300000000008b004b00000d690000a13d000000050bc00210000000000bb60019000000050d800210000000000dd50019000000000e0b04330000000000ed0435000000000d01043300000000008d004b00000d690000a13d000000010990008a000000000d030433000000000e0d043300000000009e004b00000d690000a13d000000000e0404330000000000ce004b00000d690000a13d000000050e900210000000000dde0019000000200dd00039000000000d0d04330000000000db0435000000000b0404330000000000cb004b00000d690000a13d000000000c02043300000000000c004b00000d750000613d00000000a0ca00d90000000108800039000003c8088001970000000f0c000029000000000c0c0433000000ff0cc0018f0000000000c8004b00000d330000413d000000000001042d000003ef01000041000000000010043f0000003201000039000000040010043f000003f00100004100000f1a00010430000003ef01000041000000000010043f0000001101000039000000040010043f000003f00100004100000f1a00010430000003ef01000041000000000010043f0000001201000039000000040010043f000003f00100004100000f1a00010430000003ef01000041000000000010043f0000004101000039000000040010043f000003f00100004100000f1a00010430000003ef01000041000000000010043f0000002201000039000000040010043f000003f00100004100000f1a00010430000000400100043d00000064021000390000041f030000410000000000320435000000440210003900000420030000410000000000320435000000240210003900000025030000390000000000320435000003ea020000410000000000210435000000040210003900000020030000390000000000320435000003c80010009c000003c8010080410000004001100210000003fe011001c700000f1a00010430000000000100001900000f1a00010430000c000000000002000000400200043d0000041d0020009c00000ef30000813d000000a003200039000000400030043f0000006003200039000000600400003900000000004304350000008003200039000000000003043500000040032000390000000000030435000000200320003900000000000304350000000000020435000000000200041a000003c80110019800000e500000613d000000010110008a000000000012004b00000f010000a13d000000400200043d000300000002001d0000041e0020009c00000ef30000213d00000003051000c90000000304000029000000a001400039000000400010043f000004130150009a000000000101041a0000004002100270000003c80220019700000040034000390000000000230435000003c80210019700000000022404360000002001100270000003c8011001970000000000120435000100000005001d000004150150009a000000000401041a000003df0040009c00000ef30000213d00000005024002100000003f02200039000003e502200197000000400300043d0000000002230019000200000003001d000000000032004b00000000030000390000000103004039000003df0020009c00000ef30000213d000000010030019000000ef30000c13d000000400020043f000400000004001d00000002020000290000000000420435000000000010043f0000000001000414000003c80010009c000003c801008041000000c00110021000000416011001c700008010020000390f180f130000040f000000010020019000000eff0000613d0000000405000029000000000005004b00000e490000613d000000000601043b000000200700008a00000000080000190000000209000029000000400a00043d000003e200a0009c00000ef30000213d0000004001a00039000000400010043f000000000106041a000003e401100197000000000b1a04360000000101600039000000000201041a0000000103200190000000010d2002700000007f0dd0618f0000001f00d0008c00000000040000390000000104002039000000000442013f000000010040019000000ef90000c13d000000400c00043d0000000004dc0436000000000003004b00000e2c0000613d000500000004001d00060000000d001d00070000000c001d00080000000b001d00090000000a001d000a00000009001d000b00000008001d000c00000006001d000000000010043f0000000001000414000003c80010009c000003c801008041000000c00110021000000416011001c700008010020000390f180f130000040f000000010020019000000eff0000613d000000060d00002900000000000d004b0000000405000029000000200700008a0000000b080000290000000a0900002900000e320000613d000000000201043b00000000010000190000000c06000029000000090a000029000000080b000029000000070c000029000000050e0000290000000003e10019000000000402041a0000000000430435000000010220003900000020011000390000000000d1004b00000e240000413d00000e370000013d0000041b01200197000000000014043500000000000d004b0000002001000039000000000100603900000e370000013d00000000010000190000000c06000029000000090a000029000000080b000029000000070c0000290000003f01100039000000000271016f0000000001c20019000000000021004b00000000020000390000000102004039000003df0010009c00000ef30000213d000000010020019000000ef30000c13d0000002009900039000000400010043f0000000000cb04350000000000a9043500000002066000390000000108800039000000000058004b00000ded0000413d00000003020000290000006001200039000000020300002900000000003104350000000101000029000004140110009a00000eed0000013d000000000002004b00000f070000613d000000400100043d000300000001001d0000041e0010009c00000ef30000213d00000003052000c90000000304000029000000a001400039000000400010043f0000040e0150009a000000000101041a0000004002100270000003c80220019700000040034000390000000000230435000003c80210019700000000022404360000002001100270000003c8011001970000000000120435000100000005001d000004170150009a000000000401041a000003df0040009c00000ef30000213d00000005024002100000003f02200039000003e502200197000000400300043d0000000002230019000200000003001d000000000032004b00000000030000390000000103004039000003df0020009c00000ef30000213d000000010030019000000ef30000c13d000000400020043f000400000004001d00000002020000290000000000420435000000000010043f0000000001000414000003c80010009c000003c801008041000000c00110021000000416011001c700008010020000390f180f130000040f000000010020019000000eff0000613d0000000405000029000000000005004b00000ee70000613d000000000601043b000000200700008a00000000080000190000000209000029000000400a00043d000003e200a0009c00000ef30000213d0000004001a00039000000400010043f000000000106041a000003e401100197000000000b1a04360000000101600039000000000201041a0000000103200190000000010d2002700000007f0dd0618f0000001f00d0008c00000000040000390000000104002039000000000043004b00000ef90000c13d000000400c00043d0000000004dc0436000000000003004b00000eca0000613d000500000004001d00060000000d001d00070000000c001d00080000000b001d00090000000a001d000a00000009001d000b00000008001d000c00000006001d000000000010043f0000000001000414000003c80010009c000003c801008041000000c00110021000000416011001c700008010020000390f180f130000040f000000010020019000000eff0000613d000000060d00002900000000000d004b0000000405000029000000200700008a0000000b080000290000000a0900002900000ed00000613d000000000201043b00000000010000190000000c06000029000000090a000029000000080b000029000000070c000029000000050e0000290000000003e10019000000000402041a0000000000430435000000010220003900000020011000390000000000d1004b00000ec20000413d00000ed50000013d0000041b01200197000000000014043500000000000d004b0000002001000039000000000100603900000ed50000013d00000000010000190000000c06000029000000090a000029000000080b000029000000070c0000290000003f01100039000000000271016f0000000001c20019000000000021004b00000000020000390000000102004039000003df0010009c00000ef30000213d000000010020019000000ef30000c13d0000002009900039000000400010043f0000000000cb04350000000000a9043500000002066000390000000108800039000000000058004b00000e8c0000413d00000003020000290000006001200039000000020300002900000000003104350000000101000029000004180110009a000000000101041a000000ff0310018f000000000102001900000080022000390000000000320435000000000001042d000003ef01000041000000000010043f0000004101000039000000040010043f000003f00100004100000f1a00010430000003ef01000041000000000010043f0000002201000039000000040010043f000003f00100004100000f1a00010430000000000100001900000f1a00010430000003ef01000041000000000010043f0000003201000039000000040010043f000003f00100004100000f1a00010430000003ef01000041000000000010043f0000001101000039000000040010043f000003f00100004100000f1a00010430000000000001042f00000f11002104210000000102000039000000000001042d0000000002000019000000000001042d00000f16002104230000000102000039000000000001042d0000000002000019000000000001042d00000f180000043200000f190001042e00000f1a000104300000000000000000010001ab3c9b13570343334cc6fb9e806af4973af7c496d98881cd8778a4374b00000000000000000000000000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000000000000000000000000000000000000000000000000000000000000000000000015180ffffffffffffffffffffffff00000000000000000000000000000000000000009c4d535bdea7cd8a978f128b93471df48c7dbab89d703809115bdc118c235bfd02000000000000000000000000000000000000a400000080000000000000000000000000ffffffffffffffffffffffffffffffffffffffff0000000000000000ffffffff0000000000000000000000000000000000000000ffffffffffffffff000000020000000000000000000000000000004000000100000000000000000000000000000000000000000000000000000000000000000000000000ffffffe00000000000000000000000000000000000000000000000000000000076671807000000000000000000000000000000000000000000000000000000008da5cb5a000000000000000000000000000000000000000000000000000000008da5cb5b00000000000000000000000000000000000000000000000000000000a960e69e00000000000000000000000000000000000000000000000000000000c6b61e4c00000000000000000000000000000000000000000000000000000000766718080000000000000000000000000000000000000000000000000000000076b86c8b000000000000000000000000000000000000000000000000000000003d3c3e06000000000000000000000000000000000000000000000000000000003d3c3e07000000000000000000000000000000000000000000000000000000004729504c0000000000000000000000000000000000000000000000000000000010abbe5600000000000000000000000000000000000000000000000000000000289989fd0000000000000000000000000000000000000080000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000fffffffffffffedf000000000000000000000000000000000000000000000000ffffffffffffffbf000000000000000000000000000000000000000000000000ffffffffffffff3f000000000000000000000000ffffffffffffffffffffffffffffffffffffffff7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe080000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000200000000000000000000000000000000000000000000000000000000000000436c61696d206964656e746966696572206d69736d617463680000000000000008c379a0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000064000000000000000000000000303132333435363738396162636465660000000000000000000000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000000000000000004e487b710000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000240000000000000000000000003078000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000ffffffffffffff9f570000000000000000000000000000000000000000000000000000000000000030000000000000000000000000000000000000000000000000000000000000007f00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000fffffffffffffffed00000000000000000000000000000000000000000000000000000000000000019457468657265756d205369676e6564204d6573736167653a0a00000000000045434453413a20696e76616c6964207369676e6174757265206c656e677468007fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a045434453413a20696e76616c6964207369676e61747572650000000000000000756500000000000000000000000000000000000000000000000000000000000045434453413a20696e76616c6964207369676e6174757265202773272076616c00000000000000000000000000000000000000840000000000000000000000006f206e756d626572206f66207769746e657373657300000000000000000000004e756d626572206f66207369676e617475726573206e6f7420657175616c20744475706c696361746564205369676e61747572657320466f756e6400000000005369676e6174757265206e6f7420617070726f707269617465000000000000001806aa1896bbf26568e884a7374b41e002500962caba6a15023a8d90e8508b8302000002000000000000000000000000000000240000000000000000000000003e4129cd000000000000000000000000000000000000000000000000000000004e6f207369676e6174757265730000000000000000000000000000000000000000000000000000000000000000000000000000200000008000000000000000004f6e6c79204f776e6572000000000000000000000000000000000000000000000000000000000000000000000000000000000064000000800000000000000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000796b89b91644bc98cd93958e4c9038275d622183e25ac5af08cc6b5d9553913202000002000000000000000000000000000000040000000000000000000000000000000000000000000000000000000000000000ffffffff0000000000000000d6f21326ab749d5729fcba5677c79037b459436ab7bff709c9d06ce9f10c1aa0ffffffffffffffffffffffffffffffffffffffff00000000ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00000000ffffffff000000000000000000000000000000000000000000000000ffffffff000000000000000000000000000000000000000000000000000000010000000000000000d6f21326ab749d5729fcba5677c79037b459436ab7bff709c9d06ce9f10c1a9dd6f21326ab749d5729fcba5677c79037b459436ab7bff709c9d06ce9f10c1a9bd6f21326ab749d5729fcba5677c79037b459436ab7bff709c9d06ce9f10c1a9c0200000000000000000000000000000000000020000000000000000000000000d6f21326ab749d5729fcba5677c79037b459436ab7bff709c9d06ce9f10c1a9fd6f21326ab749d5729fcba5677c79037b459436ab7bff709c9d06ce9f10c1a9eb2a1462b8d912a9fe495da7a1188c48bb87bac4644a0931aa4ce2dd7017ce365ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff00ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff000000000000000000000000000000000000000000000000ffffffffffffff60000000000000000000000000000000000000000000000000ffffffffffffff5f6f756e64730000000000000000000000000000000000000000000000000000004f6666736574202b2034206d7573742062652077697468696e20646174612062fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffb76736dd10bee905a6f3ecda0ef1596e6fed3c032ca0c5734d070ab4dc7eb8bca
Loading...
Loading
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ 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.