Contract 0x129AD040Bd127c00d6De9051b3CfE9F3E36453D3

 
Txn Hash
Block
From
To
Value [Txn Fee]
0xd10d010c39a9b27a63c9fd5101bafbfd995ee384d0f74055dc368d8f88e635425890232021-09-12 15:35:515 days 2 hrs ago0xb943e534ccb68a976bfa9007ad6705c76da81ec6 IN  0x129ad040bd127c00d6de9051b3cfe9f3e36453d30 ETH0.000888617526 ETH
0x302bc9619bed7130f2bad0c13ed7bfdae237d846415cc3986da2ce5b9e5bef362199092021-08-17 13:23:5431 days 5 hrs ago0x904b5993fc92979eeedc19ccc58bed6b7216667c IN  Contract Creation0 ETH0.009401028878 ETH
[ Download CSV Export 
Parent Txn Hash Block From To Value
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
InverseStateService

Compiler Version
v0.7.4+commit.3f05b770

Optimization Enabled:
Yes with 1000 runs

Other Settings:
default evmVersion

Contract Source Code (Solidity Standard Json-Input format)

File 1 of 2 : InverseStateService.sol
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.7.4;
pragma experimental ABIEncoderV2;

import "@openzeppelin/contracts/utils/EnumerableSet.sol";

contract InverseStateService {
    using EnumerableSet for EnumerableSet.Bytes32Set;

    EnumerableSet.Bytes32Set internal _inverseStates;

    event SetInverseState(address indexed liquidityPool, uint256 perpetualIndex, bool isInverse);

    function setInverseState(
        address liquidityPool,
        uint256 perpetualIndex,
        bool isInverse_
    ) external {
        require(liquidityPool != address(0), "liquidityPool is zero address");
        (address operator, uint256 perpetualCount) = _getLiquidityPoolInfo(liquidityPool);
        require(msg.sender == operator, "caller must be the operator of the liquidityPool");
        require(perpetualIndex < perpetualCount, "perpetualIndex exceeds count of perpetuals");

        bytes32 key = _encode(liquidityPool, perpetualIndex);
        bool isExist = _inverseStates.contains(key);
        require(isInverse_ ? !isExist : isExist, "duplicated operation");
        if (isInverse_) {
            _inverseStates.add(key);
        } else {
            _inverseStates.remove(key);
        }
        emit SetInverseState(liquidityPool, perpetualIndex, isInverse_);
    }

    function isInverse(address liquidityPool, uint256 perpetualIndex) public view returns (bool) {
        return _inverseStates.contains(_encode(liquidityPool, perpetualIndex));
    }

    function export(uint256 begin, uint256 end) external view returns (bytes32[] memory result) {
        require(end > begin, "begin should be lower than end");
        uint256 length = _inverseStates.length();
        if (begin >= length) {
            return result;
        }
        uint256 safeEnd = end > length ? length : end;
        result = new bytes32[](safeEnd - begin);
        for (uint256 i = begin; i < safeEnd; i++) {
            result[i - begin] = _inverseStates.at(i);
        }
        return result;
    }

    function _getLiquidityPoolInfo(address liquidityPool)
        internal
        view
        returns (address operator, uint256 perpetualCount)
    {
        (bool success, bytes memory result) = liquidityPool.staticcall(
            abi.encodeWithSignature("getLiquidityPoolInfo()")
        );
        require(success, "call getLiquidityPoolInfo failed");
        assembly {
            operator := mload(add(result, 128)) // 32 + 32 * 3
            perpetualCount := mload(add(result, 512)) // 32 + 32 * 15
        }
    }

    function _encode(address liquidityPool, uint256 perpetualIndex)
        internal
        pure
        returns (bytes32 key)
    {
        require(perpetualIndex <= type(uint32).max, "perpetualIndex exceeds uint32.max");
        bytes memory packed = abi.encodePacked(liquidityPool, uint32(perpetualIndex));
        assembly {
            key := mload(add(packed, 32))
        }
    }

    function _decode(bytes32 key)
        internal
        pure
        returns (address liquidityPool, uint256 perpetualIndex)
    {
        liquidityPool = address(bytes20(key));
        perpetualIndex = uint256(uint32(bytes4(key << 160)));
    }
}

File 2 of 2 : EnumerableSet.sol
// SPDX-License-Identifier: MIT

pragma solidity >=0.6.0 <0.8.0;

/**
 * @dev Library for managing
 * https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
 * types.
 *
 * Sets have the following properties:
 *
 * - Elements are added, removed, and checked for existence in constant time
 * (O(1)).
 * - Elements are enumerated in O(n). No guarantees are made on the ordering.
 *
 * ```
 * contract Example {
 *     // Add the library methods
 *     using EnumerableSet for EnumerableSet.AddressSet;
 *
 *     // Declare a set state variable
 *     EnumerableSet.AddressSet private mySet;
 * }
 * ```
 *
 * As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
 * and `uint256` (`UintSet`) are supported.
 */
library EnumerableSet {
    // To implement this library for multiple types with as little code
    // repetition as possible, we write it in terms of a generic Set type with
    // bytes32 values.
    // The Set implementation uses private functions, and user-facing
    // implementations (such as AddressSet) are just wrappers around the
    // underlying Set.
    // This means that we can only create new EnumerableSets for types that fit
    // in bytes32.

    struct Set {
        // Storage of set values
        bytes32[] _values;

        // Position of the value in the `values` array, plus 1 because index 0
        // means a value is not in the set.
        mapping (bytes32 => uint256) _indexes;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function _add(Set storage set, bytes32 value) private returns (bool) {
        if (!_contains(set, value)) {
            set._values.push(value);
            // The value is stored at length-1, but we add 1 to all indexes
            // and use 0 as a sentinel value
            set._indexes[value] = set._values.length;
            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function _remove(Set storage set, bytes32 value) private returns (bool) {
        // We read and store the value's index to prevent multiple reads from the same storage slot
        uint256 valueIndex = set._indexes[value];

        if (valueIndex != 0) { // Equivalent to contains(set, value)
            // To delete an element from the _values array in O(1), we swap the element to delete with the last one in
            // the array, and then remove the last element (sometimes called as 'swap and pop').
            // This modifies the order of the array, as noted in {at}.

            uint256 toDeleteIndex = valueIndex - 1;
            uint256 lastIndex = set._values.length - 1;

            // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs
            // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.

            bytes32 lastvalue = set._values[lastIndex];

            // Move the last value to the index where the value to delete is
            set._values[toDeleteIndex] = lastvalue;
            // Update the index for the moved value
            set._indexes[lastvalue] = toDeleteIndex + 1; // All indexes are 1-based

            // Delete the slot where the moved value was stored
            set._values.pop();

            // Delete the index for the deleted slot
            delete set._indexes[value];

            return true;
        } else {
            return false;
        }
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function _contains(Set storage set, bytes32 value) private view returns (bool) {
        return set._indexes[value] != 0;
    }

    /**
     * @dev Returns the number of values on the set. O(1).
     */
    function _length(Set storage set) private view returns (uint256) {
        return set._values.length;
    }

   /**
    * @dev Returns the value stored at position `index` in the set. O(1).
    *
    * Note that there are no guarantees on the ordering of values inside the
    * array, and it may change when more values are added or removed.
    *
    * Requirements:
    *
    * - `index` must be strictly less than {length}.
    */
    function _at(Set storage set, uint256 index) private view returns (bytes32) {
        require(set._values.length > index, "EnumerableSet: index out of bounds");
        return set._values[index];
    }

    // Bytes32Set

    struct Bytes32Set {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
        return _add(set._inner, value);
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
        return _remove(set._inner, value);
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
        return _contains(set._inner, value);
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(Bytes32Set storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

   /**
    * @dev Returns the value stored at position `index` in the set. O(1).
    *
    * Note that there are no guarantees on the ordering of values inside the
    * array, and it may change when more values are added or removed.
    *
    * Requirements:
    *
    * - `index` must be strictly less than {length}.
    */
    function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
        return _at(set._inner, index);
    }

    // AddressSet

    struct AddressSet {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(AddressSet storage set, address value) internal returns (bool) {
        return _add(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(AddressSet storage set, address value) internal returns (bool) {
        return _remove(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(AddressSet storage set, address value) internal view returns (bool) {
        return _contains(set._inner, bytes32(uint256(uint160(value))));
    }

    /**
     * @dev Returns the number of values in the set. O(1).
     */
    function length(AddressSet storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

   /**
    * @dev Returns the value stored at position `index` in the set. O(1).
    *
    * Note that there are no guarantees on the ordering of values inside the
    * array, and it may change when more values are added or removed.
    *
    * Requirements:
    *
    * - `index` must be strictly less than {length}.
    */
    function at(AddressSet storage set, uint256 index) internal view returns (address) {
        return address(uint160(uint256(_at(set._inner, index))));
    }


    // UintSet

    struct UintSet {
        Set _inner;
    }

    /**
     * @dev Add a value to a set. O(1).
     *
     * Returns true if the value was added to the set, that is if it was not
     * already present.
     */
    function add(UintSet storage set, uint256 value) internal returns (bool) {
        return _add(set._inner, bytes32(value));
    }

    /**
     * @dev Removes a value from a set. O(1).
     *
     * Returns true if the value was removed from the set, that is if it was
     * present.
     */
    function remove(UintSet storage set, uint256 value) internal returns (bool) {
        return _remove(set._inner, bytes32(value));
    }

    /**
     * @dev Returns true if the value is in the set. O(1).
     */
    function contains(UintSet storage set, uint256 value) internal view returns (bool) {
        return _contains(set._inner, bytes32(value));
    }

    /**
     * @dev Returns the number of values on the set. O(1).
     */
    function length(UintSet storage set) internal view returns (uint256) {
        return _length(set._inner);
    }

   /**
    * @dev Returns the value stored at position `index` in the set. O(1).
    *
    * Note that there are no guarantees on the ordering of values inside the
    * array, and it may change when more values are added or removed.
    *
    * Requirements:
    *
    * - `index` must be strictly less than {length}.
    */
    function at(UintSet storage set, uint256 index) internal view returns (uint256) {
        return uint256(_at(set._inner, index));
    }
}

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 1000
  },
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "abi"
      ]
    }
  },
  "libraries": {}
}

Contract ABI

[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"liquidityPool","type":"address"},{"indexed":false,"internalType":"uint256","name":"perpetualIndex","type":"uint256"},{"indexed":false,"internalType":"bool","name":"isInverse","type":"bool"}],"name":"SetInverseState","type":"event"},{"inputs":[{"internalType":"uint256","name":"begin","type":"uint256"},{"internalType":"uint256","name":"end","type":"uint256"}],"name":"export","outputs":[{"internalType":"bytes32[]","name":"result","type":"bytes32[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"liquidityPool","type":"address"},{"internalType":"uint256","name":"perpetualIndex","type":"uint256"}],"name":"isInverse","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"liquidityPool","type":"address"},{"internalType":"uint256","name":"perpetualIndex","type":"uint256"},{"internalType":"bool","name":"isInverse_","type":"bool"}],"name":"setInverseState","outputs":[],"stateMutability":"nonpayable","type":"function"}]

608060405234801561001057600080fd5b506109b8806100206000396000f3fe608060405234801561001057600080fd5b50600436106100415760003560e01c8063160eee8814610046578063312b04351461005b578063aeb0abbb14610084575b600080fd5b61005961005436600461062c565b6100a4565b005b61006e61006936600461066f565b6101e1565b60405161007b9190610710565b60405180910390f35b610097610092366004610603565b6102b6565b60405161007b9190610754565b6001600160a01b0383166100d35760405162461bcd60e51b81526004016100ca90610885565b60405180910390fd5b6000806100df856102d4565b9092509050336001600160a01b0383161461010c5760405162461bcd60e51b81526004016100ca906108bc565b80841061012b5760405162461bcd60e51b81526004016100ca9061075f565b600061013786866103c2565b905060006101458183610419565b9050846101525780610155565b80155b6101715760405162461bcd60e51b81526004016100ca90610919565b841561018857610182600083610425565b50610195565b610193600083610431565b505b866001600160a01b03167f2b70e1ec5a268bad42523803ab84bceb3de0f8616314fe7484906a86a575bae587876040516101d0929190610950565b60405180910390a250505050505050565b60608282116102025760405162461bcd60e51b81526004016100ca906107bc565b600061020e600061043d565b905080841061021d57506102b0565b600081841161022c578361022e565b815b905084810367ffffffffffffffff8111801561024957600080fd5b50604051908082528060200260200182016040528015610273578160200160208202803683370190505b509250845b818110156102ac5761028b600082610450565b848783038151811061029957fe5b6020908102919091010152600101610278565b5050505b92915050565b60006102cd6102c584846103c2565b600090610419565b9392505050565b60408051600481526024810182526020810180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff167f0cdc105a000000000000000000000000000000000000000000000000000000001790529051600091829182916060916001600160a01b0387169161034a916106d7565b600060405180830381855afa9150503d8060008114610385576040519150601f19603f3d011682016040523d82523d6000602084013e61038a565b606091505b5091509150816103ac5760405162461bcd60e51b81526004016100ca906107f3565b6080810151935061020081015192505050915091565b600063ffffffff8211156103e85760405162461bcd60e51b81526004016100ca90610828565b606083836040516020016103fd929190610690565b60408051601f1981840301815291905260200151949350505050565b60006102cd838361045c565b60006102cd8383610474565b60006102cd83836104be565b600061044882610584565b90505b919050565b60006102cd8383610588565b60009081526001919091016020526040902054151590565b6000610480838361045c565b6104b6575081546001818101845560008481526020808220909301849055845484825282860190935260409020919091556102b0565b5060006102b0565b6000818152600183016020526040812054801561057a57835460001980830191908101906000908790839081106104f157fe5b906000526020600020015490508087600001848154811061050e57fe5b60009182526020808320909101929092558281526001898101909252604090209084019055865487908061053e57fe5b600190038181906000526020600020016000905590558660010160008781526020019081526020016000206000905560019450505050506102b0565b60009150506102b0565b5490565b815460009082106105ca5760405162461bcd60e51b81526004018080602001828103825260228152602001806109616022913960400191505060405180910390fd5b8260000182815481106105d957fe5b9060005260206000200154905092915050565b80356001600160a01b038116811461044b57600080fd5b60008060408385031215610615578182fd5b61061e836105ec565b946020939093013593505050565b600080600060608486031215610640578081fd5b610649846105ec565b92506020840135915060408401358015158114610664578182fd5b809150509250925092565b60008060408385031215610681578182fd5b50508035926020909101359150565b60609290921b6bffffffffffffffffffffffff1916825260e01b7fffffffff0000000000000000000000000000000000000000000000000000000016601482015260180190565b60008251815b818110156106f757602081860181015185830152016106dd565b818111156107055782828501525b509190910192915050565b6020808252825182820181905260009190848201906040850190845b818110156107485783518352928401929184019160010161072c565b50909695505050505050565b901515815260200190565b6020808252602a908201527f70657270657475616c496e646578206578636565647320636f756e74206f662060408201527f70657270657475616c7300000000000000000000000000000000000000000000606082015260800190565b6020808252601e908201527f626567696e2073686f756c64206265206c6f776572207468616e20656e640000604082015260600190565b6020808252818101527f63616c6c206765744c6971756964697479506f6f6c496e666f206661696c6564604082015260600190565b60208082526021908201527f70657270657475616c496e64657820657863656564732075696e7433322e6d6160408201527f7800000000000000000000000000000000000000000000000000000000000000606082015260800190565b6020808252601d908201527f6c6971756964697479506f6f6c206973207a65726f2061646472657373000000604082015260600190565b60208082526030908201527f63616c6c6572206d75737420626520746865206f70657261746f72206f66207460408201527f6865206c6971756964697479506f6f6c00000000000000000000000000000000606082015260800190565b60208082526014908201527f6475706c696361746564206f7065726174696f6e000000000000000000000000604082015260600190565b918252151560208201526040019056fe456e756d657261626c655365743a20696e646578206f7574206f6620626f756e6473a2646970667358221220b8e601650a95a51c9002124981ebcf20ee2ac78275542b67e6eed09c7973ca0f64736f6c63430007040033

Block Transaction Gas Used Reward
Age Block Fee Address BC Fee Address Voting Power Jailed Incoming
Block Uncle Number Difficulty Gas Used Reward
Loading
Loading
Make sure to use the "Vote Down" button for any spammy posts, and the "Vote Up" for interesting conversations.