Sepolia Testnet

Contract

0xf52BC7bE133a4CB3799Bfe6399bc576465f28153

Overview

ETH Balance

0.001 ETH

Multichain Info

N/A
Transaction Hash
Method
Block
From
To
Settle64942732024-08-13 20:20:4862 days ago1723580448IN
0xf52BC7bE...465f28153
0 ETH0.000448982.79730428
Bid For Coverage64942692024-08-13 20:20:0062 days ago1723580400IN
0xf52BC7bE...465f28153
0.002 ETH0.000239662.77099546
Apply For Covera...64942672024-08-13 20:19:3662 days ago1723580376IN
0xf52BC7bE...465f28153
0.001 ETH0.00053132.77548698
Apply For Covera...64942292024-08-13 20:11:0062 days ago1723579860IN
0xf52BC7bE...465f28153
0.001 ETH0.000502082.62281938
Settle64390172024-08-05 2:27:3671 days ago1722824856IN
0xf52BC7bE...465f28153
0 ETH0.000838055.24331164
Bid For Coverage64390122024-08-05 2:26:3671 days ago1722824796IN
0xf52BC7bE...465f28153
0.002 ETH0.00050775.87006918
Apply For Covera...64389872024-08-05 2:20:3671 days ago1722824436IN
0xf52BC7bE...465f28153
0.001 ETH0.000948554.95517578
Settle64365552024-08-04 17:03:4871 days ago1722791028IN
0xf52BC7bE...465f28153
0 ETH0.000865415.41448562
Bid For Coverage64365542024-08-04 17:03:3671 days ago1722791016IN
0xf52BC7bE...465f28153
0.002 ETH0.000484335.59985504
Apply For Covera...64365522024-08-04 17:03:1271 days ago1722790992IN
0xf52BC7bE...465f28153
0.001 ETH0.001165196.08685745
Settle64332462024-08-04 4:24:0072 days ago1722745440IN
0xf52BC7bE...465f28153
0 ETH0.000322832.01980655
Bid For Coverage64332032024-08-04 4:14:2472 days ago1722744864IN
0xf52BC7bE...465f28153
0.002 ETH0.000110491.27753114
Apply For Covera...64332022024-08-04 4:14:0072 days ago1722744840IN
0xf52BC7bE...465f28153
0.001 ETH0.000244051.27492169
Settle64331962024-08-04 4:12:4872 days ago1722744768IN
0xf52BC7bE...465f28153
0 ETH0.000215541.34857484
Bid For Coverage64331952024-08-04 4:12:3672 days ago1722744756IN
0xf52BC7bE...465f28153
0.002 ETH0.000134111.55062337
Apply For Covera...64331892024-08-04 4:11:2472 days ago1722744684IN
0xf52BC7bE...465f28153
0.001 ETH0.000376731.96803661
Settle64327842024-08-04 2:42:2472 days ago1722739344IN
0xf52BC7bE...465f28153
0 ETH0.000683014.27326918
Bid For Coverage64327822024-08-04 2:42:0072 days ago1722739320IN
0xf52BC7bE...465f28153
0.002 ETH0.000364154.21039282
Apply For Covera...64327802024-08-04 2:41:3672 days ago1722739296IN
0xf52BC7bE...465f28153
0.001 ETH0.000782394.08717257
Settle64327602024-08-04 2:36:4872 days ago1722739008IN
0xf52BC7bE...465f28153
0 ETH0.000633553.96384125
Bid For Coverage64327582024-08-04 2:36:2472 days ago1722738984IN
0xf52BC7bE...465f28153
0.002 ETH0.000294943.41021394
Apply For Covera...64327562024-08-04 2:36:0072 days ago1722738960IN
0xf52BC7bE...465f28153
0.001 ETH0.000645733.37326236
0x6080604064327512024-08-04 2:34:4872 days ago1722738888IN
 Create: InsuranceBroker
0 ETH0.011669143.64406605

Latest 7 internal transactions

Advanced mode:
Parent Transaction Hash Block From To
64942742024-08-13 20:21:0062 days ago1723580460
0xf52BC7bE...465f28153
0.003 ETH
64390192024-08-05 2:28:0071 days ago1722824880
0xf52BC7bE...465f28153
0.003 ETH
64365562024-08-04 17:04:1271 days ago1722791052
0xf52BC7bE...465f28153
0.003 ETH
64332482024-08-04 4:24:3672 days ago1722745476
0xf52BC7bE...465f28153
0.003 ETH
64331972024-08-04 4:13:0072 days ago1722744780
0xf52BC7bE...465f28153
0.003 ETH
64327872024-08-04 2:43:1272 days ago1722739392
0xf52BC7bE...465f28153
0.003 ETH
64327632024-08-04 2:37:2472 days ago1722739044
0xf52BC7bE...465f28153
0.003 ETH
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
InsuranceBroker

Compiler Version
v0.8.25+commit.b61c2a91

Optimization Enabled:
Yes with 10000 runs

Other Settings:
paris EvmVersion

Contract Source Code (Solidity Standard Json-Input format)

File 1 of 6 : InsuranceBroker.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.25;

import {OdfRequest, OdfResponse, IOdfClient, CborReader} from "@opendatafabric/contracts/src/Odf.sol";
// import { console2 } from "forge-std/src/console2.sol";

// Example weather insurance broker contract
contract InsuranceBroker {
    event CoverageApplication(
        uint64 indexed policyId,
        address indexed holder,
        uint holderDeposit
    );

    event PolicyCreated(
        uint64 indexed policyId,
        address indexed holder,
        address indexed insurer,
        uint holderDeposit,
        uint insurerDeposit
    );

    event PolicySettlementInitiated(
        uint64 indexed policyId,
        address indexed holder,
        address indexed insurer,
        uint holderDeposit,
        uint insurerDeposit,
        uint64 dataRequestId
    );

    event PolicySettled(
        uint64 indexed policyId,
        address indexed holder,
        address indexed insurer,
        uint holderDeposit,
        uint insurerDeposit,
        uint64 dataRequestId,
        bool holderClaims
    );

    struct Policy {
        // Identifies the insurance policy
        uint64 policyId;
        // Applicant / beneficiary of the insurance payment and their deposit / premium / cost of the insurance
        address payable holder;
        uint holderDeposit;
        // Underwriter of the insurance and their deposit / settlement amount
        address payable insurer;
        uint insurerDeposit;
        // Whether this policy already settled one way or another
        bool settled;
        // Minimal amount of rainfall that has to be observed for policy to settle in insurer's favor
        uint64 precipitationThreshold;
        // ID of the dataset to use for querying
        string datasetId;
    }

    address private _owner;
    IOdfClient private _oracle;

    uint64 private _lastPolicyId = 0;
    mapping(uint64 policyId => Policy policy) private _policies;
    mapping(uint64 requestId => uint64 policyId) private _dataRequests;

    // Initialize contract with the oracle address
    constructor(address oracleAddr) {
        _owner = msg.sender;
        _oracle = IOdfClient(oracleAddr);
    }

    function applyForCoverage(
        uint64 precipitationThreshold,
        string memory datasetId
    ) external payable returns (uint64) {
        require(msg.value != 0, "need to provide a deposit");

        _lastPolicyId += 1;
        Policy memory policy;
        policy.policyId = _lastPolicyId;
        policy.holder = payable(msg.sender);
        policy.holderDeposit = msg.value;
        policy.precipitationThreshold = precipitationThreshold;
        policy.datasetId = datasetId;

        _policies[policy.policyId] = policy;

        emit CoverageApplication(
            policy.policyId,
            policy.holder,
            policy.holderDeposit
        );

        return policy.policyId;
    }

    function bidForCoverage(uint64 policyId) external payable {
        Policy memory policy = _policies[policyId];

        require(policy.holder != address(0), "policy does not exist");
        require(policy.insurer == address(0), "policy was already accepted");
        require(!policy.settled, "policy was already settled");
        require(
            msg.value > policy.holderDeposit,
            "need to provide sufficient deposit"
        );

        policy.insurer = payable(msg.sender);
        policy.insurerDeposit = msg.value;
        _policies[policyId] = policy;

        emit PolicyCreated(
            policyId,
            policy.holder,
            policy.insurer,
            policy.holderDeposit,
            policy.insurerDeposit
        );
    }

    function settle(uint64 policyId) external returns (uint64) {
        Policy memory policy = _policies[policyId];

        require(policy.holder != address(0), "policy does not exist");

        require(!policy.settled, "policy was already settled");

        // policy was not accepted by an insusrer?
        if (policy.insurer == address(0)) {
            // Return the deposit to the applicant
            policy.settled = true;
            _policies[policyId] = policy;
            policy.holder.transfer(policy.holderDeposit);
            return 0;
        }

        // Request data from the oracle
        OdfRequest.Req memory req = OdfRequest.init();

        // Specify ID of the dataset(s) we will be querying.
        // Repeat this call for multiple inputs.
        req.dataset("weather_stations", policy.datasetId);

        // Specify an arbitrary complex SQL query.
        // Queries can include even JOINs
        req.sql(
            "select "
            "cast(floor(avg(precipitation_accumulated)) as bigint) "
            "from ( "
            "select "
            "device_id, max(precipitation_accumulated) as precipitation_accumulated "
            "from weather_stations "
            "group by device_id "
            ") "
        );

        // Send request to the oracle and specify a callback
        uint64 dataRequestId = _oracle.sendRequest(req, this.onResult);
        _dataRequests[dataRequestId] = policyId;

        emit PolicySettlementInitiated(
            policy.policyId,
            policy.holder,
            policy.insurer,
            policy.holderDeposit,
            policy.insurerDeposit,
            dataRequestId
        );

        return dataRequestId;
    }

    // This function will be called by the oracle when request is fulfilled
    function onResult(OdfResponse.Res memory result) external {
        require(msg.sender == address(_oracle), "Can only be called by oracle");

        uint64 policyId = _dataRequests[result.requestId()];
        require(policyId != 0, "corresponding policy not found");

        Policy memory policy = _policies[policyId];
        require(
            policy.holder != address(0) && policy.insurer != address(0),
            "policy is in invalid state"
        );
        require(!policy.settled, "policy already settled");

        require(result.numRecords() == 1, "Expected one record");

        CborReader.CBOR[] memory record = result.record(0);
        uint64 precipitationActual = uint64(int64(record[0].readInt()));

        bool holderClaims = precipitationActual < policy.precipitationThreshold;

        policy.settled = true;
        _policies[policyId] = policy;

        emit PolicySettled(
            policy.policyId,
            policy.holder,
            policy.insurer,
            policy.holderDeposit,
            policy.insurerDeposit,
            result.requestId(),
            holderClaims
        );

        if (holderClaims) {
            policy.holder.transfer(
                policy.holderDeposit + policy.insurerDeposit
            );
        } else {
            policy.insurer.transfer(
                policy.holderDeposit + policy.insurerDeposit
            );
        }
    }

    function withdraw() external {
        require(msg.sender == _owner, "Only owner can withdraw");
        payable(_owner).transfer(address(this).balance);
    }

    using OdfRequest for OdfRequest.Req;
    using OdfResponse for OdfResponse.Res;
    using CborReader for CborReader.CBOR;
}

File 2 of 6 : Odf.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.25;

import { OdfRequest, CborWriter } from "./OdfRequest.sol";
import { OdfResponse, CborReader } from "./OdfResponse.sol";

////////////////////////////////////////////////////////////////////////////////////////

// Interface used by client contracts
interface IOdfClient {
    // Current contract was disabled and you need to upgrade to a new one
    error ContractDisabled();

    // Called by the clients to request off-chain data
    function sendRequest(
        OdfRequest.Req memory request,
        function(OdfResponse.Res memory) external callback
    )
        external
        payable
        returns (uint64);
}

////////////////////////////////////////////////////////////////////////////////////////

// Interface used by data providers
interface IOdfProvider {
    // Emitted when client request was made and awaits a response
    event SendRequest(uint64 indexed requestId, address indexed consumerAddr, bytes request);

    // Emitted when a provider fulfills a pending request.
    //
    // Fields:
    // - requestId - unique identifier of the request
    // - consumerAddr - address of the contract that sent request and awaits the response
    // - providerAddr - address of the provider that fulfilled the request
    // - response - response data, see `OdfResponse`
    // - requestError - indicates that response contained an unrecoverable error instead of data
    // - consumerError - indicates that consumer callback has failed when processing the result
    // - consumerErrorData - will contain the details of consumer-side error
    event ProvideResult(
        uint64 indexed requestId,
        address indexed consumerAddr,
        address indexed providerAddr,
        bytes response,
        bool requestError,
        bool consumerError,
        bytes consumerErrorData
    );

    // Returned when provider was not registered to provide results to the oracle
    error UnauthorizedProvider(address providerAddr);

    // Returned when pending request by this ID is not found
    error RequestNotFound(uint64 requestId);

    // Returns true/false whether `addr` is authorized to provide results to this oracle
    function canProvideResults(address addr) external view returns (bool);

    // Called to fulfill a pending request
    // See `OdfResponse` for explanation of the `result`
    function provideResult(uint64 requestId, bytes calldata result) external;
}

////////////////////////////////////////////////////////////////////////////////////////

// Interface used by oracle admins
interface IOdfAdmin {
    // Emitted when a provider is authorized
    event AddProvider(address indexed providerAddr);

    // Emitted when a provider authorization is revoked
    event RemoveProvider(address indexed providerAddr);

    // Authorizes a provider to supply results
    function addProvider(address providerAddr) external;

    // Revoke the authorization from a provider to supply results
    function removeProvider(address providerAddr) external;
}

////////////////////////////////////////////////////////////////////////////////////////

File 3 of 6 : OdfRequest.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.25;

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

////////////////////////////////////////////////////////////////////////////////////////

// ODF Oracle request builder.
//
// Example use:
//
//   using OdfRequest for OdfRequest.Req;
//
//   OdfRequest.Req memory req = OdfRequest.init();
//   req.dataset(
//       "my_temp_sensor",
//       "did:odf:fed014895afeb476d5d94c1af0668f30ab661c8561760bba6744e43225ba52e099595"
//   );
//   req.sql(
//       "select event_time, value "
//       "from my_temp_sensor "
//       "order by offset desc "
//       "limit 1"
//   );
//   oracle.sendRequest(req, this.callback);
//
// Requests are represented as a CBOR-encoded flat array that carries all the parameters:
//
//   [
//     version,
//     "ds", "alias1", b"did:odf:x",
//     "ds", "alias2", b"did:odf:y",
//     "sql", "select ...",
//     ...
//   ]
//
// The `dataset` method MUST be used to associate all intput aliases with their IDs to
// both avoid the risks of getting wrong data is dataset is renamed, and to allow
// providers quickly test in they have necessary data to satisfy the request.
//
// Note that DIDs are encoded as binaries to save space.
//
library OdfRequest {
    using CborWriter for CborWriter.CBORBuffer;

    // Protocol version - always written as the first element of the CBOR array.
    uint16 public constant VERSION = 1;

    struct Req {
        CborWriter.CBORBuffer _buf;
    }

    // Creates a new empty request with protocol version set
    function init() internal pure returns (Req memory) {
        CborWriter.CBORBuffer memory buf = CborWriter.create(1024);
        buf.startArray();
        buf.writeUInt64(VERSION);
        return Req(buf);
    }

    // Finishes construction of the request returning the bytes representation
    function intoBytes(Req memory self) internal pure returns (bytes memory) {
        self._buf.endSequence();
        return self._buf.data();
    }

    // Specifies the SQL query (only one query is allowed per request)
    function sql(Req memory self, string memory _sql) internal pure {
        self._buf.writeString("sql");
        self._buf.writeString(_sql);
    }

    // Associates an alias used in the query with a specific ODF dataset ID.
    //
    // Example:
    //
    //   req.dataset(
    //      "foo",
    //      "did:odf:fed014895afeb476d5d94c1af0668f30ab661c8561760bba6744e43225ba52e099595"
    //   )
    //
    // If you don't want to pay for the cost of DID parsing - use `datasetRaw()` function.
    function dataset(Req memory self, string memory _alias, string memory _did) internal pure {
        bytes memory didBin = didToBytes(_did);
        datasetRaw(self, _alias, didBin);
    }

    // Associates an alias used in the query with a specific ODF dataset ID given in binary form.
    //
    // Example:
    //
    //   req.datasetRaw(
    //      "foo",
    //      hex"ed014895afeb476d5d94c1af0668f30ab661c8561760bba6744e43225ba52e099595"
    //   )
    //
    // If you don't want to pay for the cost of DID parsing - use `datasetRaw()` function.
    function datasetRaw(Req memory self, string memory _alias, bytes memory _did) internal pure {
        self._buf.writeString("ds");
        self._buf.writeString(_alias);
        self._buf.writeBytes(_did);
    }

    // solhint-disable custom-errors
    function didToBytes(string memory _did) private pure returns (bytes memory) {
        bytes memory bin = bytes(_did);

        require(bin.length == 77, "Invalid DID");
        require(bytes9(bin) == "did:odf:f", "Invalid DID");

        bytes memory result = new bytes(34);

        for (uint16 i = 0; i < 34; i++) {
            uint16 s = i * 2 + 9;
            result[i] = bytes1((hexToInt(bin[s]) << 4) + hexToInt(bin[s + 1]));
        }

        return result;
    }

    // solhint-disable custom-errors
    function hexToInt(bytes1 c) public pure returns (uint8) {
        if (c >= bytes1("0") && c <= bytes1("9")) {
            return uint8(c) - uint8(bytes1("0"));
        }
        if (bytes1(c) >= bytes1("a") && bytes1(c) <= bytes1("f")) {
            return 10 + uint8(c) - uint8(bytes1("a"));
        }
        if (bytes1(c) >= bytes1("A") && bytes1(c) <= bytes1("F")) {
            return 10 + uint8(c) - uint8(bytes1("A"));
        }
        revert("Not a hex char");
    }
}

////////////////////////////////////////////////////////////////////////////////////////

File 4 of 6 : OdfResponse.sol
// SPDX-License-Identifier: UNLICENSED
pragma solidity ^0.8.25;

import { CborReader } from "./CborReader.sol";
import { CborWriter } from "./CborWriter.sol";

////////////////////////////////////////////////////////////////////////////////////////

// Responses are deserialized from CBOR with data using the Array-of-Arrays
// representation. State information is included that makes requests reproducible
// and verifiable.
//
// The successful response structure is as follows:
//
// [
//   1, // version
//   true, // success
//   [
//     [<row1-col1>, <row1-col2>, ...],
//     [<row2-col1>, <row2-col2>, ...],
//     ...
//   ],
//   b"data-logical-multihash",
//   [
//     b"odf:did:x", b"block1-multihash",
//     b"odf:did:y", b"block2-multihash",
//     ...
//   ]
// ]
//
// The unsuccessful response structure is:
//
// [
//   1, // version
//   false, // error
//   "SQL query error ..." // error message
// ]
//
// Note that DIDs and Multihashes are encoded as binaries to save space.
//
library OdfResponse {
    using CborReader for CborReader.CBOR;
    using CborWriter for CborWriter.CBORBuffer;

    uint16 public constant VERSION = 1;

    struct Res {
        uint64 _requestId;
        bool _ok;
        CborReader.CBOR[] _data;
        string _errorMessage;
    }

    // solhint-disable custom-errors
    function fromBytes(uint64 reqId, bytes memory data) internal pure returns (Res memory) {
        Res memory res;
        res._requestId = reqId;
        CborReader.CBOR[] memory root = CborReader.fromBytes(data).readArray();

        // NOTE: witnet library adds extra item to the end
        require(root.length == 5 + 1 || root.length == 3 + 1, "Invalid length");

        uint256 version = root[0].readUint();
        require(version == VERSION, "Unsupported response version");

        res._ok = root[1].readBool();
        if (res._ok) {
            res._data = root[2].readArray();
        } else {
            res._errorMessage = root[2].readString();
        }

        return res;
    }

    function requestId(Res memory self) internal pure returns (uint64) {
        return self._requestId;
    }

    // Tells whether result was successful and contains data or an error
    function ok(Res memory self) internal pure returns (bool) {
        return self._ok;
    }

    // Error message associated with unsuccessful response
    function errorMessage(Res memory self) internal pure returns (string memory) {
        return self._errorMessage;
    }

    function numRecords(Res memory self) internal pure returns (uint64) {
        // NOTE: witnet library adds extra item to the end
        return uint64(self._data.length - 1);
    }

    function records(Res memory self) internal pure returns (CborReader.CBOR[] memory) {
        return self._data;
    }

    function record(Res memory self, uint64 i) internal pure returns (CborReader.CBOR[] memory) {
        return self._data[i].readArray();
    }

    // For testing: constructs an empty successful response
    function empty(uint64 reqId) internal pure returns (Res memory) {
        Res memory res;
        res._requestId = reqId;
        res._ok = true;
        // NOTE: witnet library adds extra item to the end
        res._data = new CborReader.CBOR[](1);
        return res;
    }

    // For testing: constructs an unsuccessful response with specified error message
    function error(uint64 reqId, string memory errMessage) internal pure returns (Res memory) {
        Res memory res;
        res._requestId = reqId;
        res._ok = false;
        res._errorMessage = errMessage;
        return res;
    }

    // For testing: converts a response to bytes
    function intoBytes(Res memory self) internal pure returns (bytes memory) {
        CborWriter.CBORBuffer memory buf = CborWriter.create(1024);
        buf.startArray();
        buf.writeBool(self._ok);
        if (self._ok) {
            // Only supports empty data, hash, and state
            buf.startArray();
            buf.endSequence();
            buf.writeString("");
            buf.startArray();
            buf.endSequence();
        } else {
            buf.writeString(self._errorMessage);
        }
        buf.endSequence();
        return buf.data();
    }
}

////////////////////////////////////////////////////////////////////////////////////////

File 5 of 6 : CborWriter.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.25;

/**
 * @dev Vendored CBOR writing utils. Copied from
 * [solidity-cborutils](https://github.com/smartcontractkit/solidity-cborutils).
 *
 */
library CborWriter {
    using Buffer for Buffer.buffer;

    struct CBORBuffer {
        Buffer.buffer buf;
        uint256 depth;
    }

    uint8 private constant MAJOR_TYPE_INT = 0;
    uint8 private constant MAJOR_TYPE_NEGATIVE_INT = 1;
    uint8 private constant MAJOR_TYPE_BYTES = 2;
    uint8 private constant MAJOR_TYPE_STRING = 3;
    uint8 private constant MAJOR_TYPE_ARRAY = 4;
    uint8 private constant MAJOR_TYPE_MAP = 5;
    uint8 private constant MAJOR_TYPE_TAG = 6;
    uint8 private constant MAJOR_TYPE_CONTENT_FREE = 7;

    uint8 private constant TAG_TYPE_BIGNUM = 2;
    uint8 private constant TAG_TYPE_NEGATIVE_BIGNUM = 3;

    uint8 private constant CBOR_FALSE = 20;
    uint8 private constant CBOR_TRUE = 21;
    uint8 private constant CBOR_NULL = 22;
    uint8 private constant CBOR_UNDEFINED = 23;

    function create(uint256 capacity) internal pure returns (CBORBuffer memory cbor) {
        Buffer.init(cbor.buf, capacity);
        cbor.depth = 0;
        return cbor;
    }

    function data(CBORBuffer memory buf) internal pure returns (bytes memory) {
        require(buf.depth == 0, "Invalid CBOR");
        return buf.buf.buf;
    }

    function writeUInt256(CBORBuffer memory buf, uint256 value) internal pure {
        buf.buf.appendUint8(uint8((MAJOR_TYPE_TAG << 5) | TAG_TYPE_BIGNUM));
        writeBytes(buf, abi.encode(value));
    }

    function writeInt256(CBORBuffer memory buf, int256 value) internal pure {
        if (value < 0) {
            buf.buf.appendUint8(uint8((MAJOR_TYPE_TAG << 5) | TAG_TYPE_NEGATIVE_BIGNUM));
            writeBytes(buf, abi.encode(uint256(-1 - value)));
        } else {
            writeUInt256(buf, uint256(value));
        }
    }

    function writeUInt64(CBORBuffer memory buf, uint64 value) internal pure {
        writeFixedNumeric(buf, MAJOR_TYPE_INT, value);
    }

    function writeInt64(CBORBuffer memory buf, int64 value) internal pure {
        if (value >= 0) {
            writeFixedNumeric(buf, MAJOR_TYPE_INT, uint64(value));
        } else {
            writeFixedNumeric(buf, MAJOR_TYPE_NEGATIVE_INT, uint64(-1 - value));
        }
    }

    function writeBytes(CBORBuffer memory buf, bytes memory value) internal pure {
        writeFixedNumeric(buf, MAJOR_TYPE_BYTES, uint64(value.length));
        buf.buf.append(value);
    }

    function writeString(CBORBuffer memory buf, string memory value) internal pure {
        writeFixedNumeric(buf, MAJOR_TYPE_STRING, uint64(bytes(value).length));
        buf.buf.append(bytes(value));
    }

    function writeBool(CBORBuffer memory buf, bool value) internal pure {
        writeContentFree(buf, value ? CBOR_TRUE : CBOR_FALSE);
    }

    function writeNull(CBORBuffer memory buf) internal pure {
        writeContentFree(buf, CBOR_NULL);
    }

    function writeUndefined(CBORBuffer memory buf) internal pure {
        writeContentFree(buf, CBOR_UNDEFINED);
    }

    function startArray(CBORBuffer memory buf) internal pure {
        writeIndefiniteLengthType(buf, MAJOR_TYPE_ARRAY);
        buf.depth += 1;
    }

    function startFixedArray(CBORBuffer memory buf, uint64 length) internal pure {
        writeDefiniteLengthType(buf, MAJOR_TYPE_ARRAY, length);
    }

    function startMap(CBORBuffer memory buf) internal pure {
        writeIndefiniteLengthType(buf, MAJOR_TYPE_MAP);
        buf.depth += 1;
    }

    function startFixedMap(CBORBuffer memory buf, uint64 length) internal pure {
        writeDefiniteLengthType(buf, MAJOR_TYPE_MAP, length);
    }

    function endSequence(CBORBuffer memory buf) internal pure {
        writeIndefiniteLengthType(buf, MAJOR_TYPE_CONTENT_FREE);
        buf.depth -= 1;
    }

    function writeKVString(
        CBORBuffer memory buf,
        string memory key,
        string memory value
    )
        internal
        pure
    {
        writeString(buf, key);
        writeString(buf, value);
    }

    function writeKVBytes(
        CBORBuffer memory buf,
        string memory key,
        bytes memory value
    )
        internal
        pure
    {
        writeString(buf, key);
        writeBytes(buf, value);
    }

    function writeKVUInt256(
        CBORBuffer memory buf,
        string memory key,
        uint256 value
    )
        internal
        pure
    {
        writeString(buf, key);
        writeUInt256(buf, value);
    }

    function writeKVInt256(CBORBuffer memory buf, string memory key, int256 value) internal pure {
        writeString(buf, key);
        writeInt256(buf, value);
    }

    function writeKVUInt64(CBORBuffer memory buf, string memory key, uint64 value) internal pure {
        writeString(buf, key);
        writeUInt64(buf, value);
    }

    function writeKVInt64(CBORBuffer memory buf, string memory key, int64 value) internal pure {
        writeString(buf, key);
        writeInt64(buf, value);
    }

    function writeKVBool(CBORBuffer memory buf, string memory key, bool value) internal pure {
        writeString(buf, key);
        writeBool(buf, value);
    }

    function writeKVNull(CBORBuffer memory buf, string memory key) internal pure {
        writeString(buf, key);
        writeNull(buf);
    }

    function writeKVUndefined(CBORBuffer memory buf, string memory key) internal pure {
        writeString(buf, key);
        writeUndefined(buf);
    }

    function writeKVMap(CBORBuffer memory buf, string memory key) internal pure {
        writeString(buf, key);
        startMap(buf);
    }

    function writeKVArray(CBORBuffer memory buf, string memory key) internal pure {
        writeString(buf, key);
        startArray(buf);
    }

    function writeFixedNumeric(CBORBuffer memory buf, uint8 major, uint64 value) private pure {
        if (value <= 23) {
            buf.buf.appendUint8(uint8((major << 5) | value));
        } else if (value <= 0xFF) {
            buf.buf.appendUint8(uint8((major << 5) | 24));
            buf.buf.appendInt(value, 1);
        } else if (value <= 0xFFFF) {
            buf.buf.appendUint8(uint8((major << 5) | 25));
            buf.buf.appendInt(value, 2);
        } else if (value <= 0xFFFFFFFF) {
            buf.buf.appendUint8(uint8((major << 5) | 26));
            buf.buf.appendInt(value, 4);
        } else {
            buf.buf.appendUint8(uint8((major << 5) | 27));
            buf.buf.appendInt(value, 8);
        }
    }

    function writeIndefiniteLengthType(CBORBuffer memory buf, uint8 major) private pure {
        buf.buf.appendUint8(uint8((major << 5) | 31));
    }

    function writeDefiniteLengthType(
        CBORBuffer memory buf,
        uint8 major,
        uint64 length
    )
        private
        pure
    {
        writeFixedNumeric(buf, major, length);
    }

    function writeContentFree(CBORBuffer memory buf, uint8 value) private pure {
        buf.buf.appendUint8(uint8((MAJOR_TYPE_CONTENT_FREE << 5) | value));
    }
}

/**
 * @dev A library for working with mutable byte buffers in Solidity.
 *
 * Copied from https://github.com/ensdomains/buffer
 *
 */
library Buffer {
    /**
     * @dev Represents a mutable buffer. Buffers have a current value (buf) and
     *      a capacity. The capacity may be longer than the current value, in
     *      which case it can be extended without the need to allocate more memory.
     */
    struct buffer {
        bytes buf;
        uint256 capacity;
    }

    /**
     * @dev Initializes a buffer with an initial capacity.
     * @param buf The buffer to initialize.
     * @param capacity The number of bytes of space to allocate the buffer.
     * @return The buffer, for chaining.
     */
    function init(buffer memory buf, uint256 capacity) internal pure returns (buffer memory) {
        if (capacity % 32 != 0) {
            capacity += 32 - (capacity % 32);
        }
        // Allocate space for the buffer data
        buf.capacity = capacity;
        assembly {
            let ptr := mload(0x40)
            mstore(buf, ptr)
            mstore(ptr, 0)
            let fpm := add(32, add(ptr, capacity))
            if lt(fpm, ptr) { revert(0, 0) }
            mstore(0x40, fpm)
        }
        return buf;
    }

    /**
     * @dev Initializes a new buffer from an existing bytes object.
     *      Changes to the buffer may mutate the original value.
     * @param b The bytes object to initialize the buffer with.
     * @return A new buffer.
     */
    function fromBytes(bytes memory b) internal pure returns (buffer memory) {
        buffer memory buf;
        buf.buf = b;
        buf.capacity = b.length;
        return buf;
    }

    function resize(buffer memory buf, uint256 capacity) private pure {
        bytes memory oldbuf = buf.buf;
        init(buf, capacity);
        append(buf, oldbuf);
    }

    /**
     * @dev Sets buffer length to 0.
     * @param buf The buffer to truncate.
     * @return The original buffer, for chaining..
     */
    function truncate(buffer memory buf) internal pure returns (buffer memory) {
        assembly {
            let bufptr := mload(buf)
            mstore(bufptr, 0)
        }
        return buf;
    }

    /**
     * @dev Appends len bytes of a byte string to a buffer. Resizes if doing so would exceed
     *      the capacity of the buffer.
     * @param buf The buffer to append to.
     * @param data The data to append.
     * @param len The number of bytes to copy.
     * @return The original buffer, for chaining.
     */
    function append(
        buffer memory buf,
        bytes memory data,
        uint256 len
    )
        internal
        pure
        returns (buffer memory)
    {
        require(len <= data.length);

        uint256 off = buf.buf.length;
        uint256 newCapacity = off + len;
        if (newCapacity > buf.capacity) {
            resize(buf, newCapacity * 2);
        }

        uint256 dest;
        uint256 src;
        assembly {
            // Memory address of the buffer data
            let bufptr := mload(buf)
            // Length of existing buffer data
            let buflen := mload(bufptr)
            // Start address = buffer address + offset + sizeof(buffer length)
            dest := add(add(bufptr, 32), off)
            // Update buffer length if we're extending it
            if gt(newCapacity, buflen) { mstore(bufptr, newCapacity) }
            src := add(data, 32)
        }

        // Copy word-length chunks while possible
        for (; len >= 32; len -= 32) {
            assembly {
                mstore(dest, mload(src))
            }
            dest += 32;
            src += 32;
        }

        // Copy remaining bytes
        unchecked {
            uint256 mask = (256 ** (32 - len)) - 1;
            assembly {
                let srcpart := and(mload(src), not(mask))
                let destpart := and(mload(dest), mask)
                mstore(dest, or(destpart, srcpart))
            }
        }

        return buf;
    }

    /**
     * @dev Appends a byte string to a buffer. Resizes if doing so would exceed
     *      the capacity of the buffer.
     * @param buf The buffer to append to.
     * @param data The data to append.
     * @return The original buffer, for chaining.
     */
    function append(buffer memory buf, bytes memory data) internal pure returns (buffer memory) {
        return append(buf, data, data.length);
    }

    /**
     * @dev Appends a byte to the buffer. Resizes if doing so would exceed the
     *      capacity of the buffer.
     * @param buf The buffer to append to.
     * @param data The data to append.
     * @return The original buffer, for chaining.
     */
    function appendUint8(buffer memory buf, uint8 data) internal pure returns (buffer memory) {
        uint256 off = buf.buf.length;
        uint256 offPlusOne = off + 1;
        if (off >= buf.capacity) {
            resize(buf, offPlusOne * 2);
        }

        assembly {
            // Memory address of the buffer data
            let bufptr := mload(buf)
            // Address = buffer address + sizeof(buffer length) + off
            let dest := add(add(bufptr, off), 32)
            mstore8(dest, data)
            // Update buffer length if we extended it
            if gt(offPlusOne, mload(bufptr)) { mstore(bufptr, offPlusOne) }
        }

        return buf;
    }

    /**
     * @dev Appends len bytes of bytes32 to a buffer. Resizes if doing so would
     *      exceed the capacity of the buffer.
     * @param buf The buffer to append to.
     * @param data The data to append.
     * @param len The number of bytes to write (left-aligned).
     * @return The original buffer, for chaining.
     */
    function append(
        buffer memory buf,
        bytes32 data,
        uint256 len
    )
        private
        pure
        returns (buffer memory)
    {
        uint256 off = buf.buf.length;
        uint256 newCapacity = len + off;
        if (newCapacity > buf.capacity) {
            resize(buf, newCapacity * 2);
        }

        unchecked {
            uint256 mask = (256 ** len) - 1;
            // Right-align data
            data = data >> (8 * (32 - len));
            assembly {
                // Memory address of the buffer data
                let bufptr := mload(buf)
                // Address = buffer address + sizeof(buffer length) + newCapacity
                let dest := add(bufptr, newCapacity)
                mstore(dest, or(and(mload(dest), not(mask)), data))
                // Update buffer length if we extended it
                if gt(newCapacity, mload(bufptr)) { mstore(bufptr, newCapacity) }
            }
        }
        return buf;
    }

    /**
     * @dev Appends a bytes20 to the buffer. Resizes if doing so would exceed
     *      the capacity of the buffer.
     * @param buf The buffer to append to.
     * @param data The data to append.
     * @return The original buffer, for chhaining.
     */
    function appendBytes20(buffer memory buf, bytes20 data) internal pure returns (buffer memory) {
        return append(buf, bytes32(data), 20);
    }

    /**
     * @dev Appends a bytes32 to the buffer. Resizes if doing so would exceed
     *      the capacity of the buffer.
     * @param buf The buffer to append to.
     * @param data The data to append.
     * @return The original buffer, for chaining.
     */
    function appendBytes32(buffer memory buf, bytes32 data) internal pure returns (buffer memory) {
        return append(buf, data, 32);
    }

    /**
     * @dev Appends a byte to the end of the buffer. Resizes if doing so would
     *      exceed the capacity of the buffer.
     * @param buf The buffer to append to.
     * @param data The data to append.
     * @param len The number of bytes to write (right-aligned).
     * @return The original buffer.
     */
    function appendInt(
        buffer memory buf,
        uint256 data,
        uint256 len
    )
        internal
        pure
        returns (buffer memory)
    {
        uint256 off = buf.buf.length;
        uint256 newCapacity = len + off;
        if (newCapacity > buf.capacity) {
            resize(buf, newCapacity * 2);
        }

        uint256 mask = (256 ** len) - 1;
        assembly {
            // Memory address of the buffer data
            let bufptr := mload(buf)
            // Address = buffer address + sizeof(buffer length) + newCapacity
            let dest := add(bufptr, newCapacity)
            mstore(dest, or(and(mload(dest), not(mask)), data))
            // Update buffer length if we extended it
            if gt(newCapacity, mload(bufptr)) { mstore(bufptr, newCapacity) }
        }
        return buf;
    }
}

File 6 of 6 : CborReader.sol
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.25;

/**
 * @dev Vendored CBOR reading utils. Copied from
 * [witnet-solidity-bridge](https://github.com/witnet/witnet-solidity-bridge/).
 */
library CborReader {
    using WitnetBuffer for WitnetBuffer.Buffer;
    using CborReader for CborReader.CBOR;

    /// Data struct following the RFC-7049 standard: Concise Binary Object Representation.
    struct CBOR {
        WitnetBuffer.Buffer buffer;
        uint8 initialByte;
        uint8 majorType;
        uint8 additionalInformation;
        uint64 len;
        uint64 tag;
    }

    uint8 internal constant MAJOR_TYPE_INT = 0;
    uint8 internal constant MAJOR_TYPE_NEGATIVE_INT = 1;
    uint8 internal constant MAJOR_TYPE_BYTES = 2;
    uint8 internal constant MAJOR_TYPE_STRING = 3;
    uint8 internal constant MAJOR_TYPE_ARRAY = 4;
    uint8 internal constant MAJOR_TYPE_MAP = 5;
    uint8 internal constant MAJOR_TYPE_TAG = 6;
    uint8 internal constant MAJOR_TYPE_CONTENT_FREE = 7;

    uint32 internal constant UINT32_MAX = type(uint32).max;
    uint64 internal constant UINT64_MAX = type(uint64).max;

    error EmptyArray();
    error InvalidLengthEncoding(uint256 length);
    error UnexpectedMajorType(uint256 read, uint256 expected);
    error UnsupportedPrimitive(uint256 primitive);
    error UnsupportedMajorType(uint256 unexpected);

    modifier isMajorType(CborReader.CBOR memory cbor, uint8 expected) {
        if (cbor.majorType != expected) {
            revert UnexpectedMajorType(cbor.majorType, expected);
        }
        _;
    }

    modifier notEmpty(WitnetBuffer.Buffer memory buffer) {
        if (buffer.data.length == 0) {
            revert WitnetBuffer.EmptyBuffer();
        }
        _;
    }

    function eof(CBOR memory cbor) internal pure returns (bool) {
        return cbor.buffer.cursor >= cbor.buffer.data.length;
    }

    /// @notice Decode a CBOR structure from raw bytes.
    /// @dev This is the main factory for CBOR instances, which can be later decoded into native EVM
    /// types.
    /// @param bytecode Raw bytes representing a CBOR-encoded value.
    /// @return A `CBOR` instance containing a partially decoded value.
    function fromBytes(bytes memory bytecode) internal pure returns (CBOR memory) {
        WitnetBuffer.Buffer memory buffer = WitnetBuffer.Buffer(bytecode, 0);
        return fromBuffer(buffer);
    }

    /// @notice Decode a CBOR structure from raw bytes.
    /// @dev This is an alternate factory for CBOR instances, which can be later decoded into native
    /// EVM types.
    /// @param buffer A Buffer structure representing a CBOR-encoded value.
    /// @return A `CBOR` instance containing a partially decoded value.
    function fromBuffer(WitnetBuffer.Buffer memory buffer)
        internal
        pure
        notEmpty(buffer)
        returns (CBOR memory)
    {
        uint8 initialByte;
        uint8 majorType = 255;
        uint8 additionalInformation;
        uint64 tag = UINT64_MAX;
        uint256 len;
        bool isTagged = true;
        while (isTagged) {
            // Extract basic CBOR properties from input bytes
            initialByte = buffer.readUint8();
            len++;
            majorType = initialByte >> 5;
            additionalInformation = initialByte & 0x1f;
            // Early CBOR tag parsing.
            if (majorType == MAJOR_TYPE_TAG) {
                uint256 _cursor = buffer.cursor;
                tag = readLength(buffer, additionalInformation);
                len += buffer.cursor - _cursor;
            } else {
                isTagged = false;
            }
        }
        if (majorType > MAJOR_TYPE_CONTENT_FREE) {
            revert UnsupportedMajorType(majorType);
        }
        return CBOR(buffer, initialByte, majorType, additionalInformation, uint64(len), tag);
    }

    function fork(CborReader.CBOR memory self) internal pure returns (CborReader.CBOR memory) {
        return CBOR({
            buffer: self.buffer.fork(),
            initialByte: self.initialByte,
            majorType: self.majorType,
            additionalInformation: self.additionalInformation,
            len: self.len,
            tag: self.tag
        });
    }

    function settle(CBOR memory self) internal pure returns (CborReader.CBOR memory) {
        if (!self.eof()) {
            return fromBuffer(self.buffer);
        } else {
            return self;
        }
    }

    function skip(CBOR memory self) internal pure returns (CborReader.CBOR memory) {
        if (
            self.majorType == MAJOR_TYPE_INT || self.majorType == MAJOR_TYPE_NEGATIVE_INT
                || (
                    self.majorType == MAJOR_TYPE_CONTENT_FREE && self.additionalInformation >= 25
                        && self.additionalInformation <= 27
                )
        ) {
            self.buffer.cursor += self.peekLength();
        } else if (self.majorType == MAJOR_TYPE_STRING || self.majorType == MAJOR_TYPE_BYTES) {
            uint64 len = readLength(self.buffer, self.additionalInformation);
            self.buffer.cursor += len;
        } else if (self.majorType == MAJOR_TYPE_ARRAY || self.majorType == MAJOR_TYPE_MAP) {
            self.len = readLength(self.buffer, self.additionalInformation);
        } else if (
            self.majorType != MAJOR_TYPE_CONTENT_FREE
                || (self.additionalInformation != 20 && self.additionalInformation != 21)
        ) {
            revert("CborReader.skip: unsupported major type");
        }
        return self;
    }

    function peekLength(CBOR memory self) internal pure returns (uint64) {
        if (self.additionalInformation < 24) {
            return 0;
        } else if (self.additionalInformation < 28) {
            return uint64(1 << (self.additionalInformation - 24));
        } else {
            revert InvalidLengthEncoding(self.additionalInformation);
        }
    }

    function readArray(CBOR memory self)
        internal
        pure
        isMajorType(self, MAJOR_TYPE_ARRAY)
        returns (CBOR[] memory items)
    {
        // read array's length and move self cursor forward to the first array element:
        uint64 len = readLength(self.buffer, self.additionalInformation);
        items = new CBOR[](len + 1);
        for (uint256 ix = 0; ix < len; ix++) {
            // settle next element in the array:
            self = self.settle();
            // fork it and added to the list of items to be returned:
            items[ix] = self.fork();
            if (self.majorType == MAJOR_TYPE_ARRAY) {
                CBOR[] memory _subitems = self.readArray();
                // move forward to the first element after inner array:
                self = _subitems[_subitems.length - 1];
            } else if (self.majorType == MAJOR_TYPE_MAP) {
                CBOR[] memory _subitems = self.readMap();
                // move forward to the first element after inner map:
                self = _subitems[_subitems.length - 1];
            } else {
                // move forward to the next element:
                self.skip();
            }
        }
        // return self cursor as extra item at the end of the list,
        // as to optimize recursion when jumping over nested arrays:
        items[len] = self;
    }

    function readMap(CBOR memory self)
        internal
        pure
        isMajorType(self, MAJOR_TYPE_MAP)
        returns (CBOR[] memory items)
    {
        // read number of items within the map and move self cursor forward to the first inner
        // element:
        uint64 len = readLength(self.buffer, self.additionalInformation) * 2;
        items = new CBOR[](len + 1);
        for (uint256 ix = 0; ix < len; ix++) {
            // settle next element in the array:
            self = self.settle();
            // fork it and added to the list of items to be returned:
            items[ix] = self.fork();
            if (ix % 2 == 0 && self.majorType != MAJOR_TYPE_STRING) {
                revert UnexpectedMajorType(self.majorType, MAJOR_TYPE_STRING);
            } else if (self.majorType == MAJOR_TYPE_ARRAY || self.majorType == MAJOR_TYPE_MAP) {
                CBOR[] memory _subitems =
                    (self.majorType == MAJOR_TYPE_ARRAY ? self.readArray() : self.readMap());
                // move forward to the first element after inner array or map:
                self = _subitems[_subitems.length - 1];
            } else {
                // move forward to the next element:
                self.skip();
            }
        }
        // return self cursor as extra item at the end of the list,
        // as to optimize recursion when jumping over nested arrays:
        items[len] = self;
    }

    /// Reads the length of the settle CBOR item from a buffer, consuming a different number of
    /// bytes depending on the
    /// value of the `additionalInformation` argument.
    function readLength(
        WitnetBuffer.Buffer memory buffer,
        uint8 additionalInformation
    )
        internal
        pure
        returns (uint64)
    {
        if (additionalInformation < 24) {
            return additionalInformation;
        }
        if (additionalInformation == 24) {
            return buffer.readUint8();
        }
        if (additionalInformation == 25) {
            return buffer.readUint16();
        }
        if (additionalInformation == 26) {
            return buffer.readUint32();
        }
        if (additionalInformation == 27) {
            return buffer.readUint64();
        }
        if (additionalInformation == 31) {
            return UINT64_MAX;
        }
        revert InvalidLengthEncoding(additionalInformation);
    }

    /// @notice Read a `CBOR` structure into a native `bool` value.
    /// @param cbor An instance of `CBOR`.
    /// @return The value represented by the input, as a `bool` value.
    function readBool(CBOR memory cbor)
        internal
        pure
        isMajorType(cbor, MAJOR_TYPE_CONTENT_FREE)
        returns (bool)
    {
        if (cbor.additionalInformation == 20) {
            return false;
        } else if (cbor.additionalInformation == 21) {
            return true;
        } else {
            revert UnsupportedPrimitive(cbor.additionalInformation);
        }
    }

    /// @notice Decode a `CBOR` structure into a native `bytes` value.
    /// @param cbor An instance of `CBOR`.
    /// @return output The value represented by the input, as a `bytes` value.
    function readBytes(CBOR memory cbor)
        internal
        pure
        isMajorType(cbor, MAJOR_TYPE_BYTES)
        returns (bytes memory output)
    {
        cbor.len = readLength(cbor.buffer, cbor.additionalInformation);
        if (cbor.len == UINT32_MAX) {
            // These checks look repetitive but the equivalent loop would be more expensive.
            uint32 length = uint32(_readIndefiniteStringLength(cbor.buffer, cbor.majorType));
            if (length < UINT32_MAX) {
                output = abi.encodePacked(cbor.buffer.read(length));
                length = uint32(_readIndefiniteStringLength(cbor.buffer, cbor.majorType));
                if (length < UINT32_MAX) {
                    output = abi.encodePacked(output, cbor.buffer.read(length));
                }
            }
        } else {
            return cbor.buffer.read(uint32(cbor.len));
        }
    }

    /// @notice Decode a `CBOR` structure into a `fixed16` value.
    /// @dev Due to the lack of support for floating or fixed point arithmetic in the EVM, this
    /// method offsets all values
    /// by 5 decimal orders so as to get a fixed precision of 5 decimal positions, which should be
    /// OK for most `fixed16`
    /// use cases. In other words, the output of this method is 10,000 times the actual value,
    /// encoded into an `int32`.
    /// @param cbor An instance of `CBOR`.
    /// @return The value represented by the input, as an `int128` value.
    function readFloat16(CBOR memory cbor)
        internal
        pure
        isMajorType(cbor, MAJOR_TYPE_CONTENT_FREE)
        returns (int32)
    {
        if (cbor.additionalInformation == 25) {
            return cbor.buffer.readFloat16();
        } else {
            revert UnsupportedPrimitive(cbor.additionalInformation);
        }
    }

    /// @notice Decode a `CBOR` structure into a `fixed32` value.
    /// @dev Due to the lack of support for floating or fixed point arithmetic in the EVM, this
    /// method offsets all values
    /// by 9 decimal orders so as to get a fixed precision of 9 decimal positions, which should be
    /// OK for most `fixed64`
    /// use cases. In other words, the output of this method is 10^9 times the actual value, encoded
    /// into an `int`.
    /// @param cbor An instance of `CBOR`.
    /// @return The value represented by the input, as an `int` value.
    function readFloat32(CBOR memory cbor)
        internal
        pure
        isMajorType(cbor, MAJOR_TYPE_CONTENT_FREE)
        returns (int256)
    {
        if (cbor.additionalInformation == 26) {
            return cbor.buffer.readFloat32();
        } else {
            revert UnsupportedPrimitive(cbor.additionalInformation);
        }
    }

    /// @notice Decode a `CBOR` structure into a `fixed64` value.
    /// @dev Due to the lack of support for floating or fixed point arithmetic in the EVM, this
    /// method offsets all values
    /// by 15 decimal orders so as to get a fixed precision of 15 decimal positions, which should be
    /// OK for most `fixed64`
    /// use cases. In other words, the output of this method is 10^15 times the actual value,
    /// encoded into an `int`.
    /// @param cbor An instance of `CBOR`.
    /// @return The value represented by the input, as an `int` value.
    function readFloat64(CBOR memory cbor)
        internal
        pure
        isMajorType(cbor, MAJOR_TYPE_CONTENT_FREE)
        returns (int256)
    {
        if (cbor.additionalInformation == 27) {
            return cbor.buffer.readFloat64();
        } else {
            revert UnsupportedPrimitive(cbor.additionalInformation);
        }
    }

    /// @notice Decode a `CBOR` structure into a native `int128[]` value whose inner values follow
    /// the same convention
    /// @notice as explained in `decodeFixed16`.
    /// @param cbor An instance of `CBOR`.
    function readFloat16Array(CBOR memory cbor)
        internal
        pure
        isMajorType(cbor, MAJOR_TYPE_ARRAY)
        returns (int32[] memory values)
    {
        uint64 length = readLength(cbor.buffer, cbor.additionalInformation);
        if (length < UINT64_MAX) {
            values = new int32[](length);
            for (uint64 i = 0; i < length;) {
                CBOR memory item = fromBuffer(cbor.buffer);
                values[i] = readFloat16(item);
                unchecked {
                    i++;
                }
            }
        } else {
            revert InvalidLengthEncoding(length);
        }
    }

    /// @notice Decode a `CBOR` structure into a native `int128` value.
    /// @param cbor An instance of `CBOR`.
    /// @return The value represented by the input, as an `int128` value.
    function readInt(CBOR memory cbor) internal pure returns (int256) {
        if (cbor.majorType == 1) {
            uint64 _value = readLength(cbor.buffer, cbor.additionalInformation);
            return int256(-1) - int256(uint256(_value));
        } else if (cbor.majorType == 0) {
            // Any `uint64` can be safely casted to `int128`, so this method supports majorType 1 as
            // well so as to have offer
            // a uniform API for positive and negative numbers
            return int256(readUint(cbor));
        } else {
            revert UnexpectedMajorType(cbor.majorType, 1);
        }
    }

    /// @notice Decode a `CBOR` structure into a native `int[]` value.
    /// @param cbor instance of `CBOR`.
    /// @return array The value represented by the input, as an `int[]` value.
    function readIntArray(CBOR memory cbor)
        internal
        pure
        isMajorType(cbor, MAJOR_TYPE_ARRAY)
        returns (int256[] memory array)
    {
        uint64 length = readLength(cbor.buffer, cbor.additionalInformation);
        if (length < UINT64_MAX) {
            array = new int256[](length);
            for (uint256 i = 0; i < length;) {
                CBOR memory item = fromBuffer(cbor.buffer);
                array[i] = readInt(item);
                unchecked {
                    i++;
                }
            }
        } else {
            revert InvalidLengthEncoding(length);
        }
    }

    /// @notice Decode a `CBOR` structure into a native `string` value.
    /// @param cbor An instance of `CBOR`.
    /// @return text The value represented by the input, as a `string` value.
    function readString(CBOR memory cbor)
        internal
        pure
        isMajorType(cbor, MAJOR_TYPE_STRING)
        returns (string memory text)
    {
        cbor.len = readLength(cbor.buffer, cbor.additionalInformation);
        if (cbor.len == UINT64_MAX) {
            bool _done;
            while (!_done) {
                uint64 length = _readIndefiniteStringLength(cbor.buffer, cbor.majorType);
                if (length < UINT64_MAX) {
                    text = string(abi.encodePacked(text, cbor.buffer.readText(length / 4)));
                } else {
                    _done = true;
                }
            }
        } else {
            return string(cbor.buffer.readText(cbor.len));
        }
    }

    /// @notice Decode a `CBOR` structure into a native `string[]` value.
    /// @param cbor An instance of `CBOR`.
    /// @return strings The value represented by the input, as an `string[]` value.
    function readStringArray(CBOR memory cbor)
        internal
        pure
        isMajorType(cbor, MAJOR_TYPE_ARRAY)
        returns (string[] memory strings)
    {
        uint256 length = readLength(cbor.buffer, cbor.additionalInformation);
        if (length < UINT64_MAX) {
            strings = new string[](length);
            for (uint256 i = 0; i < length;) {
                CBOR memory item = fromBuffer(cbor.buffer);
                strings[i] = readString(item);
                unchecked {
                    i++;
                }
            }
        } else {
            revert InvalidLengthEncoding(length);
        }
    }

    /// @notice Decode a `CBOR` structure into a native `uint64` value.
    /// @param cbor An instance of `CBOR`.
    /// @return The value represented by the input, as an `uint64` value.
    function readUint(CBOR memory cbor)
        internal
        pure
        isMajorType(cbor, MAJOR_TYPE_INT)
        returns (uint256)
    {
        return readLength(cbor.buffer, cbor.additionalInformation);
    }

    /// @notice Decode a `CBOR` structure into a native `uint64[]` value.
    /// @param cbor An instance of `CBOR`.
    /// @return values The value represented by the input, as an `uint64[]` value.
    function readUintArray(CBOR memory cbor)
        internal
        pure
        isMajorType(cbor, MAJOR_TYPE_ARRAY)
        returns (uint256[] memory values)
    {
        uint64 length = readLength(cbor.buffer, cbor.additionalInformation);
        if (length < UINT64_MAX) {
            values = new uint256[](length);
            for (uint256 ix = 0; ix < length;) {
                CBOR memory item = fromBuffer(cbor.buffer);
                values[ix] = readUint(item);
                unchecked {
                    ix++;
                }
            }
        } else {
            revert InvalidLengthEncoding(length);
        }
    }

    /// Read the length of a CBOR indifinite-length item (arrays, maps, byte strings and text) from
    /// a buffer, consuming
    /// as many bytes as specified by the first byte.
    function _readIndefiniteStringLength(
        WitnetBuffer.Buffer memory buffer,
        uint8 majorType
    )
        private
        pure
        returns (uint64 len)
    {
        uint8 initialByte = buffer.readUint8();
        if (initialByte == 0xff) {
            return UINT64_MAX;
        }
        len = readLength(buffer, initialByte & 0x1f);
        if (len >= UINT64_MAX) {
            revert InvalidLengthEncoding(len);
        } else if (majorType != (initialByte >> 5)) {
            revert UnexpectedMajorType((initialByte >> 5), majorType);
        }
    }
}

/// @title A convenient wrapper around the `bytes memory` type that exposes a buffer-like interface
/// @notice The buffer has an inner cursor that tracks the final offset of every read, i.e. any
/// subsequent read will
/// start with the byte that goes right after the last one in the previous read.
/// @dev `uint32` is used here for `cursor` because `uint16` would only enable seeking up to 8KB,
/// which could in some
/// theoretical use cases be exceeded. Conversely, `uint32` supports up to 512MB, which cannot
/// credibly be exceeded.
/// @author The Witnet Foundation.
library WitnetBuffer {
    error EmptyBuffer();
    error IndexOutOfBounds(uint256 index, uint256 range);
    error MissingArgs(uint256 expected, uint256 given);

    /// Iterable bytes buffer.
    struct Buffer {
        bytes data;
        uint256 cursor;
    }

    // Ensures we access an existing index in an array
    modifier withinRange(uint256 index, uint256 _range) {
        if (index > _range) {
            revert IndexOutOfBounds(index, _range);
        }
        _;
    }

    /// @notice Concatenate undefinite number of bytes chunks.
    /// @dev Faster than looping on `abi.encodePacked(output, _buffs[ix])`.
    function concat(bytes[] memory _buffs) internal pure returns (bytes memory output) {
        unchecked {
            uint256 destinationPointer;
            uint256 destinationLength;
            assembly {
                // get safe scratch location
                output := mload(0x40)
                // set starting destination pointer
                destinationPointer := add(output, 32)
            }
            for (uint256 ix = 1; ix <= _buffs.length; ix++) {
                uint256 source;
                uint256 sourceLength;
                uint256 sourcePointer;
                assembly {
                    // load source length pointer
                    source := mload(add(_buffs, mul(ix, 32)))
                    // load source length
                    sourceLength := mload(source)
                    // sets source memory pointer
                    sourcePointer := add(source, 32)
                }
                memcpy(destinationPointer, sourcePointer, sourceLength);
                assembly {
                    // increase total destination length
                    destinationLength := add(destinationLength, sourceLength)
                    // sets destination memory pointer
                    destinationPointer := add(destinationPointer, sourceLength)
                }
            }
            assembly {
                // protect output bytes
                mstore(output, destinationLength)
                // set final output length
                mstore(0x40, add(mload(0x40), add(destinationLength, 32)))
            }
        }
    }

    function fork(WitnetBuffer.Buffer memory buffer)
        internal
        pure
        returns (WitnetBuffer.Buffer memory)
    {
        return Buffer(buffer.data, buffer.cursor);
    }

    function mutate(
        WitnetBuffer.Buffer memory buffer,
        uint256 length,
        bytes memory pokes
    )
        internal
        pure
        withinRange(length, buffer.data.length - buffer.cursor + 1)
    {
        bytes[] memory parts = new bytes[](3);
        parts[0] = peek(buffer, 0, buffer.cursor);
        parts[1] = pokes;
        parts[2] = peek(buffer, buffer.cursor + length, buffer.data.length - buffer.cursor - length);
        buffer.data = concat(parts);
    }

    /// @notice Read and consume the next byte from the buffer.
    /// @param buffer An instance of `Buffer`.
    /// @return The next byte in the buffer counting from the cursor position.
    function next(Buffer memory buffer)
        internal
        pure
        withinRange(buffer.cursor, buffer.data.length)
        returns (bytes1)
    {
        // Return the byte at the position marked by the cursor and advance the cursor all at once
        return buffer.data[buffer.cursor++];
    }

    function peek(
        WitnetBuffer.Buffer memory buffer,
        uint256 offset,
        uint256 length
    )
        internal
        pure
        withinRange(offset + length, buffer.data.length)
        returns (bytes memory)
    {
        bytes memory data = buffer.data;
        bytes memory peeks = new bytes(length);
        uint256 destinationPointer;
        uint256 sourcePointer;
        assembly {
            destinationPointer := add(peeks, 32)
            sourcePointer := add(add(data, 32), offset)
        }
        memcpy(destinationPointer, sourcePointer, length);
        return peeks;
    }

    // @notice Extract bytes array from buffer starting from current cursor.
    /// @param buffer An instance of `Buffer`.
    /// @param length How many bytes to peek from the Buffer.
    // solium-disable-next-line security/no-assign-params
    function peek(
        WitnetBuffer.Buffer memory buffer,
        uint256 length
    )
        internal
        pure
        withinRange(length, buffer.data.length - buffer.cursor)
        returns (bytes memory)
    {
        return peek(buffer, buffer.cursor, length);
    }

    /// @notice Read and consume a certain amount of bytes from the buffer.
    /// @param buffer An instance of `Buffer`.
    /// @param length How many bytes to read and consume from the buffer.
    /// @return output A `bytes memory` containing the first `length` bytes from the buffer,
    /// counting from the cursor position.
    function read(
        Buffer memory buffer,
        uint256 length
    )
        internal
        pure
        withinRange(buffer.cursor + length, buffer.data.length)
        returns (bytes memory output)
    {
        // Create a new `bytes memory destination` value
        output = new bytes(length);
        // Early return in case that bytes length is 0
        if (length > 0) {
            bytes memory input = buffer.data;
            uint256 offset = buffer.cursor;
            // Get raw pointers for source and destination
            uint256 sourcePointer;
            uint256 destinationPointer;
            assembly {
                sourcePointer := add(add(input, 32), offset)
                destinationPointer := add(output, 32)
            }
            // Copy `length` bytes from source to destination
            memcpy(destinationPointer, sourcePointer, length);
            // Move the cursor forward by `length` bytes
            seek(buffer, length, true);
        }
    }

    /// @notice Read and consume the next 2 bytes from the buffer as an IEEE 754-2008 floating point
    /// number enclosed in an
    /// `int32`.
    /// @dev Due to the lack of support for floating or fixed point arithmetic in the EVM, this
    /// method offsets all values
    /// by 5 decimal orders so as to get a fixed precision of 5 decimal positions, which should be
    /// OK for most `float16`
    /// use cases. In other words, the integer output of this method is 10,000 times the actual
    /// value. The input bytes are
    /// expected to follow the 16-bit base-2 format (a.k.a. `binary16`) in the IEEE 754-2008
    /// standard.
    /// @param buffer An instance of `Buffer`.
    /// @return result The `int32` value of the next 4 bytes in the buffer counting from the cursor
    /// position.
    function readFloat16(Buffer memory buffer) internal pure returns (int32 result) {
        uint32 value = readUint16(buffer);
        // Get bit at position 0
        uint32 sign = value & 0x8000;
        // Get bits 1 to 5, then normalize to the [-15, 16] range so as to counterweight the IEEE
        // 754 exponent bias
        int32 exponent = (int32(value & 0x7c00) >> 10) - 15;
        // Get bits 6 to 15
        int32 fraction = int32(value & 0x03ff);
        // Add 2^10 to the fraction if exponent is not -15
        if (exponent != -15) {
            fraction |= 0x400;
        } else if (exponent == 16) {
            revert(
                string(
                    abi.encodePacked(
                        "WitnetBuffer.readFloat16: ", sign != 0 ? "negative" : hex"", " infinity"
                    )
                )
            );
        }
        // Compute `2 ^ exponent · (1 + fraction / 1024)`
        if (exponent >= 0) {
            result = int32(int256(int256(1 << uint256(int256(exponent))) * 10_000 * fraction) >> 10);
        } else {
            result = int32(
                int256(int256(fraction) * 10_000 / int256(1 << uint256(int256(-exponent)))) >> 10
            );
        }
        // Make the result negative if the sign bit is not 0
        if (sign != 0) {
            result *= -1;
        }
    }

    /// @notice Consume the next 4 bytes from the buffer as an IEEE 754-2008 floating point number
    /// enclosed into an `int`.
    /// @dev Due to the lack of support for floating or fixed point arithmetic in the EVM, this
    /// method offsets all values
    /// by 9 decimal orders so as to get a fixed precision of 9 decimal positions, which should be
    /// OK for most `float32`
    /// use cases. In other words, the integer output of this method is 10^9 times the actual value.
    /// The input bytes are
    /// expected to follow the 64-bit base-2 format (a.k.a. `binary32`) in the IEEE 754-2008
    /// standard.
    /// @param buffer An instance of `Buffer`.
    /// @return result The `int` value of the next 8 bytes in the buffer counting from the cursor
    /// position.
    function readFloat32(Buffer memory buffer) internal pure returns (int256 result) {
        uint256 value = readUint32(buffer);
        // Get bit at position 0
        uint256 sign = value & 0x80000000;
        // Get bits 1 to 8, then normalize to the [-127, 128] range so as to counterweight the IEEE
        // 754 exponent bias
        int256 exponent = (int256(value & 0x7f800000) >> 23) - 127;
        // Get bits 9 to 31
        int256 fraction = int256(value & 0x007fffff);
        // Add 2^23 to the fraction if exponent is not -127
        if (exponent != -127) {
            fraction |= 0x800000;
        } else if (exponent == 128) {
            revert(
                string(
                    abi.encodePacked(
                        "WitnetBuffer.readFloat32: ", sign != 0 ? "negative" : hex"", " infinity"
                    )
                )
            );
        }
        // Compute `2 ^ exponent · (1 + fraction / 2^23)`
        if (exponent >= 0) {
            result = (int256(1 << uint256(exponent)) * (10 ** 9) * fraction) >> 23;
        } else {
            result = (fraction * (10 ** 9) / int256(1 << uint256(-exponent))) >> 23;
        }
        // Make the result negative if the sign bit is not 0
        if (sign != 0) {
            result *= -1;
        }
    }

    /// @notice Consume the next 8 bytes from the buffer as an IEEE 754-2008 floating point number
    /// enclosed into an `int`.
    /// @dev Due to the lack of support for floating or fixed point arithmetic in the EVM, this
    /// method offsets all values
    /// by 15 decimal orders so as to get a fixed precision of 15 decimal positions, which should be
    /// OK for most `float64`
    /// use cases. In other words, the integer output of this method is 10^15 times the actual
    /// value. The input bytes are
    /// expected to follow the 64-bit base-2 format (a.k.a. `binary64`) in the IEEE 754-2008
    /// standard.
    /// @param buffer An instance of `Buffer`.
    /// @return result The `int` value of the next 8 bytes in the buffer counting from the cursor
    /// position.
    function readFloat64(Buffer memory buffer) internal pure returns (int256 result) {
        uint256 value = readUint64(buffer);
        // Get bit at position 0
        uint256 sign = value & 0x8000000000000000;
        // Get bits 1 to 12, then normalize to the [-1023, 1024] range so as to counterweight the
        // IEEE 754 exponent bias
        int256 exponent = (int256(value & 0x7ff0000000000000) >> 52) - 1023;
        // Get bits 6 to 15
        int256 fraction = int256(value & 0x000fffffffffffff);
        // Add 2^52 to the fraction if exponent is not -1023
        if (exponent != -1023) {
            fraction |= 0x10000000000000;
        } else if (exponent == 1024) {
            revert(
                string(
                    abi.encodePacked(
                        "WitnetBuffer.readFloat64: ", sign != 0 ? "negative" : hex"", " infinity"
                    )
                )
            );
        }
        // Compute `2 ^ exponent · (1 + fraction / 1024)`
        if (exponent >= 0) {
            result = (int256(1 << uint256(exponent)) * (10 ** 15) * fraction) >> 52;
        } else {
            result = (fraction * (10 ** 15) / int256(1 << uint256(-exponent))) >> 52;
        }
        // Make the result negative if the sign bit is not 0
        if (sign != 0) {
            result *= -1;
        }
    }

    // Read a text string of a given length from a buffer. Returns a `bytes memory` value for the
    // sake of genericness,
    /// but it can be easily casted into a string with `string(result)`.
    // solium-disable-next-line security/no-assign-params
    function readText(
        WitnetBuffer.Buffer memory buffer,
        uint64 length
    )
        internal
        pure
        returns (bytes memory text)
    {
        text = new bytes(length);
        unchecked {
            for (uint64 index = 0; index < length; index++) {
                uint8 char = readUint8(buffer);
                if (char & 0x80 != 0) {
                    if (char < 0xe0) {
                        char = (char & 0x1f) << 6 | (readUint8(buffer) & 0x3f);
                        length -= 1;
                    } else if (char < 0xf0) {
                        char = (char & 0x0f) << 12 | (readUint8(buffer) & 0x3f) << 6
                            | (readUint8(buffer) & 0x3f);
                        length -= 2;
                    } else {
                        char = (char & 0x0f) << 18 | (readUint8(buffer) & 0x3f) << 12
                            | (readUint8(buffer) & 0x3f) << 6 | (readUint8(buffer) & 0x3f);
                        length -= 3;
                    }
                }
                text[index] = bytes1(char);
            }
            // Adjust text to actual length:
            assembly {
                mstore(text, length)
            }
        }
    }

    /// @notice Read and consume the next byte from the buffer as an `uint8`.
    /// @param buffer An instance of `Buffer`.
    /// @return value The `uint8` value of the next byte in the buffer counting from the cursor
    /// position.
    function readUint8(Buffer memory buffer)
        internal
        pure
        withinRange(buffer.cursor, buffer.data.length)
        returns (uint8 value)
    {
        bytes memory data = buffer.data;
        uint256 offset = buffer.cursor;
        assembly {
            value := mload(add(add(data, 1), offset))
        }
        buffer.cursor++;
    }

    /// @notice Read and consume the next 2 bytes from the buffer as an `uint16`.
    /// @param buffer An instance of `Buffer`.
    /// @return value The `uint16` value of the next 2 bytes in the buffer counting from the cursor
    /// position.
    function readUint16(Buffer memory buffer)
        internal
        pure
        withinRange(buffer.cursor + 2, buffer.data.length)
        returns (uint16 value)
    {
        bytes memory data = buffer.data;
        uint256 offset = buffer.cursor;
        assembly {
            value := mload(add(add(data, 2), offset))
        }
        buffer.cursor += 2;
    }

    /// @notice Read and consume the next 4 bytes from the buffer as an `uint32`.
    /// @param buffer An instance of `Buffer`.
    /// @return value The `uint32` value of the next 4 bytes in the buffer counting from the cursor
    /// position.
    function readUint32(Buffer memory buffer)
        internal
        pure
        withinRange(buffer.cursor + 4, buffer.data.length)
        returns (uint32 value)
    {
        bytes memory data = buffer.data;
        uint256 offset = buffer.cursor;
        assembly {
            value := mload(add(add(data, 4), offset))
        }
        buffer.cursor += 4;
    }

    /// @notice Read and consume the next 8 bytes from the buffer as an `uint64`.
    /// @param buffer An instance of `Buffer`.
    /// @return value The `uint64` value of the next 8 bytes in the buffer counting from the cursor
    /// position.
    function readUint64(Buffer memory buffer)
        internal
        pure
        withinRange(buffer.cursor + 8, buffer.data.length)
        returns (uint64 value)
    {
        bytes memory data = buffer.data;
        uint256 offset = buffer.cursor;
        assembly {
            value := mload(add(add(data, 8), offset))
        }
        buffer.cursor += 8;
    }

    /// @notice Read and consume the next 16 bytes from the buffer as an `uint128`.
    /// @param buffer An instance of `Buffer`.
    /// @return value The `uint128` value of the next 16 bytes in the buffer counting from the
    /// cursor position.
    function readUint128(Buffer memory buffer)
        internal
        pure
        withinRange(buffer.cursor + 16, buffer.data.length)
        returns (uint128 value)
    {
        bytes memory data = buffer.data;
        uint256 offset = buffer.cursor;
        assembly {
            value := mload(add(add(data, 16), offset))
        }
        buffer.cursor += 16;
    }

    /// @notice Read and consume the next 32 bytes from the buffer as an `uint256`.
    /// @param buffer An instance of `Buffer`.
    /// @return value The `uint256` value of the next 32 bytes in the buffer counting from the
    /// cursor position.
    function readUint256(Buffer memory buffer)
        internal
        pure
        withinRange(buffer.cursor + 32, buffer.data.length)
        returns (uint256 value)
    {
        bytes memory data = buffer.data;
        uint256 offset = buffer.cursor;
        assembly {
            value := mload(add(add(data, 32), offset))
        }
        buffer.cursor += 32;
    }

    /// @notice Count number of required parameters for given bytes arrays
    /// @dev Wildcard format: "\#\", with # in ["0".."9"].
    /// @param input Bytes array containing strings.
    /// @param count Highest wildcard index found, plus 1.
    function argsCountOf(bytes memory input) internal pure returns (uint8 count) {
        if (input.length < 3) {
            return 0;
        }
        unchecked {
            uint256 ix = 0;
            uint256 length = input.length - 2;
            for (; ix < length;) {
                if (
                    input[ix] == bytes1("\\") && input[ix + 2] == bytes1("\\")
                        && input[ix + 1] >= bytes1("0") && input[ix + 1] <= bytes1("9")
                ) {
                    uint8 ax = uint8(uint8(input[ix + 1]) - uint8(bytes1("0")) + 1);
                    if (ax > count) {
                        count = ax;
                    }
                    ix += 3;
                } else {
                    ix++;
                }
            }
        }
    }

    /// @notice Replace bytecode indexed wildcards by correspondent substrings.
    /// @dev Wildcard format: "\#\", with # in ["0".."9"].
    /// @param input Bytes array containing strings.
    /// @param args Array of substring values for replacing indexed wildcards.
    /// @return output Resulting bytes array after replacing all wildcards.
    /// @return hits Total number of replaced wildcards.
    function replace(
        bytes memory input,
        string[] memory args
    )
        internal
        pure
        returns (bytes memory output, uint256 hits)
    {
        uint256 ix = 0;
        uint256 lix = 0;
        uint256 inputLength;
        uint256 inputPointer;
        uint256 outputLength;
        uint256 outputPointer;
        uint256 source;
        uint256 sourceLength;
        uint256 sourcePointer;

        if (input.length < 3) {
            return (input, 0);
        }

        assembly {
            // set starting input pointer
            inputPointer := add(input, 32)
            // get safe output location
            output := mload(0x40)
            // set starting output pointer
            outputPointer := add(output, 32)
        }

        unchecked {
            uint256 length = input.length - 2;
            for (; ix < length;) {
                if (
                    input[ix] == bytes1("\\") && input[ix + 2] == bytes1("\\")
                        && input[ix + 1] >= bytes1("0") && input[ix + 1] <= bytes1("9")
                ) {
                    inputLength = (ix - lix);
                    if (ix > lix) {
                        memcpy(outputPointer, inputPointer, inputLength);
                        inputPointer += inputLength + 3;
                        outputPointer += inputLength;
                    } else {
                        inputPointer += 3;
                    }
                    uint256 ax = uint256(uint8(input[ix + 1]) - uint8(bytes1("0")));
                    if (ax >= args.length) {
                        revert MissingArgs(ax + 1, args.length);
                    }
                    assembly {
                        source := mload(add(args, mul(32, add(ax, 1))))
                        sourceLength := mload(source)
                        sourcePointer := add(source, 32)
                    }
                    memcpy(outputPointer, sourcePointer, sourceLength);
                    outputLength += inputLength + sourceLength;
                    outputPointer += sourceLength;
                    ix += 3;
                    lix = ix;
                    hits++;
                } else {
                    ix++;
                }
            }
            ix = input.length;
        }
        if (outputLength > 0) {
            if (ix > lix) {
                memcpy(outputPointer, inputPointer, ix - lix);
                outputLength += (ix - lix);
            }
            assembly {
                // set final output length
                mstore(output, outputLength)
                // protect output bytes
                mstore(0x40, add(mload(0x40), add(outputLength, 32)))
            }
        } else {
            return (input, 0);
        }
    }

    /// @notice Replace string indexed wildcards by correspondent substrings.
    /// @dev Wildcard format: "\#\", with # in ["0".."9"].
    /// @param input String potentially containing wildcards.
    /// @param args Array of substring values for replacing indexed wildcards.
    /// @return output Resulting string after replacing all wildcards.
    function replace(
        string memory input,
        string[] memory args
    )
        internal
        pure
        returns (string memory)
    {
        (bytes memory _outputBytes,) = replace(bytes(input), args);
        return string(_outputBytes);
    }

    /// @notice Move the inner cursor of the buffer to a relative or absolute position.
    /// @param buffer An instance of `Buffer`.
    /// @param offset How many bytes to move the cursor forward.
    /// @param relative Whether to count `offset` from the last position of the cursor (`true`) or
    /// the beginning of the
    /// buffer (`true`).
    /// @return The final position of the cursor (will equal `offset` if `relative` is `false`).
    // solium-disable-next-line security/no-assign-params
    function seek(
        Buffer memory buffer,
        uint256 offset,
        bool relative
    )
        internal
        pure
        withinRange(offset, buffer.data.length)
        returns (uint256)
    {
        // Deal with relative offsets
        if (relative) {
            offset += buffer.cursor;
        }
        buffer.cursor = offset;
        return offset;
    }

    /// @notice Move the inner cursor a number of bytes forward.
    /// @dev This is a simple wrapper around the relative offset case of `seek()`.
    /// @param buffer An instance of `Buffer`.
    /// @param relativeOffset How many bytes to move the cursor forward.
    /// @return The final position of the cursor.
    function seek(Buffer memory buffer, uint256 relativeOffset) internal pure returns (uint256) {
        return seek(buffer, relativeOffset, true);
    }

    /// @notice Copy bytes from one memory address into another.
    /// @dev This function was borrowed from Nick Johnson's `solidity-stringutils` lib, and
    /// reproduced here under the terms
    /// of [Apache License
    /// 2.0](https://github.com/Arachnid/solidity-stringutils/blob/master/LICENSE).
    /// @param dest Address of the destination memory.
    /// @param src Address to the source memory.
    /// @param len How many bytes to copy.
    // solium-disable-next-line security/no-assign-params
    function memcpy(uint256 dest, uint256 src, uint256 len) private pure {
        unchecked {
            // Copy word-length chunks while possible
            for (; len >= 32; len -= 32) {
                assembly {
                    mstore(dest, mload(src))
                }
                dest += 32;
                src += 32;
            }
            if (len > 0) {
                // Copy remaining bytes
                uint256 _mask = 256 ** (32 - len) - 1;
                assembly {
                    let srcpart := and(mload(src), not(_mask))
                    let destpart := and(mload(dest), _mask)
                    mstore(dest, or(destpart, srcpart))
                }
            }
        }
    }
}

Settings
{
  "remappings": [
    "@opendatafabric/=node_modules/@opendatafabric/",
    "@openzeppelin/=node_modules/@openzeppelin/",
    "forge-std/=node_modules/forge-std/"
  ],
  "optimizer": {
    "enabled": true,
    "runs": 10000
  },
  "metadata": {
    "useLiteralContent": false,
    "bytecodeHash": "none",
    "appendCBOR": true
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "evmVersion": "paris",
  "viaIR": false,
  "libraries": {}
}

Contract ABI

[{"inputs":[{"internalType":"address","name":"oracleAddr","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"EmptyBuffer","type":"error"},{"inputs":[{"internalType":"uint256","name":"index","type":"uint256"},{"internalType":"uint256","name":"range","type":"uint256"}],"name":"IndexOutOfBounds","type":"error"},{"inputs":[{"internalType":"uint256","name":"length","type":"uint256"}],"name":"InvalidLengthEncoding","type":"error"},{"inputs":[{"internalType":"uint256","name":"read","type":"uint256"},{"internalType":"uint256","name":"expected","type":"uint256"}],"name":"UnexpectedMajorType","type":"error"},{"inputs":[{"internalType":"uint256","name":"unexpected","type":"uint256"}],"name":"UnsupportedMajorType","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint64","name":"policyId","type":"uint64"},{"indexed":true,"internalType":"address","name":"holder","type":"address"},{"indexed":false,"internalType":"uint256","name":"holderDeposit","type":"uint256"}],"name":"CoverageApplication","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint64","name":"policyId","type":"uint64"},{"indexed":true,"internalType":"address","name":"holder","type":"address"},{"indexed":true,"internalType":"address","name":"insurer","type":"address"},{"indexed":false,"internalType":"uint256","name":"holderDeposit","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"insurerDeposit","type":"uint256"}],"name":"PolicyCreated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint64","name":"policyId","type":"uint64"},{"indexed":true,"internalType":"address","name":"holder","type":"address"},{"indexed":true,"internalType":"address","name":"insurer","type":"address"},{"indexed":false,"internalType":"uint256","name":"holderDeposit","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"insurerDeposit","type":"uint256"},{"indexed":false,"internalType":"uint64","name":"dataRequestId","type":"uint64"},{"indexed":false,"internalType":"bool","name":"holderClaims","type":"bool"}],"name":"PolicySettled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint64","name":"policyId","type":"uint64"},{"indexed":true,"internalType":"address","name":"holder","type":"address"},{"indexed":true,"internalType":"address","name":"insurer","type":"address"},{"indexed":false,"internalType":"uint256","name":"holderDeposit","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"insurerDeposit","type":"uint256"},{"indexed":false,"internalType":"uint64","name":"dataRequestId","type":"uint64"}],"name":"PolicySettlementInitiated","type":"event"},{"inputs":[{"internalType":"uint64","name":"precipitationThreshold","type":"uint64"},{"internalType":"string","name":"datasetId","type":"string"}],"name":"applyForCoverage","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"uint64","name":"policyId","type":"uint64"}],"name":"bidForCoverage","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"components":[{"internalType":"uint64","name":"_requestId","type":"uint64"},{"internalType":"bool","name":"_ok","type":"bool"},{"components":[{"components":[{"internalType":"bytes","name":"data","type":"bytes"},{"internalType":"uint256","name":"cursor","type":"uint256"}],"internalType":"struct WitnetBuffer.Buffer","name":"buffer","type":"tuple"},{"internalType":"uint8","name":"initialByte","type":"uint8"},{"internalType":"uint8","name":"majorType","type":"uint8"},{"internalType":"uint8","name":"additionalInformation","type":"uint8"},{"internalType":"uint64","name":"len","type":"uint64"},{"internalType":"uint64","name":"tag","type":"uint64"}],"internalType":"struct CborReader.CBOR[]","name":"_data","type":"tuple[]"},{"internalType":"string","name":"_errorMessage","type":"string"}],"internalType":"struct OdfResponse.Res","name":"result","type":"tuple"}],"name":"onResult","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"policyId","type":"uint64"}],"name":"settle","outputs":[{"internalType":"uint64","name":"","type":"uint64"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]

608060405260018054600160a01b600160e01b0319169055348015602257600080fd5b50604051613919380380613919833981016040819052603f916071565b60008054336001600160a01b031991821617909155600180549091166001600160a01b0392909216919091179055609f565b600060208284031215608257600080fd5b81516001600160a01b0381168114609857600080fd5b9392505050565b61386b806100ae6000396000f3fe60806040526004361061005a5760003560e01c80634b9ba446116100435780634b9ba446146100895780638b6f0d74146100c6578063cae6a407146100e657600080fd5b8063272001e71461005f5780633ccfd60b14610074575b600080fd5b61007261006d366004612df4565b6100f9565b005b34801561008057600080fd5b506100726105ab565b34801561009557600080fd5b506100a96100a4366004612df4565b61065c565b60405167ffffffffffffffff909116815260200160405180910390f35b3480156100d257600080fd5b506100726100e1366004613139565b610bf6565b6100a96100f43660046131f5565b611258565b67ffffffffffffffff8082166000908152600260208181526040808420815161010080820184528254808916835273ffffffffffffffffffffffffffffffffffffffff6801000000000000000090910481169583019590955260018301549382019390935293810154909216606084015260038201546080840152600482015460ff8116151560a08501520490931660c08201526005830180549293919260e0840191906101a690613245565b80601f01602080910402602001604051908101604052809291908181526020018280546101d290613245565b801561021f5780601f106101f45761010080835404028352916020019161021f565b820191906000526020600020905b81548152906001019060200180831161020257829003601f168201915b50505091909252505050602081015190915073ffffffffffffffffffffffffffffffffffffffff166102985760405162461bcd60e51b815260206004820152601560248201527f706f6c69637920646f6573206e6f74206578697374000000000000000000000060448201526064015b60405180910390fd5b606081015173ffffffffffffffffffffffffffffffffffffffff16156103005760405162461bcd60e51b815260206004820152601b60248201527f706f6c6963792077617320616c72656164792061636365707465640000000000604482015260640161028f565b8060a00151156103525760405162461bcd60e51b815260206004820152601a60248201527f706f6c6963792077617320616c726561647920736574746c6564000000000000604482015260640161028f565b806040015134116103cb5760405162461bcd60e51b815260206004820152602260248201527f6e65656420746f2070726f766964652073756666696369656e74206465706f7360448201527f6974000000000000000000000000000000000000000000000000000000000000606482015260840161028f565b3360608201908152346080830190815267ffffffffffffffff84811660009081526002602081815260409283902087518154928901519086167fffffffff00000000000000000000000000000000000000000000000000000000909316929092176801000000000000000073ffffffffffffffffffffffffffffffffffffffff93841602178155928701516001840155945190820180547fffffffffffffffffffffffff00000000000000000000000000000000000000001691909516179093559051600383015560a083015160048301805460c08601517fffffffffffffffffffffffffffffffffffffffffffffff0000000000000000009091169215157fffffffffffffffffffffffffffffffffffffffffffffff0000000000000000ff1692909217610100929093169190910291909117905560e0820151829190600582019061051890826132da565b50905050806060015173ffffffffffffffffffffffffffffffffffffffff16816020015173ffffffffffffffffffffffffffffffffffffffff168367ffffffffffffffff167fac9f49869e29bfd82412359f358df8bf88224381ef1995ad3fb0e5b51c129c298460400151856080015160405161059f929190918252602082015260400190565b60405180910390a45050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146106125760405162461bcd60e51b815260206004820152601760248201527f4f6e6c79206f776e65722063616e207769746864726177000000000000000000604482015260640161028f565b6000805460405173ffffffffffffffffffffffffffffffffffffffff909116914780156108fc02929091818181858888f19350505050158015610659573d6000803e3d6000fd5b50565b67ffffffffffffffff8082166000908152600260208181526040808420815161010080820184528254808916835273ffffffffffffffffffffffffffffffffffffffff6801000000000000000090910481169583019590955260018301549382019390935293810154909216606084015260038201546080840152600482015460ff8116151560a08501520490931660c082015260058301805492938493909160e084019161070a90613245565b80601f016020809104026020016040519081016040528092919081815260200182805461073690613245565b80156107835780601f1061075857610100808354040283529160200191610783565b820191906000526020600020905b81548152906001019060200180831161076657829003601f168201915b50505091909252505050602081015190915073ffffffffffffffffffffffffffffffffffffffff166107f75760405162461bcd60e51b815260206004820152601560248201527f706f6c69637920646f6573206e6f742065786973740000000000000000000000604482015260640161028f565b8060a00151156108495760405162461bcd60e51b815260206004820152601a60248201527f706f6c6963792077617320616c726561647920736574746c6564000000000000604482015260640161028f565b606081015173ffffffffffffffffffffffffffffffffffffffff16610a0f57600160a0820181815267ffffffffffffffff85811660009081526002602081815260409283902087518154928901519086167fffffffff00000000000000000000000000000000000000000000000000000000909316929092176801000000000000000073ffffffffffffffffffffffffffffffffffffffff938416021781559287015195830195909555606086015190820180547fffffffffffffffffffffffff000000000000000000000000000000000000000016919095161790935560808401516003840155905160048301805460c08601517fffffffffffffffffffffffffffffffffffffffffffffff0000000000000000009091169215157fffffffffffffffffffffffffffffffffffffffffffffff0000000000000000ff1692909217610100929093169190910291909117905560e082015182919060058201906109b390826132da565b50905050806020015173ffffffffffffffffffffffffffffffffffffffff166108fc82604001519081150290604051600060405180830381858888f19350505050158015610a05573d6000803e3d6000fd5b5060009392505050565b6000610a19611531565b9050610a696040518060400160405280601081526020017f776561746865725f73746174696f6e73000000000000000000000000000000008152508360e001518361156f9092919063ffffffff16565b610a8c6040518060e0016040528060bd81526020016137a260bd9139829061158d565b6001546040517fb8853b5400000000000000000000000000000000000000000000000000000000815260009173ffffffffffffffffffffffffffffffffffffffff169063b8853b5490610aeb9085903090638b6f0d74906004016133b8565b6020604051808303816000875af1158015610b0a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b2e9190613475565b67ffffffffffffffff81811660008181526003602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000168b8616179055606088810151898301518a518b86015160808d01518751918252958101959095529484019590955295965073ffffffffffffffffffffffffffffffffffffffff958616959093169391909116917f54bd3a28af22ebd07e9ba95adde85521fe7ae950fc9d3b4f5574b6deb506de11910160405180910390a4949350505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610c5d5760405162461bcd60e51b815260206004820152601c60248201527f43616e206f6e6c792062652063616c6c6564206279206f7261636c6500000000604482015260640161028f565b600060036000610c6b845190565b67ffffffffffffffff908116825260208201929092526040016000908120549091169150819003610cde5760405162461bcd60e51b815260206004820152601e60248201527f636f72726573706f6e64696e6720706f6c696379206e6f7420666f756e640000604482015260640161028f565b67ffffffffffffffff8082166000908152600260208181526040808420815161010080820184528254808916835273ffffffffffffffffffffffffffffffffffffffff6801000000000000000090910481169583019590955260018301549382019390935293810154909216606084015260038201546080840152600482015460ff8116151560a08501520490931660c08201526005830180549293919260e084019190610d8b90613245565b80601f0160208091040260200160405190810160405280929190818152602001828054610db790613245565b8015610e045780601f10610dd957610100808354040283529160200191610e04565b820191906000526020600020905b815481529060010190602001808311610de757829003601f168201915b50505091909252505050602081015190915073ffffffffffffffffffffffffffffffffffffffff1615801590610e535750606081015173ffffffffffffffffffffffffffffffffffffffff1615155b610e9f5760405162461bcd60e51b815260206004820152601a60248201527f706f6c69637920697320696e20696e76616c6964207374617465000000000000604482015260640161028f565b8060a0015115610ef15760405162461bcd60e51b815260206004820152601660248201527f706f6c69637920616c726561647920736574746c656400000000000000000000604482015260640161028f565b610efa836115dc565b67ffffffffffffffff16600114610f535760405162461bcd60e51b815260206004820152601360248201527f4578706563746564206f6e65207265636f726400000000000000000000000000604482015260640161028f565b6000610f5f84826115f0565b90506000610f8682600081518110610f7957610f79613492565b6020026020010151611629565b60c084018051600160a0870181815267ffffffffffffffff8981166000908152600260208181526040928390208c518154928e01519086167fffffffff00000000000000000000000000000000000000000000000000000000909316929092176801000000000000000073ffffffffffffffffffffffffffffffffffffffff93841602178155928c01519583019590955560608b015190820180547fffffffffffffffffffffffff000000000000000000000000000000000000000016919095161790935560808901516003840155905160048301805495517fffffffffffffffffffffffffffffffffffffffffffffff0000000000000000009096169115157fffffffffffffffffffffffffffffffffffffffffffffff0000000000000000ff1691909117610100958316959095029490941790935560e0870151939450908216918416919091109185919060058201906110e290826132da565b50905050836060015173ffffffffffffffffffffffffffffffffffffffff16846020015173ffffffffffffffffffffffffffffffffffffffff16856000015167ffffffffffffffff167f3cba6f1baeb45c5440208ba050bfeb9e604dc591d7661cf2c7d8065351423a048760400151886080015161115e8c5190565b60408051938452602084019290925267ffffffffffffffff1690820152851515606082015260800160405180910390a480156111f457836020015173ffffffffffffffffffffffffffffffffffffffff166108fc856080015186604001516111c691906134f0565b6040518115909202916000818181858888f193505050501580156111ee573d6000803e3d6000fd5b50611250565b836060015173ffffffffffffffffffffffffffffffffffffffff166108fc8560800151866040015161122691906134f0565b6040518115909202916000818181858888f1935050505015801561124e573d6000803e3d6000fd5b505b505050505050565b6000346000036112aa5760405162461bcd60e51b815260206004820152601960248201527f6e65656420746f2070726f766964652061206465706f73697400000000000000604482015260640161028f565b6001805481906014906112e090839074010000000000000000000000000000000000000000900467ffffffffffffffff16613503565b825467ffffffffffffffff91821661010093840a908102920219161790915560408051918201815260008083526020830181905290820181905260608083018290526080830182905260a0830182905260c083019190915260e082015290506001805474010000000000000000000000000000000000000000900467ffffffffffffffff9081168084523360208086019182523460408088019182528a861660c0890190815260e089018b81526000968752600294859052919095208851815495519088167fffffffff00000000000000000000000000000000000000000000000000000000909616959095176801000000000000000073ffffffffffffffffffffffffffffffffffffffff96871602178155915196820196909655606087015191810180547fffffffffffffffffffffffff00000000000000000000000000000000000000001692909316919091179091556080850151600382015560a085015160048201805493517fffffffffffffffffffffffffffffffffffffffffffffff0000000000000000009094169115157fffffffffffffffffffffffffffffffffffffffffffffff0000000000000000ff16919091176101009390941692909202929092179055905182919060058201906114bc90826132da565b50905050806020015173ffffffffffffffffffffffffffffffffffffffff16816000015167ffffffffffffffff167fe9b43372ad2470bf088a19481efde518124553fb2f7cb1216c0b8f83cf15ff45836040015160405161151f91815260200190565b60405180910390a35190505b92915050565b611539612d86565b60006115466104006116c6565b9050611551816116e7565b61155c81600161170b565b6040805160208101909152908152919050565b600061157a82611717565b905061158784848361191c565b50505050565b60408051808201909152600381527f73716c0000000000000000000000000000000000000000000000000000000000602082015282516115cc91611978565b81516115d89082611978565b5050565b6000600182604001515161152b919061352b565b606061162283604001518367ffffffffffffffff168151811061161557611615613492565b6020026020010151611991565b9392505050565b6000816040015160ff1660010361166657600061164e83600001518460600151611c64565b905061162267ffffffffffffffff821660001961353e565b816040015160ff1660000361167e5761152b82611d46565b60408083015190517e1000a000000000000000000000000000000000000000000000000000000000815260ff90911660048201526001602482015260440161028f565b919050565b6116ce612d9e565b80516116da9083611dc4565b5060006020820152919050565b6116f2816004611e3b565b60018160200181815161170591906134f0565b90525050565b6115d882600083611e52565b80516060908290604d1461176d5760405162461bcd60e51b815260206004820152600b60248201527f496e76616c696420444944000000000000000000000000000000000000000000604482015260640161028f565b6117768161355e565b76ffffffffffffffffffffffffffffffffffffffffffffff19167f6469643a6f64663a660000000000000000000000000000000000000000000000146117fe5760405162461bcd60e51b815260206004820152600b60248201527f496e76616c696420444944000000000000000000000000000000000000000000604482015260640161028f565b6040805160228082526060820190925260009160208201818036833701905050905060005b60228161ffff16101561191457600061183d8260026135ae565b6118489060096135d4565b9050611899846118598360016135d4565b61ffff168151811061186d5761186d613492565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016611f73565b60046118b4868461ffff168151811061186d5761186d613492565b60ff16901b6118c391906135ef565b60f81b838361ffff16815181106118dc576118dc613492565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535050600101611823565b509392505050565b60408051808201909152600281527f64730000000000000000000000000000000000000000000000000000000000006020820152835161195b91611978565b82516119679083611978565b825161197390826121c3565b505050565b6119858260038351611e52565b815161197390826121d0565b60608160048060ff16826040015160ff16146119eb5760408083015190517e1000a000000000000000000000000000000000000000000000000000000000815260ff9182166004820152908216602482015260440161028f565b60006119ff85600001518660600151611c64565b9050611a0c816001613503565b67ffffffffffffffff1667ffffffffffffffff811115611a2e57611a2e612e11565b604051908082528060200260200182016040528015611a9e57816020015b6040805161010081018252606060c08201818152600060e0840181905290835260208084018290529383018190529082018190526080820181905260a08201528252600019909201910181611a4c5790505b50935060005b8167ffffffffffffffff16811015611c3357611abf866121f1565b9550611b98866040805161010081018252606060c08201818152600060e084018190529083526020830181905292820183905281018290526080810182905260a08101919091526040805160c081018083528451610100830184526060909152600060e0830152825180840190935280518352602090810151908301529081908152602001836020015160ff168152602001836040015160ff168152602001836060015160ff168152602001836080015167ffffffffffffffff1681526020018360a0015167ffffffffffffffff168152509050919050565b858281518110611baa57611baa613492565b6020026020010181905250600460ff16866040015160ff1603611c03576000611bd287611991565b90508060018251611be3919061352b565b81518110611bf357611bf3613492565b6020026020010151965050611c2b565b600560ff16866040015160ff1603611c20576000611bd287612252565b611c2986612578565b505b600101611aa4565b5084848267ffffffffffffffff1681518110611c5157611c51613492565b6020026020010181905250505050919050565b600060188260ff161015611c7c575060ff811661152b565b8160ff16601803611c9a57611c908361278c565b60ff16905061152b565b8160ff16601903611cb957611cae83612807565b61ffff16905061152b565b8160ff16601a03611cda57611ccd8361288c565b63ffffffff16905061152b565b8160ff16601b03611cf557611cee83612904565b905061152b565b8160ff16601f03611d0f575067ffffffffffffffff61152b565b6040517f6d785b1300000000000000000000000000000000000000000000000000000000815260ff8316600482015260240161028f565b60008160008060ff16826040015160ff1614611da05760408083015190517e1000a000000000000000000000000000000000000000000000000000000000815260ff9182166004820152908216602482015260440161028f565b611db284600001518560600151611c64565b67ffffffffffffffff16949350505050565b604080518082019091526060815260006020820152611de4602083613608565b15611e0c57611df4602083613608565b611dff90602061352b565b611e0990836134f0565b91505b602080840183905260405180855260008152908184010181811015611e3057600080fd5b604052509192915050565b815161197390601f611fe0600585901b161761297c565b60178167ffffffffffffffff1611611e795782516115879060e0600585901b16831761297c565b60ff8167ffffffffffffffff1611611ebb578251611ea2906018611fe0600586901b161761297c565b5082516115879067ffffffffffffffff831660016129e5565b61ffff8167ffffffffffffffff1611611efe578251611ee5906019611fe0600586901b161761297c565b5082516115879067ffffffffffffffff831660026129e5565b63ffffffff8167ffffffffffffffff1611611f43578251611f2a90601a611fe0600586901b161761297c565b5082516115879067ffffffffffffffff831660046129e5565b8251611f5a90601b611fe0600586901b161761297c565b5082516115879067ffffffffffffffff831660086129e5565b60007f30000000000000000000000000000000000000000000000000000000000000007fff0000000000000000000000000000000000000000000000000000000000000083161080159061200957507f39000000000000000000000000000000000000000000000000000000000000007fff00000000000000000000000000000000000000000000000000000000000000831611155b1561201d5761152b603060f884901c613643565b7f61000000000000000000000000000000000000000000000000000000000000007fff000000000000000000000000000000000000000000000000000000000000008316108015906120b157507f66000000000000000000000000000000000000000000000000000000000000007fff00000000000000000000000000000000000000000000000000000000000000831611155b156120d15760616120c760f884901c600a6135ef565b61152b9190613643565b7f41000000000000000000000000000000000000000000000000000000000000007fff0000000000000000000000000000000000000000000000000000000000000083161080159061216557507f46000000000000000000000000000000000000000000000000000000000000007fff00000000000000000000000000000000000000000000000000000000000000831611155b1561217b5760416120c760f884901c600a6135ef565b60405162461bcd60e51b815260206004820152600e60248201527f4e6f742061206865782063686172000000000000000000000000000000000000604482015260640161028f565b6119858260028351611e52565b60408051808201909152606081526000602082015261162283838451612a6a565b6040805161010081018252606060c08201818152600060e084018190529083526020830181905292820183905281018290526080810182905260a08101919091528151805151602090910151101561224e57815161152b90612b3b565b5090565b60608160058060ff16826040015160ff16146122ac5760408083015190517e1000a000000000000000000000000000000000000000000000000000000000815260ff9182166004820152908216602482015260440161028f565b60006122c085600001518660600151611c64565b6122cb90600261365c565b90506122d8816001613503565b67ffffffffffffffff1667ffffffffffffffff8111156122fa576122fa612e11565b60405190808252806020026020018201604052801561236a57816020015b6040805161010081018252606060c08201818152600060e0840181905290835260208084018290529383018190529082018190526080820181905260a082015282526000199092019101816123185790505b50935060005b8167ffffffffffffffff16811015611c335761238b866121f1565b9550612464866040805161010081018252606060c08201818152600060e084018190529083526020830181905292820183905281018290526080810182905260a08101919091526040805160c081018083528451610100830184526060909152600060e0830152825180840190935280518352602090810151908301529081908152602001836020015160ff168152602001836040015160ff168152602001836060015160ff168152602001836080015167ffffffffffffffff1681526020018360a0015167ffffffffffffffff168152509050919050565b85828151811061247657612476613492565b602090810291909101015261248c600282613608565b1580156124a15750604086015160ff16600314155b156124e95760408087015190517e1000a000000000000000000000000000000000000000000000000000000000815260ff90911660048201526003602482015260440161028f565b604086015160ff16600414806125065750604086015160ff166005145b1561256557604086015160009060ff1660041461252b5761252687612252565b612534565b61253487611991565b90508060018251612545919061352b565b8151811061255557612555613492565b6020026020010151965050612570565b61256e86612578565b505b600101612370565b6040805161010081018252606060c08201818152600060e08401819052908352602083018190528284018190529082018190526080820181905260a08201529082015160ff1615806125d15750604082015160ff166001145b8061260a5750604082015160ff1660071480156125f657506019826060015160ff1610155b801561260a5750601b826060015160ff1611155b1561263e5761261882612ce9565b67ffffffffffffffff16826000015160200181815161263791906134f0565b9052505090565b604082015160ff166003148061265b5750604082015160ff166002145b156126a057600061267483600001518460600151611c64565b90508067ffffffffffffffff16836000015160200181815161269691906134f0565b90525061224e9050565b604082015160ff16600414806126bd5750604082015160ff166005145b156126e7576126d482600001518360600151611c64565b67ffffffffffffffff1660808301525090565b604082015160ff1660071415806127195750816060015160ff166014141580156127195750816060015160ff16601514155b1561224e5760405162461bcd60e51b815260206004820152602760248201527f43626f725265616465722e736b69703a20756e737570706f72746564206d616a60448201527f6f72207479706500000000000000000000000000000000000000000000000000606482015260840161028f565b60008160200151826000015151808211156127dd576040517f63a056dd000000000000000000000000000000000000000000000000000000008152600481018390526024810182905260440161028f565b83516020850180518083016001015195509081906127fa82613680565b8152505050505050919050565b60008160200151600261281a91906134f0565b82515180821115612861576040517f63a056dd000000000000000000000000000000000000000000000000000000008152600481018390526024810182905260440161028f565b835160208501805160028184018101519650909161287f82846134f0565b9052509395945050505050565b60008160200151600461289f91906134f0565b825151808211156128e6576040517f63a056dd000000000000000000000000000000000000000000000000000000008152600481018390526024810182905260440161028f565b835160208501805160048184018101519650909161287f82846134f0565b60008160200151600861291791906134f0565b8251518082111561295e576040517f63a056dd000000000000000000000000000000000000000000000000000000008152600481018390526024810182905260440161028f565b835160208501805160088184018101519650909161287f82846134f0565b60408051808201909152606081526000602082015282515160006129a18260016134f0565b9050846020015182106129c2576129c2856129bd83600261369a565b612d6f565b84516020838201018581535080518211156129db578181525b5093949350505050565b6040805180820190915260608152600060208201528351516000612a0982856134f0565b90508560200151811115612a2657612a26866129bd83600261369a565b60006001612a3686610100613795565b612a40919061352b565b90508651828101878319825116178152508051831115612a5e578281525b50959695505050505050565b6040805180820190915260608152600060208201528251821115612a8d57600080fd5b8351516000612a9c84836134f0565b90508560200151811115612ab957612ab9866129bd83600261369a565b855180518382016020019160009180851115612ad3578482525b505050602086015b60208610612b135780518252612af26020836134f0565b9150612aff6020826134f0565b9050612b0c60208761352b565b9550612adb565b51815160001960208890036101000a0190811690199190911617905250849150509392505050565b6040805161010081018252606060c08201818152600060e084018190529083526020830181905292820183905281018290526080810182905260a08101919091528151518290600003612bba576040517f240db51c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060ff8167ffffffffffffffff8160015b8015612c5c57612bdb8961278c565b955081612be781613680565b6007600589901c169650601f881695509250507ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa8501612c54576020890151612c308a86611c64565b9350808a60200151612c42919061352b565b612c4c90846134f0565b925050612bcc565b506000612bcc565b600760ff86161115612c9f576040517fbd2ac87900000000000000000000000000000000000000000000000000000000815260ff8616600482015260240161028f565b506040805160c08101825289815260ff96871660208201529486169085015291909316606083015267ffffffffffffffff908116608083015290911660a082015291505b50919050565b60006018826060015160ff161015612d0357506000919050565b601c826060015160ff161015612d325760188260600151612d249190613643565b60ff166001901b9050919050565b60608201516040517f6d785b1300000000000000000000000000000000000000000000000000000000815260ff909116600482015260240161028f565b8151612d7b8383611dc4565b5061158783826121d0565b6040518060200160405280612d99612d9e565b905290565b6040518060400160405280612dc6604051806040016040528060608152602001600081525090565b8152602001600081525090565b67ffffffffffffffff8116811461065957600080fd5b80356116c181612dd3565b600060208284031215612e0657600080fd5b813561162281612dd3565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160c0810167ffffffffffffffff81118282101715612e6357612e63612e11565b60405290565b6040805190810167ffffffffffffffff81118282101715612e6357612e63612e11565b6040516080810167ffffffffffffffff81118282101715612e6357612e63612e11565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715612ef657612ef6612e11565b604052919050565b600067ffffffffffffffff831115612f1857612f18612e11565b612f4960207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f86011601612eaf565b9050828152838383011115612f5d57600080fd5b828260208301376000602084830101529392505050565b803560ff811681146116c157600080fd5b600082601f830112612f9657600080fd5b8135602067ffffffffffffffff80831115612fb357612fb3612e11565b8260051b612fc2838201612eaf565b9384528581018301938381019088861115612fdc57600080fd5b84880192505b8583101561310d57823584811115612ff957600080fd5b88017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe060c0828c038201121561302e57600080fd5b613036612e40565b878301358781111561304757600080fd5b83016040818e038401121561305b57600080fd5b613063612e69565b9250888101358881111561307657600080fd5b8101603f81018e1361308757600080fd5b6130988e8b83013560408401612efe565b845250604081013589840152508181526130b460408401612f74565b888201526130c460608401612f74565b60408201526130d560808401612f74565b60608201526130e660a08401612de9565b60808201526130f760c08401612de9565b60a0820152845250509184019190840190612fe2565b98975050505050505050565b600082601f83011261312a57600080fd5b61162283833560208501612efe565b60006020828403121561314b57600080fd5b813567ffffffffffffffff8082111561316357600080fd5b908301906080828603121561317757600080fd5b61317f612e8c565b823561318a81612dd3565b81526020830135801515811461319f57600080fd5b60208201526040830135828111156131b657600080fd5b6131c287828601612f85565b6040830152506060830135828111156131da57600080fd5b6131e687828601613119565b60608301525095945050505050565b6000806040838503121561320857600080fd5b823561321381612dd3565b9150602083013567ffffffffffffffff81111561322f57600080fd5b61323b85828601613119565b9150509250929050565b600181811c9082168061325957607f821691505b602082108103612ce3577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b601f821115611973576000816000526020600020601f850160051c810160208610156132bb5750805b601f850160051c820191505b81811015611250578281556001016132c7565b815167ffffffffffffffff8111156132f4576132f4612e11565b613308816133028454613245565b84613292565b602080601f83116001811461333d57600084156133255750858301515b600019600386901b1c1916600185901b178555611250565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b8281101561338a5788860151825594840194600190910190840161336b565b50858210156133a85787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b604081526000845160208060408501528151604060608601528051604060a087015280518060e088015260005b8181101561340257828101850151888201610100015284016133e5565b506000878201610100908101919091529284015160c088015284840151608088015263ffffffff881660208a901b1760401b84880152601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168601909101935061346b9050565b5050949350505050565b60006020828403121561348757600080fd5b815161162281612dd3565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082018082111561152b5761152b6134c1565b67ffffffffffffffff818116838216019080821115613524576135246134c1565b5092915050565b8181038181111561152b5761152b6134c1565b8181036000831280158383131683831282161715613524576135246134c1565b6000815160208301517fffffffffffffffffff0000000000000000000000000000000000000000000000808216935060098310156135a65780818460090360031b1b83161693505b505050919050565b61ffff8181168382160280821691908281146135cc576135cc6134c1565b505092915050565b61ffff818116838216019080821115613524576135246134c1565b60ff818116838216019081111561152b5761152b6134c1565b60008261363e577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500690565b60ff828116828216039081111561152b5761152b6134c1565b67ffffffffffffffff8181168382160280821691908281146135cc576135cc6134c1565b60006000198203613693576136936134c1565b5060010190565b808202811582820484141761152b5761152b6134c1565b600181815b808511156136ec5781600019048211156136d2576136d26134c1565b808516156136df57918102915b93841c93908002906136b6565b509250929050565b6000826137035750600161152b565b816137105750600061152b565b816001811461372657600281146137305761374c565b600191505061152b565b60ff841115613741576137416134c1565b50506001821b61152b565b5060208310610133831016604e8410600b841016171561376f575081810a61152b565b61377983836136b1565b806000190482111561378d5761378d6134c1565b029392505050565b600061162283836136f456fe73656c656374206361737428666c6f6f72286176672870726563697069746174696f6e5f616363756d756c61746564292920617320626967696e74292066726f6d20282073656c656374206465766963655f69642c206d61782870726563697069746174696f6e5f616363756d756c61746564292061732070726563697069746174696f6e5f616363756d756c617465642066726f6d20776561746865725f73746174696f6e732067726f7570206279206465766963655f6964202920a164736f6c6343000819000a000000000000000000000000f1960569d1b4a23c34109d9341af6496ed90c0c3

Deployed Bytecode

0x60806040526004361061005a5760003560e01c80634b9ba446116100435780634b9ba446146100895780638b6f0d74146100c6578063cae6a407146100e657600080fd5b8063272001e71461005f5780633ccfd60b14610074575b600080fd5b61007261006d366004612df4565b6100f9565b005b34801561008057600080fd5b506100726105ab565b34801561009557600080fd5b506100a96100a4366004612df4565b61065c565b60405167ffffffffffffffff909116815260200160405180910390f35b3480156100d257600080fd5b506100726100e1366004613139565b610bf6565b6100a96100f43660046131f5565b611258565b67ffffffffffffffff8082166000908152600260208181526040808420815161010080820184528254808916835273ffffffffffffffffffffffffffffffffffffffff6801000000000000000090910481169583019590955260018301549382019390935293810154909216606084015260038201546080840152600482015460ff8116151560a08501520490931660c08201526005830180549293919260e0840191906101a690613245565b80601f01602080910402602001604051908101604052809291908181526020018280546101d290613245565b801561021f5780601f106101f45761010080835404028352916020019161021f565b820191906000526020600020905b81548152906001019060200180831161020257829003601f168201915b50505091909252505050602081015190915073ffffffffffffffffffffffffffffffffffffffff166102985760405162461bcd60e51b815260206004820152601560248201527f706f6c69637920646f6573206e6f74206578697374000000000000000000000060448201526064015b60405180910390fd5b606081015173ffffffffffffffffffffffffffffffffffffffff16156103005760405162461bcd60e51b815260206004820152601b60248201527f706f6c6963792077617320616c72656164792061636365707465640000000000604482015260640161028f565b8060a00151156103525760405162461bcd60e51b815260206004820152601a60248201527f706f6c6963792077617320616c726561647920736574746c6564000000000000604482015260640161028f565b806040015134116103cb5760405162461bcd60e51b815260206004820152602260248201527f6e65656420746f2070726f766964652073756666696369656e74206465706f7360448201527f6974000000000000000000000000000000000000000000000000000000000000606482015260840161028f565b3360608201908152346080830190815267ffffffffffffffff84811660009081526002602081815260409283902087518154928901519086167fffffffff00000000000000000000000000000000000000000000000000000000909316929092176801000000000000000073ffffffffffffffffffffffffffffffffffffffff93841602178155928701516001840155945190820180547fffffffffffffffffffffffff00000000000000000000000000000000000000001691909516179093559051600383015560a083015160048301805460c08601517fffffffffffffffffffffffffffffffffffffffffffffff0000000000000000009091169215157fffffffffffffffffffffffffffffffffffffffffffffff0000000000000000ff1692909217610100929093169190910291909117905560e0820151829190600582019061051890826132da565b50905050806060015173ffffffffffffffffffffffffffffffffffffffff16816020015173ffffffffffffffffffffffffffffffffffffffff168367ffffffffffffffff167fac9f49869e29bfd82412359f358df8bf88224381ef1995ad3fb0e5b51c129c298460400151856080015160405161059f929190918252602082015260400190565b60405180910390a45050565b60005473ffffffffffffffffffffffffffffffffffffffff1633146106125760405162461bcd60e51b815260206004820152601760248201527f4f6e6c79206f776e65722063616e207769746864726177000000000000000000604482015260640161028f565b6000805460405173ffffffffffffffffffffffffffffffffffffffff909116914780156108fc02929091818181858888f19350505050158015610659573d6000803e3d6000fd5b50565b67ffffffffffffffff8082166000908152600260208181526040808420815161010080820184528254808916835273ffffffffffffffffffffffffffffffffffffffff6801000000000000000090910481169583019590955260018301549382019390935293810154909216606084015260038201546080840152600482015460ff8116151560a08501520490931660c082015260058301805492938493909160e084019161070a90613245565b80601f016020809104026020016040519081016040528092919081815260200182805461073690613245565b80156107835780601f1061075857610100808354040283529160200191610783565b820191906000526020600020905b81548152906001019060200180831161076657829003601f168201915b50505091909252505050602081015190915073ffffffffffffffffffffffffffffffffffffffff166107f75760405162461bcd60e51b815260206004820152601560248201527f706f6c69637920646f6573206e6f742065786973740000000000000000000000604482015260640161028f565b8060a00151156108495760405162461bcd60e51b815260206004820152601a60248201527f706f6c6963792077617320616c726561647920736574746c6564000000000000604482015260640161028f565b606081015173ffffffffffffffffffffffffffffffffffffffff16610a0f57600160a0820181815267ffffffffffffffff85811660009081526002602081815260409283902087518154928901519086167fffffffff00000000000000000000000000000000000000000000000000000000909316929092176801000000000000000073ffffffffffffffffffffffffffffffffffffffff938416021781559287015195830195909555606086015190820180547fffffffffffffffffffffffff000000000000000000000000000000000000000016919095161790935560808401516003840155905160048301805460c08601517fffffffffffffffffffffffffffffffffffffffffffffff0000000000000000009091169215157fffffffffffffffffffffffffffffffffffffffffffffff0000000000000000ff1692909217610100929093169190910291909117905560e082015182919060058201906109b390826132da565b50905050806020015173ffffffffffffffffffffffffffffffffffffffff166108fc82604001519081150290604051600060405180830381858888f19350505050158015610a05573d6000803e3d6000fd5b5060009392505050565b6000610a19611531565b9050610a696040518060400160405280601081526020017f776561746865725f73746174696f6e73000000000000000000000000000000008152508360e001518361156f9092919063ffffffff16565b610a8c6040518060e0016040528060bd81526020016137a260bd9139829061158d565b6001546040517fb8853b5400000000000000000000000000000000000000000000000000000000815260009173ffffffffffffffffffffffffffffffffffffffff169063b8853b5490610aeb9085903090638b6f0d74906004016133b8565b6020604051808303816000875af1158015610b0a573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b2e9190613475565b67ffffffffffffffff81811660008181526003602090815260409182902080547fffffffffffffffffffffffffffffffffffffffffffffffff0000000000000000168b8616179055606088810151898301518a518b86015160808d01518751918252958101959095529484019590955295965073ffffffffffffffffffffffffffffffffffffffff958616959093169391909116917f54bd3a28af22ebd07e9ba95adde85521fe7ae950fc9d3b4f5574b6deb506de11910160405180910390a4949350505050565b60015473ffffffffffffffffffffffffffffffffffffffff163314610c5d5760405162461bcd60e51b815260206004820152601c60248201527f43616e206f6e6c792062652063616c6c6564206279206f7261636c6500000000604482015260640161028f565b600060036000610c6b845190565b67ffffffffffffffff908116825260208201929092526040016000908120549091169150819003610cde5760405162461bcd60e51b815260206004820152601e60248201527f636f72726573706f6e64696e6720706f6c696379206e6f7420666f756e640000604482015260640161028f565b67ffffffffffffffff8082166000908152600260208181526040808420815161010080820184528254808916835273ffffffffffffffffffffffffffffffffffffffff6801000000000000000090910481169583019590955260018301549382019390935293810154909216606084015260038201546080840152600482015460ff8116151560a08501520490931660c08201526005830180549293919260e084019190610d8b90613245565b80601f0160208091040260200160405190810160405280929190818152602001828054610db790613245565b8015610e045780601f10610dd957610100808354040283529160200191610e04565b820191906000526020600020905b815481529060010190602001808311610de757829003601f168201915b50505091909252505050602081015190915073ffffffffffffffffffffffffffffffffffffffff1615801590610e535750606081015173ffffffffffffffffffffffffffffffffffffffff1615155b610e9f5760405162461bcd60e51b815260206004820152601a60248201527f706f6c69637920697320696e20696e76616c6964207374617465000000000000604482015260640161028f565b8060a0015115610ef15760405162461bcd60e51b815260206004820152601660248201527f706f6c69637920616c726561647920736574746c656400000000000000000000604482015260640161028f565b610efa836115dc565b67ffffffffffffffff16600114610f535760405162461bcd60e51b815260206004820152601360248201527f4578706563746564206f6e65207265636f726400000000000000000000000000604482015260640161028f565b6000610f5f84826115f0565b90506000610f8682600081518110610f7957610f79613492565b6020026020010151611629565b60c084018051600160a0870181815267ffffffffffffffff8981166000908152600260208181526040928390208c518154928e01519086167fffffffff00000000000000000000000000000000000000000000000000000000909316929092176801000000000000000073ffffffffffffffffffffffffffffffffffffffff93841602178155928c01519583019590955560608b015190820180547fffffffffffffffffffffffff000000000000000000000000000000000000000016919095161790935560808901516003840155905160048301805495517fffffffffffffffffffffffffffffffffffffffffffffff0000000000000000009096169115157fffffffffffffffffffffffffffffffffffffffffffffff0000000000000000ff1691909117610100958316959095029490941790935560e0870151939450908216918416919091109185919060058201906110e290826132da565b50905050836060015173ffffffffffffffffffffffffffffffffffffffff16846020015173ffffffffffffffffffffffffffffffffffffffff16856000015167ffffffffffffffff167f3cba6f1baeb45c5440208ba050bfeb9e604dc591d7661cf2c7d8065351423a048760400151886080015161115e8c5190565b60408051938452602084019290925267ffffffffffffffff1690820152851515606082015260800160405180910390a480156111f457836020015173ffffffffffffffffffffffffffffffffffffffff166108fc856080015186604001516111c691906134f0565b6040518115909202916000818181858888f193505050501580156111ee573d6000803e3d6000fd5b50611250565b836060015173ffffffffffffffffffffffffffffffffffffffff166108fc8560800151866040015161122691906134f0565b6040518115909202916000818181858888f1935050505015801561124e573d6000803e3d6000fd5b505b505050505050565b6000346000036112aa5760405162461bcd60e51b815260206004820152601960248201527f6e65656420746f2070726f766964652061206465706f73697400000000000000604482015260640161028f565b6001805481906014906112e090839074010000000000000000000000000000000000000000900467ffffffffffffffff16613503565b825467ffffffffffffffff91821661010093840a908102920219161790915560408051918201815260008083526020830181905290820181905260608083018290526080830182905260a0830182905260c083019190915260e082015290506001805474010000000000000000000000000000000000000000900467ffffffffffffffff9081168084523360208086019182523460408088019182528a861660c0890190815260e089018b81526000968752600294859052919095208851815495519088167fffffffff00000000000000000000000000000000000000000000000000000000909616959095176801000000000000000073ffffffffffffffffffffffffffffffffffffffff96871602178155915196820196909655606087015191810180547fffffffffffffffffffffffff00000000000000000000000000000000000000001692909316919091179091556080850151600382015560a085015160048201805493517fffffffffffffffffffffffffffffffffffffffffffffff0000000000000000009094169115157fffffffffffffffffffffffffffffffffffffffffffffff0000000000000000ff16919091176101009390941692909202929092179055905182919060058201906114bc90826132da565b50905050806020015173ffffffffffffffffffffffffffffffffffffffff16816000015167ffffffffffffffff167fe9b43372ad2470bf088a19481efde518124553fb2f7cb1216c0b8f83cf15ff45836040015160405161151f91815260200190565b60405180910390a35190505b92915050565b611539612d86565b60006115466104006116c6565b9050611551816116e7565b61155c81600161170b565b6040805160208101909152908152919050565b600061157a82611717565b905061158784848361191c565b50505050565b60408051808201909152600381527f73716c0000000000000000000000000000000000000000000000000000000000602082015282516115cc91611978565b81516115d89082611978565b5050565b6000600182604001515161152b919061352b565b606061162283604001518367ffffffffffffffff168151811061161557611615613492565b6020026020010151611991565b9392505050565b6000816040015160ff1660010361166657600061164e83600001518460600151611c64565b905061162267ffffffffffffffff821660001961353e565b816040015160ff1660000361167e5761152b82611d46565b60408083015190517e1000a000000000000000000000000000000000000000000000000000000000815260ff90911660048201526001602482015260440161028f565b919050565b6116ce612d9e565b80516116da9083611dc4565b5060006020820152919050565b6116f2816004611e3b565b60018160200181815161170591906134f0565b90525050565b6115d882600083611e52565b80516060908290604d1461176d5760405162461bcd60e51b815260206004820152600b60248201527f496e76616c696420444944000000000000000000000000000000000000000000604482015260640161028f565b6117768161355e565b76ffffffffffffffffffffffffffffffffffffffffffffff19167f6469643a6f64663a660000000000000000000000000000000000000000000000146117fe5760405162461bcd60e51b815260206004820152600b60248201527f496e76616c696420444944000000000000000000000000000000000000000000604482015260640161028f565b6040805160228082526060820190925260009160208201818036833701905050905060005b60228161ffff16101561191457600061183d8260026135ae565b6118489060096135d4565b9050611899846118598360016135d4565b61ffff168151811061186d5761186d613492565b01602001517fff0000000000000000000000000000000000000000000000000000000000000016611f73565b60046118b4868461ffff168151811061186d5761186d613492565b60ff16901b6118c391906135ef565b60f81b838361ffff16815181106118dc576118dc613492565b60200101907effffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff1916908160001a90535050600101611823565b509392505050565b60408051808201909152600281527f64730000000000000000000000000000000000000000000000000000000000006020820152835161195b91611978565b82516119679083611978565b825161197390826121c3565b505050565b6119858260038351611e52565b815161197390826121d0565b60608160048060ff16826040015160ff16146119eb5760408083015190517e1000a000000000000000000000000000000000000000000000000000000000815260ff9182166004820152908216602482015260440161028f565b60006119ff85600001518660600151611c64565b9050611a0c816001613503565b67ffffffffffffffff1667ffffffffffffffff811115611a2e57611a2e612e11565b604051908082528060200260200182016040528015611a9e57816020015b6040805161010081018252606060c08201818152600060e0840181905290835260208084018290529383018190529082018190526080820181905260a08201528252600019909201910181611a4c5790505b50935060005b8167ffffffffffffffff16811015611c3357611abf866121f1565b9550611b98866040805161010081018252606060c08201818152600060e084018190529083526020830181905292820183905281018290526080810182905260a08101919091526040805160c081018083528451610100830184526060909152600060e0830152825180840190935280518352602090810151908301529081908152602001836020015160ff168152602001836040015160ff168152602001836060015160ff168152602001836080015167ffffffffffffffff1681526020018360a0015167ffffffffffffffff168152509050919050565b858281518110611baa57611baa613492565b6020026020010181905250600460ff16866040015160ff1603611c03576000611bd287611991565b90508060018251611be3919061352b565b81518110611bf357611bf3613492565b6020026020010151965050611c2b565b600560ff16866040015160ff1603611c20576000611bd287612252565b611c2986612578565b505b600101611aa4565b5084848267ffffffffffffffff1681518110611c5157611c51613492565b6020026020010181905250505050919050565b600060188260ff161015611c7c575060ff811661152b565b8160ff16601803611c9a57611c908361278c565b60ff16905061152b565b8160ff16601903611cb957611cae83612807565b61ffff16905061152b565b8160ff16601a03611cda57611ccd8361288c565b63ffffffff16905061152b565b8160ff16601b03611cf557611cee83612904565b905061152b565b8160ff16601f03611d0f575067ffffffffffffffff61152b565b6040517f6d785b1300000000000000000000000000000000000000000000000000000000815260ff8316600482015260240161028f565b60008160008060ff16826040015160ff1614611da05760408083015190517e1000a000000000000000000000000000000000000000000000000000000000815260ff9182166004820152908216602482015260440161028f565b611db284600001518560600151611c64565b67ffffffffffffffff16949350505050565b604080518082019091526060815260006020820152611de4602083613608565b15611e0c57611df4602083613608565b611dff90602061352b565b611e0990836134f0565b91505b602080840183905260405180855260008152908184010181811015611e3057600080fd5b604052509192915050565b815161197390601f611fe0600585901b161761297c565b60178167ffffffffffffffff1611611e795782516115879060e0600585901b16831761297c565b60ff8167ffffffffffffffff1611611ebb578251611ea2906018611fe0600586901b161761297c565b5082516115879067ffffffffffffffff831660016129e5565b61ffff8167ffffffffffffffff1611611efe578251611ee5906019611fe0600586901b161761297c565b5082516115879067ffffffffffffffff831660026129e5565b63ffffffff8167ffffffffffffffff1611611f43578251611f2a90601a611fe0600586901b161761297c565b5082516115879067ffffffffffffffff831660046129e5565b8251611f5a90601b611fe0600586901b161761297c565b5082516115879067ffffffffffffffff831660086129e5565b60007f30000000000000000000000000000000000000000000000000000000000000007fff0000000000000000000000000000000000000000000000000000000000000083161080159061200957507f39000000000000000000000000000000000000000000000000000000000000007fff00000000000000000000000000000000000000000000000000000000000000831611155b1561201d5761152b603060f884901c613643565b7f61000000000000000000000000000000000000000000000000000000000000007fff000000000000000000000000000000000000000000000000000000000000008316108015906120b157507f66000000000000000000000000000000000000000000000000000000000000007fff00000000000000000000000000000000000000000000000000000000000000831611155b156120d15760616120c760f884901c600a6135ef565b61152b9190613643565b7f41000000000000000000000000000000000000000000000000000000000000007fff0000000000000000000000000000000000000000000000000000000000000083161080159061216557507f46000000000000000000000000000000000000000000000000000000000000007fff00000000000000000000000000000000000000000000000000000000000000831611155b1561217b5760416120c760f884901c600a6135ef565b60405162461bcd60e51b815260206004820152600e60248201527f4e6f742061206865782063686172000000000000000000000000000000000000604482015260640161028f565b6119858260028351611e52565b60408051808201909152606081526000602082015261162283838451612a6a565b6040805161010081018252606060c08201818152600060e084018190529083526020830181905292820183905281018290526080810182905260a08101919091528151805151602090910151101561224e57815161152b90612b3b565b5090565b60608160058060ff16826040015160ff16146122ac5760408083015190517e1000a000000000000000000000000000000000000000000000000000000000815260ff9182166004820152908216602482015260440161028f565b60006122c085600001518660600151611c64565b6122cb90600261365c565b90506122d8816001613503565b67ffffffffffffffff1667ffffffffffffffff8111156122fa576122fa612e11565b60405190808252806020026020018201604052801561236a57816020015b6040805161010081018252606060c08201818152600060e0840181905290835260208084018290529383018190529082018190526080820181905260a082015282526000199092019101816123185790505b50935060005b8167ffffffffffffffff16811015611c335761238b866121f1565b9550612464866040805161010081018252606060c08201818152600060e084018190529083526020830181905292820183905281018290526080810182905260a08101919091526040805160c081018083528451610100830184526060909152600060e0830152825180840190935280518352602090810151908301529081908152602001836020015160ff168152602001836040015160ff168152602001836060015160ff168152602001836080015167ffffffffffffffff1681526020018360a0015167ffffffffffffffff168152509050919050565b85828151811061247657612476613492565b602090810291909101015261248c600282613608565b1580156124a15750604086015160ff16600314155b156124e95760408087015190517e1000a000000000000000000000000000000000000000000000000000000000815260ff90911660048201526003602482015260440161028f565b604086015160ff16600414806125065750604086015160ff166005145b1561256557604086015160009060ff1660041461252b5761252687612252565b612534565b61253487611991565b90508060018251612545919061352b565b8151811061255557612555613492565b6020026020010151965050612570565b61256e86612578565b505b600101612370565b6040805161010081018252606060c08201818152600060e08401819052908352602083018190528284018190529082018190526080820181905260a08201529082015160ff1615806125d15750604082015160ff166001145b8061260a5750604082015160ff1660071480156125f657506019826060015160ff1610155b801561260a5750601b826060015160ff1611155b1561263e5761261882612ce9565b67ffffffffffffffff16826000015160200181815161263791906134f0565b9052505090565b604082015160ff166003148061265b5750604082015160ff166002145b156126a057600061267483600001518460600151611c64565b90508067ffffffffffffffff16836000015160200181815161269691906134f0565b90525061224e9050565b604082015160ff16600414806126bd5750604082015160ff166005145b156126e7576126d482600001518360600151611c64565b67ffffffffffffffff1660808301525090565b604082015160ff1660071415806127195750816060015160ff166014141580156127195750816060015160ff16601514155b1561224e5760405162461bcd60e51b815260206004820152602760248201527f43626f725265616465722e736b69703a20756e737570706f72746564206d616a60448201527f6f72207479706500000000000000000000000000000000000000000000000000606482015260840161028f565b60008160200151826000015151808211156127dd576040517f63a056dd000000000000000000000000000000000000000000000000000000008152600481018390526024810182905260440161028f565b83516020850180518083016001015195509081906127fa82613680565b8152505050505050919050565b60008160200151600261281a91906134f0565b82515180821115612861576040517f63a056dd000000000000000000000000000000000000000000000000000000008152600481018390526024810182905260440161028f565b835160208501805160028184018101519650909161287f82846134f0565b9052509395945050505050565b60008160200151600461289f91906134f0565b825151808211156128e6576040517f63a056dd000000000000000000000000000000000000000000000000000000008152600481018390526024810182905260440161028f565b835160208501805160048184018101519650909161287f82846134f0565b60008160200151600861291791906134f0565b8251518082111561295e576040517f63a056dd000000000000000000000000000000000000000000000000000000008152600481018390526024810182905260440161028f565b835160208501805160088184018101519650909161287f82846134f0565b60408051808201909152606081526000602082015282515160006129a18260016134f0565b9050846020015182106129c2576129c2856129bd83600261369a565b612d6f565b84516020838201018581535080518211156129db578181525b5093949350505050565b6040805180820190915260608152600060208201528351516000612a0982856134f0565b90508560200151811115612a2657612a26866129bd83600261369a565b60006001612a3686610100613795565b612a40919061352b565b90508651828101878319825116178152508051831115612a5e578281525b50959695505050505050565b6040805180820190915260608152600060208201528251821115612a8d57600080fd5b8351516000612a9c84836134f0565b90508560200151811115612ab957612ab9866129bd83600261369a565b855180518382016020019160009180851115612ad3578482525b505050602086015b60208610612b135780518252612af26020836134f0565b9150612aff6020826134f0565b9050612b0c60208761352b565b9550612adb565b51815160001960208890036101000a0190811690199190911617905250849150509392505050565b6040805161010081018252606060c08201818152600060e084018190529083526020830181905292820183905281018290526080810182905260a08101919091528151518290600003612bba576040517f240db51c00000000000000000000000000000000000000000000000000000000815260040160405180910390fd5b600060ff8167ffffffffffffffff8160015b8015612c5c57612bdb8961278c565b955081612be781613680565b6007600589901c169650601f881695509250507ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffa8501612c54576020890151612c308a86611c64565b9350808a60200151612c42919061352b565b612c4c90846134f0565b925050612bcc565b506000612bcc565b600760ff86161115612c9f576040517fbd2ac87900000000000000000000000000000000000000000000000000000000815260ff8616600482015260240161028f565b506040805160c08101825289815260ff96871660208201529486169085015291909316606083015267ffffffffffffffff908116608083015290911660a082015291505b50919050565b60006018826060015160ff161015612d0357506000919050565b601c826060015160ff161015612d325760188260600151612d249190613643565b60ff166001901b9050919050565b60608201516040517f6d785b1300000000000000000000000000000000000000000000000000000000815260ff909116600482015260240161028f565b8151612d7b8383611dc4565b5061158783826121d0565b6040518060200160405280612d99612d9e565b905290565b6040518060400160405280612dc6604051806040016040528060608152602001600081525090565b8152602001600081525090565b67ffffffffffffffff8116811461065957600080fd5b80356116c181612dd3565b600060208284031215612e0657600080fd5b813561162281612dd3565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b60405160c0810167ffffffffffffffff81118282101715612e6357612e63612e11565b60405290565b6040805190810167ffffffffffffffff81118282101715612e6357612e63612e11565b6040516080810167ffffffffffffffff81118282101715612e6357612e63612e11565b604051601f82017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe016810167ffffffffffffffff81118282101715612ef657612ef6612e11565b604052919050565b600067ffffffffffffffff831115612f1857612f18612e11565b612f4960207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f86011601612eaf565b9050828152838383011115612f5d57600080fd5b828260208301376000602084830101529392505050565b803560ff811681146116c157600080fd5b600082601f830112612f9657600080fd5b8135602067ffffffffffffffff80831115612fb357612fb3612e11565b8260051b612fc2838201612eaf565b9384528581018301938381019088861115612fdc57600080fd5b84880192505b8583101561310d57823584811115612ff957600080fd5b88017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe060c0828c038201121561302e57600080fd5b613036612e40565b878301358781111561304757600080fd5b83016040818e038401121561305b57600080fd5b613063612e69565b9250888101358881111561307657600080fd5b8101603f81018e1361308757600080fd5b6130988e8b83013560408401612efe565b845250604081013589840152508181526130b460408401612f74565b888201526130c460608401612f74565b60408201526130d560808401612f74565b60608201526130e660a08401612de9565b60808201526130f760c08401612de9565b60a0820152845250509184019190840190612fe2565b98975050505050505050565b600082601f83011261312a57600080fd5b61162283833560208501612efe565b60006020828403121561314b57600080fd5b813567ffffffffffffffff8082111561316357600080fd5b908301906080828603121561317757600080fd5b61317f612e8c565b823561318a81612dd3565b81526020830135801515811461319f57600080fd5b60208201526040830135828111156131b657600080fd5b6131c287828601612f85565b6040830152506060830135828111156131da57600080fd5b6131e687828601613119565b60608301525095945050505050565b6000806040838503121561320857600080fd5b823561321381612dd3565b9150602083013567ffffffffffffffff81111561322f57600080fd5b61323b85828601613119565b9150509250929050565b600181811c9082168061325957607f821691505b602082108103612ce3577f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b601f821115611973576000816000526020600020601f850160051c810160208610156132bb5750805b601f850160051c820191505b81811015611250578281556001016132c7565b815167ffffffffffffffff8111156132f4576132f4612e11565b613308816133028454613245565b84613292565b602080601f83116001811461333d57600084156133255750858301515b600019600386901b1c1916600185901b178555611250565b6000858152602081207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08616915b8281101561338a5788860151825594840194600190910190840161336b565b50858210156133a85787850151600019600388901b60f8161c191681555b5050505050600190811b01905550565b604081526000845160208060408501528151604060608601528051604060a087015280518060e088015260005b8181101561340257828101850151888201610100015284016133e5565b506000878201610100908101919091529284015160c088015284840151608088015263ffffffff881660208a901b1760401b84880152601f017fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0168601909101935061346b9050565b5050949350505050565b60006020828403121561348757600080fd5b815161162281612dd3565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b8082018082111561152b5761152b6134c1565b67ffffffffffffffff818116838216019080821115613524576135246134c1565b5092915050565b8181038181111561152b5761152b6134c1565b8181036000831280158383131683831282161715613524576135246134c1565b6000815160208301517fffffffffffffffffff0000000000000000000000000000000000000000000000808216935060098310156135a65780818460090360031b1b83161693505b505050919050565b61ffff8181168382160280821691908281146135cc576135cc6134c1565b505092915050565b61ffff818116838216019080821115613524576135246134c1565b60ff818116838216019081111561152b5761152b6134c1565b60008261363e577f4e487b7100000000000000000000000000000000000000000000000000000000600052601260045260246000fd5b500690565b60ff828116828216039081111561152b5761152b6134c1565b67ffffffffffffffff8181168382160280821691908281146135cc576135cc6134c1565b60006000198203613693576136936134c1565b5060010190565b808202811582820484141761152b5761152b6134c1565b600181815b808511156136ec5781600019048211156136d2576136d26134c1565b808516156136df57918102915b93841c93908002906136b6565b509250929050565b6000826137035750600161152b565b816137105750600061152b565b816001811461372657600281146137305761374c565b600191505061152b565b60ff841115613741576137416134c1565b50506001821b61152b565b5060208310610133831016604e8410600b841016171561376f575081810a61152b565b61377983836136b1565b806000190482111561378d5761378d6134c1565b029392505050565b600061162283836136f456fe73656c656374206361737428666c6f6f72286176672870726563697069746174696f6e5f616363756d756c61746564292920617320626967696e74292066726f6d20282073656c656374206465766963655f69642c206d61782870726563697069746174696f6e5f616363756d756c61746564292061732070726563697069746174696f6e5f616363756d756c617465642066726f6d20776561746865725f73746174696f6e732067726f7570206279206465766963655f6964202920a164736f6c6343000819000a

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

000000000000000000000000f1960569d1b4a23c34109d9341af6496ed90c0c3

-----Decoded View---------------
Arg [0] : oracleAddr (address): 0xf1960569d1b4A23c34109D9341Af6496Ed90C0c3

-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 000000000000000000000000f1960569d1b4a23c34109d9341af6496ed90c0c3


Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

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

Validator Index Block Amount
View All Withdrawals

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

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