ETH Price: $2,066.48 (-0.06%)

Contract Diff Checker

Contract Name:
OrionVoting

Contract Source Code:

<i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (token/ERC20/IERC20.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 standard as defined in the EIP.
 */
interface IERC20 {
    /**
     * @dev Emitted when `value` tokens are moved from one account (`from`) to
     * another (`to`).
     *
     * Note that `value` may be zero.
     */
    event Transfer(address indexed from, address indexed to, uint256 value);

    /**
     * @dev Emitted when the allowance of a `spender` for an `owner` is set by
     * a call to {approve}. `value` is the new allowance.
     */
    event Approval(address indexed owner, address indexed spender, uint256 value);

    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);

    /**
     * @dev Returns the amount of tokens owned by `account`.
     */
    function balanceOf(address account) external view returns (uint256);

    /**
     * @dev Moves `amount` tokens from the caller's account to `to`.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transfer(address to, uint256 amount) external returns (bool);

    /**
     * @dev Returns the remaining number of tokens that `spender` will be
     * allowed to spend on behalf of `owner` through {transferFrom}. This is
     * zero by default.
     *
     * This value changes when {approve} or {transferFrom} are called.
     */
    function allowance(address owner, address spender) external view returns (uint256);

    /**
     * @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * IMPORTANT: Beware that changing an allowance with this method brings the risk
     * that someone may use both the old and the new allowance by unfortunate
     * transaction ordering. One possible solution to mitigate this race
     * condition is to first reduce the spender's allowance to 0 and set the
     * desired value afterwards:
     * https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
     *
     * Emits an {Approval} event.
     */
    function approve(address spender, uint256 amount) external returns (bool);

    /**
     * @dev Moves `amount` tokens from `from` to `to` using the
     * allowance mechanism. `amount` is then deducted from the caller's
     * allowance.
     *
     * Returns a boolean value indicating whether the operation succeeded.
     *
     * Emits a {Transfer} event.
     */
    function transferFrom(address from, address to, uint256 amount) external returns (bool);
}

<i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/structs/EnumerableSet.sol)
// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.

pragma solidity ^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.
 *
 * ```solidity
 * 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.
 *
 * [WARNING]
 * ====
 * Trying to delete such a structure from storage will likely result in data corruption, rendering the structure
 * unusable.
 * See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.
 *
 * In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an
 * array of EnumerableSet.
 * ====
 */
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;

            if (lastIndex != toDeleteIndex) {
                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] = valueIndex; // Replace lastValue's index to valueIndex
            }

            // 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) {
        return set._values[index];
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function _values(Set storage set) private view returns (bytes32[] memory) {
        return set._values;
    }

    // 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);
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {
        bytes32[] memory store = _values(set._inner);
        bytes32[] memory result;

        /// @solidity memory-safe-assembly
        assembly {
            result := store
        }

        return result;
    }

    // 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))));
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(AddressSet storage set) internal view returns (address[] memory) {
        bytes32[] memory store = _values(set._inner);
        address[] memory result;

        /// @solidity memory-safe-assembly
        assembly {
            result := store
        }

        return result;
    }

    // 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 in 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));
    }

    /**
     * @dev Return the entire set in an array
     *
     * WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
     * to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
     * this function has an unbounded cost, and using it as part of a state-changing function may render the function
     * uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
     */
    function values(UintSet storage set) internal view returns (uint256[] memory) {
        bytes32[] memory store = _values(set._inner);
        uint256[] memory result;

        /// @solidity memory-safe-assembly
        assembly {
            result := store
        }

        return result;
    }
}

<i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;

//import "hardhat/console.sol";

abstract contract Staking {
    uint256 internal constant RATE_PRECISION = 1e40;

    uint256 public rewardRate; //скорость наград, например 1 ORN в секунду на всех (точность 10**48)

    struct UserState {
        uint256 stake;
        uint256 rateCumulative;
        uint256 reward;
        uint256 rewardWithdraw;
    }

    uint256 public allStake; //сумма всех стейков
    mapping(address => UserState) public poolStake; //стейки по пользователям

    uint256 public rateCumulative;
    uint256 public rateTime;
    uint256 private rewardCumulativeTotal; //сумма всех наград

    event SetRewards(
        uint64 rewards,
        uint64 duration,
        uint256 rewardCumulativeTotal,
        uint256 rateCumulative,
        uint256 timestamp
    );
    event Stake(
        address indexed account,
        uint256 amount,
        uint256 rewardCumulativeTotal,
        uint256 rateCumulative,
        uint256 reward,
        uint256 timestamp
    );
    event Unstake(
        address indexed account,
        uint256 amount,
        uint256 rewardCumulativeTotal,
        uint256 rateCumulative,
        uint256 reward,
        uint256 timestamp
    );
    event ClaimReward(
        address indexed account,
        uint256 amount,
        uint256 rewardCumulativeTotal,
        uint256 rateCumulative,
        uint256 reward,
        uint256 timestamp
    );

    //  Set the overall reward
    function _setRewards(uint64 rewards, uint64 duration) internal {
        require(duration > 0, "_setRewards: zero duration");

        _writeCumulative();

        //  ORN / sec
        rewardRate = (RATE_PRECISION * rewards) / duration;

        emit SetRewards(
            rewards,
            duration,
            rewardCumulativeTotal,
            rateCumulative,
            block.timestamp
        );
    }

    //Расчет нового курса награды
    function calcNewRate() public view virtual returns (uint256) {
        uint256 Rate = 0;
        if (allStake > 0) {
            Rate = rewardRate / allStake;
        }

        return Rate * (block.timestamp - rateTime);
    }

    function _writeCumulative() internal virtual {
        uint256 newRate = calcNewRate();

        rewardCumulativeTotal += (newRate * allStake) / RATE_PRECISION;
        rateCumulative += newRate;
        rateTime = block.timestamp;
    }

    function _stake(address account, uint256 amount) internal {
        require(amount > 0, "_stake: zero stake amount");

        _writeCumulative();

        UserState memory item = poolStake[account];
        item.reward = _calcReward(item, rateCumulative);
        item.stake += amount;
        item.rateCumulative = rateCumulative;
        poolStake[account] = item;

        allStake += amount;

        emit Stake(
            account,
            amount,
            rewardCumulativeTotal,
            rateCumulative,
            item.reward,
            block.timestamp
        );
    }

    function _claimReward(address account, uint256 amount) internal {
        _writeCumulative();

        UserState memory item = poolStake[account];

        item.reward = _calcReward(item, rateCumulative);
        require(
            item.reward - item.rewardWithdraw >= amount,
            "Error claim amount"
        );
        item.rewardWithdraw += amount;
        item.rateCumulative = rateCumulative;
        poolStake[account] = item;

        emit ClaimReward(
            account,
            amount,
            rewardCumulativeTotal,
            rateCumulative,
            item.reward,
            block.timestamp
        );
    }

    function _unstake(address account, uint256 amount) internal {
        _writeCumulative();

        UserState memory item = poolStake[account];
        require(item.stake >= amount, "Error unstake amount");

        item.reward = _calcReward(item, rateCumulative);
        item.stake -= amount;
        item.rateCumulative = rateCumulative;
        poolStake[account] = item;

        allStake -= amount;

        emit Unstake(
            account,
            amount,
            rewardCumulativeTotal,
            rateCumulative,
            item.reward,
            block.timestamp
        );
    }

    function _calcReward(
        UserState memory item,
        uint256 _rateCumulative
    ) internal pure returns (uint256) {
        return
            item.reward +
            ((_rateCumulative - item.rateCumulative) * item.stake) /
            RATE_PRECISION;
    }

    function getReward(address account) public view virtual returns (uint256) {
        UserState memory item = poolStake[account];
        uint256 _rateCumulative = rateCumulative + calcNewRate();
        return _calcReward(item, _rateCumulative) - item.rewardWithdraw;
    }

    function getStake(address account) public view returns (uint256) {
        return poolStake[account].stake;
    }

    function getRewardWithdraw(
        address account
    ) external view returns (uint256) {
        return poolStake[account].rewardWithdraw;
    }

    function getRewardCumulative(
        address account
    ) external view returns (uint256) {
        return getReward(account) + poolStake[account].rewardWithdraw;
    }

    function getRewardCumulativeAll() public view returns (uint256) {
        uint256 newRate = calcNewRate();
        return rewardCumulativeTotal + (newRate * allStake) / RATE_PRECISION;
    }
}

<i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;


interface IOrionFarmV2
{
    //Action
    function create_lock_period(address pool, uint256 amount, uint256 lock_period) external;
    function increase_amount(address pool, uint256 amount) external;
    function increase_lock_period(address pool, uint256 new_lock_period) external;
    function withdraw(address pool) external;
    function claimReward(address pool) external;

    function createSmartReward(address pool) external;

    //View
    function getReward(address pool, address account) external view returns (uint256);
    function getBoost(address pool, address account) external view returns (uint256);
    function getStake(address pool, address account) external view returns (uint256);
    function allStake(address pool) external view returns (uint256);
    function lockTimeStart(address pool, address account) external view returns (uint48);
    function lockTimePeriod(address pool, address account) external view returns (uint48);

    function libStakingReward() external view returns(address);
}

<i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;

import "./IStaking.sol";

interface IOrionVoting is IStaking
{

    //admin
    function setSmart(address addr, bool bUse) external;
    function setRewards(uint64 rewards, uint64 duration) external;
    function addPool(address pool) external;
    function deletePool(address pool) external;


    //user
    function vote(address pool, uint256 amount) external;
    function voteArr(address[] calldata pools, uint256[] calldata amounts) external;
    function unvote(address pool, uint256 amount) external;
    function unvoteAll(address account) external;

    //smart
    function claimReward(address pool, address to, uint256 amount) external;

    //vew
    function countPool() external view returns (uint256);//number of pools
    function poolList(uint256) external view returns (address);//list of pools
    function poolIndex(address pool) external view returns (uint256);//whether there is a pool in the list (index numbers starting from 1)
    function users(address user) external view returns (uint256);//user votes across all pools
    function usersPool(address user,address pool) external view returns (uint256);//user votes by pool
    function smarts(address smart) external view returns (bool);//white list of trusted farm contracts

    function veORN() external view returns (address);
    function ORN() external view returns (address);

    function havePool(address account) external view returns (bool);



}

<i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;


interface IStaking
{
    //staking
    function getReward(address account) external view returns (uint256);
    function getStake(address account) external view returns (uint256);
    function allStake() external view returns (uint256);
    function rewardRate() external view returns (uint256);
    function rateCumulative() external view returns (uint256);
    function rateTime() external view returns (uint256);


    function getRewardWithdraw(address account) external view returns (uint256);
    function getRewardCumulative(address account) external view returns (uint256);
    function getRewardCumulativeAll() external view returns (uint256);

}

<i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;

interface ITWBalance
{
    struct TWItem
    {
        // the block timestamp
        uint48  timestamp;        
        // the amount accumulator, i.e. amount * time elapsed
        uint208 amountTW;
    }

    /// @notice Returns the time weight (TW) amount of tokens in existence.
    function totalSupplyTW() external view returns (TWItem memory);

    /// @notice Calculates the average aamount of tokens in existence from the specified TW period
    function totalSupplyAvg(TWItem memory itemStart) view external returns (uint256);

    /// @notice Returns the time weight (TW) balance of a token
    /// @param user The account for which to look up the number of tokens it has, i.e. its balance
    /// @return The number of tokens held by the account
    function balanceOfTW(address user) external view returns (TWItem memory);
    
    /// @notice Calculates the average address balance from the specified TW period
    function balanceOfAvg(address user, TWItem memory itemStart) view external returns (uint256);

}

<i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;

import "./ITWBalance.sol";
import "./IStaking.sol";

interface IveORN is ITWBalance,IStaking
{
    struct UserInfo {
        uint48 time_lock;
        uint128 balance;
        uint128 amount_token;
    }
    /**
     * @dev Returns the amount of tokens in existence.
     */
    function totalSupply() external view returns (uint256);
    function totalSupply(uint256 ts) external view returns (uint256);
    function totalSupply0() external view returns (uint256);//balance on start timestamp

    /// @notice Returns the balance of a token
    /// @param account The account for which to look up the number of tokens it has, i.e. its balance
    /// @return The number of tokens held by the account
    function balanceOf(address account) external view returns (uint256);
    function balanceOf(address account, uint256 ts) external view returns (uint256);
    function balanceOf0(address account) external view returns (uint256);//balance on start timestamp

    function balanceTokenOf(address account) external view  returns (uint256);

    /// @notice Returns the number of decimals used to get its user representation.
    function decimals() external view returns (uint8);
    
    function name() pure external returns(string memory);
    function symbol() pure external returns(string memory);
 

    function ORN() external view returns (address);

    function lockTime(address account) external view returns (uint48);

    
    //staking ORN
    function create_lock(uint256 _value, uint256 _unlock_time) external;
    //function deposit_for(address _addr, uint256 _value) external;
    function increase_amount(uint256 _value) external;
    function increase_unlock_time(uint256 _unlock_time) external;
    function increase_unlock_period(uint256 unlock_period) external;
    function create_lock_period(uint256 _value, uint256 unlock_period) external;

    function withdraw() external;
    function claimReward() external;

    function tokenMap(address user) external returns(UserInfo memory);

}

<i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>

// SPDX-License-Identifier: GPL-2.0-or-later
pragma solidity ^0.8.7;

import '@openzeppelin/contracts/token/ERC20/IERC20.sol';

library TransferHelper {
    /// @notice Transfers tokens from the targeted address to the given destination
    /// @notice Errors with 'STF' if transfer fails
    /// @param token The contract address of the token to be transferred
    /// @param from The originating address from which the tokens will be transferred
    /// @param to The destination address of the transfer
    /// @param value The amount to be transferred
    function safeTransferFrom(
        address token,
        address from,
        address to,
        uint256 value
    ) internal {
        (bool success, bytes memory data) =
            token.call(abi.encodeWithSelector(IERC20.transferFrom.selector, from, to, value));
        require(success && (data.length == 0 || abi.decode(data, (bool))), 'STF');
    }

    /// @notice Transfers tokens from msg.sender to a recipient
    /// @dev Errors with ST if transfer fails
    /// @param token The contract address of the token which will be transferred
    /// @param to The recipient of the transfer
    /// @param value The value of the transfer
    function safeTransfer(
        address token,
        address to,
        uint256 value
    ) internal {
        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.transfer.selector, to, value));
        require(success && (data.length == 0 || abi.decode(data, (bool))), 'ST');
    }

    /// @notice Approves the stipulated contract to spend the given allowance in the given token
    /// @dev Errors with 'SA' if transfer fails
    /// @param token The contract address of the token to be approved
    /// @param to The target of the approval
    /// @param value The amount of the given token the target will be allowed to spend
    function safeApprove(
        address token,
        address to,
        uint256 value
    ) internal {
        (bool success, bytes memory data) = token.call(abi.encodeWithSelector(IERC20.approve.selector, to, value));
        require(success && (data.length == 0 || abi.decode(data, (bool))), 'SA');
    }

    /// @notice Transfers ETH to the recipient address
    /// @dev Fails with `STE`
    /// @param to The destination of the transfer
    /// @param value The value to be transferred
    function safeTransferETH(address to, uint256 value) internal {
        (bool success, ) = to.call{value: value}(new bytes(0));
        require(success, 'STE');
    }
}

<i class='far fa-question-circle text-muted ms-2' data-bs-trigger='hover' data-bs-toggle='tooltip' data-bs-html='true' data-bs-title='Click on the check box to select individual contract to compare. Only 1 contract can be selected from each side.'></i>

// SPDX-License-Identifier: MIT
pragma solidity ^0.8.7;

import "./base/Staking.sol";
import "./libraries/TransferHelper.sol";
import "./interfaces/IveORN.sol";
import "./interfaces/IOrionVoting.sol";
import "./interfaces/IOrionFarmV2.sol";

import "@openzeppelin/contracts/utils/structs/EnumerableSet.sol";
uint256 constant MAX_PERCENT = 10000;


contract OrionVoting is Staking {
    using EnumerableSet for EnumerableSet.Bytes32Set;

    struct Proposal {
        bytes32 name;
        EnumerableSet.Bytes32Set choices;
        uint256 timestampFinish;
    }

    uint256 public countPool; //number of pools
    mapping(uint256 => address) public poolList; //list of pools
    mapping(address => uint256) public poolIndex; //whether there is a pool in the list (index numbers starting from 1)

    mapping(address => uint256) public users; //user votes across all pools
    mapping(address => mapping(address => uint256)) public usersPool; //user votes by pool

    mapping(address => bool) public smarts; //white list of trusted farm contracts

    address public immutable veORN;
    address public immutable ORN;
    address public immutable smartOwner;

    mapping(bytes32 => Proposal) private proposals;
    mapping(bytes32 => uint256) public proposalVotes;
    mapping(bytes32 => mapping(address => uint256)) public voted;
    mapping(address => mapping(bytes32 => bytes32)) public userVotedChoice;

    modifier onlyOwner() {
        require(msg.sender == smartOwner, "Caller is not the owner");
        _;
    }

    event UsePool(address indexed pool, bool bUse);
    event Vote(address indexed pool, address indexed account, uint256 amount);
    event Unvote(address indexed pool, address indexed account, uint256 amount);
    event UnvoteAll(address indexed account);
    event ProposalCreated(
        bytes32 name,
        uint256 timestampFinish,
        bytes32[] choices
    );
    event ProposalVoted(
        address user,
        bytes32 name,
        bytes32 choice,
        uint256 votePower
    );
    event ProposalUnvoted(
        address user,
        bytes32 name,
        bytes32 choice,
        uint256 votePower
    );

    error MAX_PROPOSALS_EXCEED();
    error PROPOSAL_NOT_EXIST();
    error ALREADY_VOTED();
    error EMPTY_NAME();
    error EMPTY_CHOICES();
    error PROPOSAL_FINISHED();
    error CHOICE_NOT_EXIST();
    error DUPLICATED_CHOICES();
    error PROPOSAL_ALREADY_EXIST();
    error LOCK_WILL_EXPIRE();
    error ZERO_PREVIOUS_VOTE();
    error CANT_CHANGE_CHOICE();

    constructor(address veORN_, address owner) {
        veORN = veORN_;
        ORN = IveORN(veORN).ORN();
        smartOwner = owner;
    }

    //admin caller

    function setSmart(address addr, bool bUse) external onlyOwner {
        smarts[addr] = bUse;
    }

    function setRewards(uint64 rewards, uint64 duration) external onlyOwner {
        _setRewards(rewards, duration);
    }

    function addPool(address pool) public onlyOwner {
        countPool++;
        poolIndex[pool] = countPool;
        poolList[countPool] = pool;

        emit UsePool(pool, true);
    }

    function deletePool(address pool) external onlyOwner {
        uint256 index = poolIndex[pool];
        require(index > 0, "Pool not found");
        delete poolIndex[pool];

        //we move the last element to the place of the deleted one and delete the last element
        poolList[index] = poolList[countPool];
        poolIndex[poolList[countPool]] = index;
        delete poolList[countPool];
        countPool--;

        emit UsePool(pool, false);
    }

    //smart caller

    function claimReward(address pool, address to, uint256 amount) external {
        require(
            smarts[msg.sender],
            "claimReward: caller not found in white list"
        );

        _claimReward(pool, amount);

        TransferHelper.safeTransfer(ORN, to, amount);
    }

    //user caller
    function votePercent(address pool, uint256 percent) external {
        require(percent <= MAX_PERCENT, "Error percent");
        uint256 balanceVeORN = IveORN(veORN).balanceOf0(msg.sender);
        vote(pool, (balanceVeORN * percent) / MAX_PERCENT);
    }

    function vote(address pool, uint256 amount) public {
        require(poolIndex[pool] > 0, "Pool not found");

        //check balance
        uint256 balanceVeORN = IveORN(veORN).balanceOf0(msg.sender);
        uint256 balanceVotes = users[msg.sender];
        //require(balanceVeORN >= balanceVotes+amount,"Error user veORN balance");// and revert if overflow
        uint256 balanceRemained;
        if (balanceVeORN > balanceVotes)
            balanceRemained = balanceVeORN - balanceVotes;
        if (amount > balanceRemained) amount = balanceRemained;

        users[msg.sender] += amount;
        usersPool[msg.sender][pool] += amount;

        _stake(pool, amount);

        emit Vote(pool, msg.sender, amount);
    }

    function unvotePercent(address pool, uint256 percent) external {
        require(percent <= MAX_PERCENT, "Error percent");
        uint256 balanceVeORN = IveORN(veORN).balanceOf0(msg.sender);
        unvote(pool, (balanceVeORN * percent) / MAX_PERCENT);
    }

    function unvote(address pool, uint256 amount) public {
        if (usersPool[msg.sender][pool] > amount) {
            usersPool[msg.sender][pool] -= amount;
        } else {
            amount = usersPool[msg.sender][pool];
            delete usersPool[msg.sender][pool];
        }
        if (users[msg.sender] > amount) {
            users[msg.sender] -= amount;
        } else {
            amount = users[msg.sender];
            delete users[msg.sender];
        }

        _unstake(pool, amount);

        emit Unvote(pool, msg.sender, amount);
    }

    //array call support
    function voteArr(
        address[] calldata pools,
        uint256[] calldata amounts
    ) external {
        require(pools.length == amounts.length, "Pool not found");

        for (uint256 i = 0; i < pools.length; i++) vote(pools[i], amounts[i]);
    }

    //user or smart caller

    function unvoteAll(address account) external {
        require(
            msg.sender == veORN || msg.sender == account,
            "unvoteAll: caller is not the veORN contract"
        );

        uint256 balanceVotes = users[account];
        if (balanceVotes > 0) {
            uint256 _countPool = countPool;
            for (uint256 i = 1; i <= _countPool; i++) {
                address pool = poolList[i];
                uint256 amount = usersPool[account][pool];

                if (amount > 0) {
                    usersPool[account][pool] = 0;
                    _unstake(pool, amount);

                    balanceVotes -= amount;
                    if (balanceVotes == 0) break;
                }
            }
            users[account] = 0;

            emit UnvoteAll(account);
        }
    }

    function addPool2(address pool, address farmv2) external {
        //добавление пула и создание смарт-контракта наград для пулов v2
        addPool(pool); //check owner
        IOrionFarmV2(farmv2).createSmartReward(pool);
    }

    function createProposal(
        bytes32 name,
        bytes32[] memory choices,
        uint256 timestampFinish
    ) external onlyOwner {
        if (name == 0x0) revert EMPTY_NAME();
        if (choices.length > 10) revert MAX_PROPOSALS_EXCEED();
        if (choices.length == 0) revert EMPTY_CHOICES();
        if (timestampFinish <= block.timestamp) revert PROPOSAL_FINISHED();

        Proposal storage proposal = proposals[name];
        if (proposal.name != 0x0) revert PROPOSAL_ALREADY_EXIST();

        proposal.name = name;
        proposal.timestampFinish = timestampFinish;

        for (uint i = 0; i < choices.length; ++i) {
            bytes32 choice = choices[i];
            if (choice == 0x0) revert EMPTY_NAME();
            if (!proposal.choices.add(choice)) revert DUPLICATED_CHOICES();
        }

        emit ProposalCreated(name, timestampFinish, choices);
    }

    function voteProposal(bytes32 name, bytes32 choice) external {
        Proposal storage proposal = proposals[name];

        if (proposal.name == 0x0) revert PROPOSAL_NOT_EXIST();

        if (proposal.timestampFinish <= block.timestamp)
            revert PROPOSAL_FINISHED();

        if (!proposal.choices.contains(choice)) revert CHOICE_NOT_EXIST();

        uint256 lockFinish = IveORN(veORN).lockTime(msg.sender);
        if (lockFinish < proposal.timestampFinish)
            revert LOCK_WILL_EXPIRE();

        bytes32 currentChoice = userVotedChoice[msg.sender][name];
        if (currentChoice != bytes32(0) && currentChoice != choice) revert CANT_CHANGE_CHOICE();

        uint256 votePower = IveORN(veORN).balanceOf0(msg.sender); // votePower != 0 due to userInfo.time_lock != 0
        uint256 votedAmount = voted[name][msg.sender];

        if (votePower <= votedAmount) revert ALREADY_VOTED();

        bytes32 id = keccak256(abi.encode(name, choice));
        proposalVotes[id] += votePower - votedAmount;
        voted[name][msg.sender] = votePower;
        userVotedChoice[msg.sender][name] = choice;

        emit ProposalVoted(msg.sender, name, choice, votePower);
    }

    function changeVoteProposal(
        bytes32 name,
        bytes32 previousChoice,
        bytes32 newChoice
    ) external {
        Proposal storage proposal = proposals[name];

        if (proposal.name == 0x0) revert PROPOSAL_NOT_EXIST();

        if (proposal.timestampFinish <= block.timestamp)
            revert PROPOSAL_FINISHED();

        if (!proposal.choices.contains(previousChoice)) revert CHOICE_NOT_EXIST();
        if (!proposal.choices.contains(newChoice)) revert CHOICE_NOT_EXIST();

        uint256 votedAmount = voted[name][msg.sender];
        if (votedAmount == 0) revert ZERO_PREVIOUS_VOTE();

        uint256 votePower = IveORN(veORN).balanceOf0(msg.sender); // votePower >= votedAmount

        bytes32 previousId = keccak256(abi.encode(name, previousChoice));
        proposalVotes[previousId] -= votedAmount;

        bytes32 newId = keccak256(abi.encode(name, newChoice));
        proposalVotes[newId] += votePower;

        voted[name][msg.sender] = votePower;
        userVotedChoice[msg.sender][name] = newChoice;

        emit ProposalUnvoted(msg.sender, name, previousChoice, votedAmount);
        emit ProposalVoted(msg.sender, name, newChoice, votePower);
    }

    function proposalInfo(
        bytes32 name
    )
        external
        view
        returns (bytes32, uint256, bytes32[] memory, uint256[] memory)
    {
        Proposal storage proposal = proposals[name];
        uint256 choicesLength = proposal.choices.length();
        uint256[] memory votes = new uint256[](choicesLength);

        for (uint i = 0; i < choicesLength; ++i) {
            bytes32 id = keccak256(abi.encode(name, proposal.choices.at(i)));
            votes[i] = proposalVotes[id];
        }

        return (
            name,
            proposal.timestampFinish,
            proposal.choices.values(),
            votes
        );
    }

    //view
    function havePool(address account) external view returns (bool) {
        return poolIndex[account] > 0;
    }
}

Please enter a contract address above to load the contract details and source code.

Context size (optional):