ETH Price: $3,202.11 (-0.31%)

Contract

0xF55684BC536487394B423e70567413faB8e45E26
 

Overview

ETH Balance

0 ETH

Eth Value

$0.00

More Info

Private Name Tags

Multichain Info

No addresses found
Transaction Hash
Method
Block
From
To
Promote237336552025-11-05 14:20:479 days ago1762352447IN
1inch: Whitelist v2
0 ETH0.000148593.22487554
Promote237262182025-11-04 13:20:4710 days ago1762262447IN
1inch: Whitelist v2
0 ETH0.000134242.91332288
Promote236740692025-10-28 6:14:2317 days ago1761632063IN
1inch: Whitelist v2
0 ETH0.000032481.121
Promote236256502025-10-21 11:29:4724 days ago1761046187IN
1inch: Whitelist v2
0 ETH0.000046541.60610243
Promote236028792025-10-18 6:54:5927 days ago1760770499IN
1inch: Whitelist v2
0 ETH0.000046491.60457752
Promote235960442025-10-17 7:59:3528 days ago1760687975IN
1inch: Whitelist v2
0 ETH0.000138954.797
Promote235949572025-10-17 4:20:2328 days ago1760674823IN
1inch: Whitelist v2
0 ETH0.000034891.204
Promote235914212025-10-16 16:30:1129 days ago1760632211IN
1inch: Whitelist v2
0 ETH0.000140574.85096883
Promote235912352025-10-16 15:52:4729 days ago1760629967IN
1inch: Whitelist v2
0 ETH0.000099643.4384634
Promote235859602025-10-15 22:05:5929 days ago1760565959IN
1inch: Whitelist v2
0 ETH0.000049031.69206218
Register235587072025-10-12 2:37:5933 days ago1760236679IN
1inch: Whitelist v2
0 ETH0.000239391.68001426
Promote235582432025-10-12 1:05:1133 days ago1760231111IN
1inch: Whitelist v2
0 ETH0.000051091.76333053
Register234838472025-10-01 15:28:5944 days ago1759332539IN
1inch: Whitelist v2
0 ETH0.000455173.32221114
Register234693012025-09-29 14:39:3546 days ago1759156775IN
1inch: Whitelist v2
0 ETH0.0014279411.89125504
Register234515472025-09-27 3:05:2348 days ago1758942323IN
1inch: Whitelist v2
0 ETH0.000147981.1251633
Promote234458502025-09-26 7:57:5949 days ago1758873479IN
1inch: Whitelist v2
0 ETH0.000048371.67
Clean234457952025-09-26 7:46:4749 days ago1758872807IN
1inch: Whitelist v2
0 ETH0.000072440.53688406
Promote233877772025-09-18 5:08:4757 days ago1758172127IN
1inch: Whitelist v2
0 ETH0.000012470.4305
Promote233816692025-09-17 8:40:5958 days ago1758098459IN
1inch: Whitelist v2
0 ETH0.000025470.8795
Promote233388122025-09-11 9:05:4764 days ago1757581547IN
1inch: Whitelist v2
0 ETH0.000024090.8316
Register233337162025-09-10 15:57:4765 days ago1757519867IN
1inch: Whitelist v2
0 ETH0.000405512.74039885
Register233260292025-09-09 14:06:3566 days ago1757426795IN
1inch: Whitelist v2
0 ETH0.000405872.96235949
Promote233246372025-09-09 9:27:3566 days ago1757410055IN
1inch: Whitelist v2
0 ETH0.000020580.7107
Register233233942025-09-09 5:17:4766 days ago1757395067IN
1inch: Whitelist v2
0 ETH0.000042290.32153527
Promote233227472025-09-09 3:08:1166 days ago1757387291IN
1inch: Whitelist v2
0 ETH0.000020710.4496
View all transactions

View more zero value Internal Transactions in Advanced View mode

Advanced mode:
Loading...
Loading
Cross-Chain Transactions

Block Transaction Difficulty Gas Used Reward
View All Blocks Produced

Validator Index Block Amount
View All Withdrawals

Transaction Hash Block Value Eth2 PubKey Valid
View All Deposits
Loading...
Loading

Contract Source Code Verified (Exact Match)

Contract Name:
WhitelistRegistry

Compiler Version
v0.8.19+commit.7dd6d404

Optimization Enabled:
Yes with 1000000 runs

Other Settings:
default evmVersion
// SPDX-License-Identifier: MIT

pragma solidity 0.8.19;

import "@1inch/solidity-utils/contracts/libraries/UniERC20.sol";
import "@1inch/solidity-utils/contracts/libraries/AddressSet.sol";
import "@1inch/st1inch/contracts/interfaces/IVotable.sol";
import "@openzeppelin/contracts/access/Ownable.sol";

/**
 * @title WhitelistRegistry
 * @notice The contract manages a whitelist for trading resolvers, providing functions to register,
 * promote and remove addresses, as well as setting various thresholds and limits. It also includes an
 * emergency rescue function for tokens sent to the contract accidentally.
 */
contract WhitelistRegistry is Ownable {
    using UniERC20 for IERC20;
    using AddressSet for AddressSet.Data;
    using AddressArray for AddressArray.Data;

    error BalanceLessThanThreshold();
    error AlreadyRegistered();
    error NotWhitelisted();
    error SamePromotee();

    /// @notice Emitted after a new resolver is registered.
    event Registered(address addr);
    /// @notice Emitted when a resolver is pushed out of whitelist.
    event Unregistered(address addr);
    /// @notice Emitted when the new minimum total supply percentage to get into the whitelist is set.
    event ResolverPercentageThresholdSet(uint256 resolverPercentageThreshold);
    /// @notice Emitted when a new worker for a resolver is set.
    event Promotion(address promoter, uint256 chainId, address promotee);

    uint256 public constant BASIS_POINTS = 10000;
    IVotable public immutable token;

    mapping(address => mapping(uint256 => address)) public promotions;
    // 100% = 10000, 10% = 1000, 1% = 100
    uint256 public resolverPercentageThreshold;

    AddressSet.Data private _whitelist;

    constructor(
        IVotable token_,
        uint256 resolverPercentageThreshold_
    ) {
        token = token_;
        _setResolverPercentageThreshold(resolverPercentageThreshold_);
    }

    /**
     * @notice Allows the contract owner to recover any tokens accidentally sent to the contract.
     * @param token_ The token to recover.
     * @param amount The amount of tokens to recover.
     */
    function rescueFunds(IERC20 token_, uint256 amount) external onlyOwner {
        token_.uniTransfer(payable(msg.sender), amount);
    }

    /**
     * @notice Allows the contract owner to set a new resolver threshold.
     * The resolver threshold is the minimum total supply percentage required to get into the whitelist.
     * @param resolverPercentageThreshold_ The new resolver threshold.
     */
    function setResolverPercentageThreshold(uint256 resolverPercentageThreshold_) external onlyOwner {
        _setResolverPercentageThreshold(resolverPercentageThreshold_);
    }


    /**
     * @notice Attempts to register the caller in the whitelist.
     * @dev Reverts if the caller's total supply percentage is below the resolver threshold.
     */
    function register() external {
        uint256 percentageThreshold = resolverPercentageThreshold;
        uint256 totalSupply = token.totalSupply();
        if (!_isValidBalance(percentageThreshold, token.balanceOf(msg.sender), totalSupply)) revert BalanceLessThanThreshold();
        if (!_whitelist.add(msg.sender)) revert AlreadyRegistered();
        emit Registered(msg.sender);
        _clean(percentageThreshold, totalSupply);
    }

    /**
     * @notice Registers a worker for the resolver to settle orders.
     * @param chainId The chain ID where the worker will assigned.
     * @param promotee The worker's address.
     */
    function promote(uint256 chainId, address promotee) external {
        if (promotions[msg.sender][chainId] == promotee) revert SamePromotee();
        promotions[msg.sender][chainId] = promotee;
        emit Promotion(msg.sender, chainId, promotee);
    }

    /**
     * @notice Cleans the whitelist by removing addresses that fall below the resolver threshold.
     */
    function clean() external {
        _clean(resolverPercentageThreshold, token.totalSupply());
    }

    /**
     * @notice Returns the addresses in the whitelist.
     * @return whitelist A list of whitelisted addresses.
     */
    function getWhitelist() external view returns (address[] memory /* whitelist */) {
        return _whitelist.items.get();
    }

    /**
     * @notice Returns the worker list for a particular chain ID.
     * @param chainId The chain ID to get the promoted addresses for.
     * @return promotees A list of worker addresses.
     */
    function getPromotees(uint256 chainId) external view returns (address[] memory promotees) {
        promotees = _whitelist.items.get();
        unchecked {
            uint256 len = promotees.length;
            for (uint256 i = 0; i < len; ++i) {
                promotees[i] = promotions[promotees[i]][chainId];
            }
        }
    }

    function _setResolverPercentageThreshold(uint256 resolverPercentageThreshold_) private {
        resolverPercentageThreshold = resolverPercentageThreshold_;
        emit ResolverPercentageThresholdSet(resolverPercentageThreshold_);
    }

    function _removeFromWhitelist(address account) private {
        _whitelist.remove(account);
        emit Unregistered(account);
    }

    function _isValidBalance(uint256 percentageThreshold, uint256 balance, uint256 totalSupply) private pure returns (bool) {
        return (
            balance > 0 &&
            balance * BASIS_POINTS >= totalSupply * percentageThreshold)
        ;
    }

    function _clean(uint256 percentageThreshold, uint256 totalSupply) private {
        uint256 whitelistLength = _whitelist.length();
        unchecked {
            for (uint256 i = 0; i < whitelistLength; ) {
                address curWhitelisted = _whitelist.at(i);
                uint256 balance = token.balanceOf(curWhitelisted);
                if (!_isValidBalance(percentageThreshold, balance, totalSupply)) {
                    _removeFromWhitelist(curWhitelisted);
                    whitelistLength--;
                } else {
                    i++;
                }
            }
        }
    }
}

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

pragma solidity ^0.8.0;

interface IDaiLikePermit {
    function permit(
        address holder,
        address spender,
        uint256 nonce,
        uint256 expiry,
        bool allowed,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;
}

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

interface IERC20MetadataUppercase {
    function NAME() external view returns (string memory); // solhint-disable-line func-name-mixedcase

    function SYMBOL() external view returns (string memory); // solhint-disable-line func-name-mixedcase
}

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

interface IPermit2 {
    struct PermitDetails {
        // ERC20 token address
        address token;
        // the maximum amount allowed to spend
        uint160 amount;
        // timestamp at which a spender's token allowances become invalid
        uint48 expiration;
        // an incrementing value indexed per owner,token,and spender for each signature
        uint48 nonce;
    }
    /// @notice The permit message signed for a single token allownce
    struct PermitSingle {
        // the permit data for a single token alownce
        PermitDetails details;
        // address permissioned on the allowed tokens
        address spender;
        // deadline on the permit signature
        uint256 sigDeadline;
    }
    /// @notice Packed allowance
    struct PackedAllowance {
        // amount allowed
        uint160 amount;
        // permission expiry
        uint48 expiration;
        // an incrementing value indexed per owner,token,and spender for each signature
        uint48 nonce;
    }

    function transferFrom(address user, address spender, uint160 amount, address token) external;

    function permit(address owner, PermitSingle memory permitSingle, bytes calldata signature) external;

    function allowance(address user, address token, address spender) external view returns (PackedAllowance memory);
}

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

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

interface IWETH is IERC20 {
    function deposit() external payable;

    function withdraw(uint256 amount) external;
}

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/// @title Library that implements address array on mapping, stores array length at 0 index.
library AddressArray {
    error IndexOutOfBounds();
    error PopFromEmptyArray();
    error OutputArrayTooSmall();

    /// @dev Data struct containing raw mapping.
    struct Data {
        mapping(uint256 => uint256) _raw;
    }

    /// @dev Length of array.
    function length(Data storage self) internal view returns (uint256) {
        return self._raw[0] >> 160;
    }

    /// @dev Returns data item from `self` storage at `i`.
    function at(Data storage self, uint256 i) internal view returns (address) {
        return address(uint160(self._raw[i]));
    }

    /// @dev Returns list of addresses from storage `self`.
    function get(Data storage self) internal view returns (address[] memory arr) {
        uint256 lengthAndFirst = self._raw[0];
        arr = new address[](lengthAndFirst >> 160);
        _get(self, arr, lengthAndFirst);
    }

    /// @dev Puts list of addresses from `self` storage into `output` array.
    function get(Data storage self, address[] memory output) internal view returns (address[] memory) {
        return _get(self, output, self._raw[0]);
    }

    function _get(
        Data storage self,
        address[] memory output,
        uint256 lengthAndFirst
    ) private view returns (address[] memory) {
        uint256 len = lengthAndFirst >> 160;
        if (len > output.length) revert OutputArrayTooSmall();
        if (len > 0) {
            output[0] = address(uint160(lengthAndFirst));
            unchecked {
                for (uint256 i = 1; i < len; i++) {
                    output[i] = address(uint160(self._raw[i]));
                }
            }
        }
        return output;
    }

    /// @dev Array push back `account` operation on storage `self`.
    function push(Data storage self, address account) internal returns (uint256) {
        unchecked {
            uint256 lengthAndFirst = self._raw[0];
            uint256 len = lengthAndFirst >> 160;
            if (len == 0) {
                self._raw[0] = (1 << 160) + uint160(account);
            } else {
                self._raw[0] = lengthAndFirst + (1 << 160);
                self._raw[len] = uint160(account);
            }
            return len + 1;
        }
    }

    /// @dev Array pop back operation for storage `self`.
    function pop(Data storage self) internal {
        unchecked {
            uint256 lengthAndFirst = self._raw[0];
            uint256 len = lengthAndFirst >> 160;
            if (len == 0) revert PopFromEmptyArray();
            self._raw[len - 1] = 0;
            if (len > 1) {
                self._raw[0] = lengthAndFirst - (1 << 160);
            }
        }
    }

    /// @dev Set element for storage `self` at `index` to `account`.
    function set(
        Data storage self,
        uint256 index,
        address account
    ) internal {
        uint256 len = length(self);
        if (index >= len) revert IndexOutOfBounds();

        if (index == 0) {
            self._raw[0] = (len << 160) | uint160(account);
        } else {
            self._raw[index] = uint160(account);
        }
    }
}

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "./AddressArray.sol";

/** @title Library that is using AddressArray library for AddressArray.Data
 * and allows Set operations on address storage data:
 * 1. add
 * 2. remove
 * 3. contains
 */
library AddressSet {
    using AddressArray for AddressArray.Data;

    /** @dev Data struct from AddressArray.Data items
     * and lookup mapping address => index in data array.
     */
    struct Data {
        AddressArray.Data items;
        mapping(address => uint256) lookup;
    }

    /// @dev Length of data storage.
    function length(Data storage s) internal view returns (uint256) {
        return s.items.length();
    }

    /// @dev Returns data item from `s` storage at `index`.
    function at(Data storage s, uint256 index) internal view returns (address) {
        return s.items.at(index);
    }

    /// @dev Returns true if storage `s` has `item`.
    function contains(Data storage s, address item) internal view returns (bool) {
        return s.lookup[item] != 0;
    }

    /// @dev Adds `item` into storage `s` and returns true if successful.
    function add(Data storage s, address item) internal returns (bool) {
        if (s.lookup[item] > 0) {
            return false;
        }
        s.lookup[item] = s.items.push(item);
        return true;
    }

    /// @dev Removes `item` from storage `s` and returns true if successful.
    function remove(Data storage s, address item) internal returns (bool) {
        uint256 index = s.lookup[item];
        if (index == 0) {
            return false;
        }
        if (index < s.items.length()) {
            unchecked {
                address lastItem = s.items.at(s.items.length() - 1);
                s.items.set(index - 1, lastItem);
                s.lookup[lastItem] = index;
            }
        }
        s.items.pop();
        delete s.lookup[item];
        return true;
    }
}

File 8 of 17 : RevertReasonForwarder.sol
// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/// @title Revert reason forwarder.
library RevertReasonForwarder {
    /// @dev Forwards latest externall call revert.
    function reRevert() internal pure {
        // bubble up revert reason from latest external call
        assembly ("memory-safe") { // solhint-disable-line no-inline-assembly
            let ptr := mload(0x40)
            returndatacopy(ptr, 0, returndatasize())
            revert(ptr, returndatasize())
        }
    }
}

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/draft-IERC20Permit.sol";
import "../interfaces/IDaiLikePermit.sol";
import "../interfaces/IPermit2.sol";
import "../interfaces/IWETH.sol";
import "../libraries/RevertReasonForwarder.sol";

/// @title Implements efficient safe methods for ERC20 interface.
library SafeERC20 {
    error SafeTransferFailed();
    error SafeTransferFromFailed();
    error ForceApproveFailed();
    error SafeIncreaseAllowanceFailed();
    error SafeDecreaseAllowanceFailed();
    error SafePermitBadLength();
    error Permit2TransferAmountTooHigh();

    address private constant _PERMIT2 = 0x000000000022D473030F116dDEE9F6B43aC78BA3;
    bytes4 private constant _PERMIT_LENGHT_ERROR = 0x68275857;  // SafePermitBadLength.selector

    /// @dev Ensures method do not revert or return boolean `true`, admits call to non-smart-contract.
    function safeTransferFromUniversal(
        IERC20 token,
        address from,
        address to,
        uint256 amount,
        bool permit2
    ) internal {
        if (permit2) {
            if (amount > type(uint160).max) revert Permit2TransferAmountTooHigh();
            safeTransferFromPermit2(token, from, to, uint160(amount));
        } else {
            safeTransferFrom(token, from, to, amount);
        }
    }

    /// @dev Ensures method do not revert or return boolean `true`, admits call to non-smart-contract.
    function safeTransferFrom(
        IERC20 token,
        address from,
        address to,
        uint256 amount
    ) internal {
        bytes4 selector = token.transferFrom.selector;
        bool success;
        assembly ("memory-safe") { // solhint-disable-line no-inline-assembly
            let data := mload(0x40)

            mstore(data, selector)
            mstore(add(data, 0x04), from)
            mstore(add(data, 0x24), to)
            mstore(add(data, 0x44), amount)
            success := call(gas(), token, 0, data, 100, 0x0, 0x20)
            if success {
                switch returndatasize()
                case 0 {
                    success := gt(extcodesize(token), 0)
                }
                default {
                    success := and(gt(returndatasize(), 31), eq(mload(0), 1))
                }
            }
        }
        if (!success) revert SafeTransferFromFailed();
    }

    /// @dev Permit2 version of safeTransferFrom above.
    function safeTransferFromPermit2(
        IERC20 token,
        address from,
        address to,
        uint160 amount
    ) internal {
        bytes4 selector = IPermit2.transferFrom.selector;
        bool success;
        assembly ("memory-safe") { // solhint-disable-line no-inline-assembly
            let data := mload(0x40)

            mstore(data, selector)
            mstore(add(data, 0x04), from)
            mstore(add(data, 0x24), to)
            mstore(add(data, 0x44), amount)
            mstore(add(data, 0x64), token)
            success := call(gas(), _PERMIT2, 0, data, 0x84, 0x0, 0x0)
            if success {
                success := gt(extcodesize(_PERMIT2), 0)
            }
        }
        if (!success) revert SafeTransferFromFailed();
    }

    /// @dev Ensures method do not revert or return boolean `true`, admits call to non-smart-contract.
    function safeTransfer(
        IERC20 token,
        address to,
        uint256 value
    ) internal {
        if (!_makeCall(token, token.transfer.selector, to, value)) {
            revert SafeTransferFailed();
        }
    }

    /// @dev If `approve(from, to, amount)` fails, try to `approve(from, to, 0)` before retry.
    function forceApprove(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        if (!_makeCall(token, token.approve.selector, spender, value)) {
            if (
                !_makeCall(token, token.approve.selector, spender, 0) ||
                !_makeCall(token, token.approve.selector, spender, value)
            ) {
                revert ForceApproveFailed();
            }
        }
    }

    /// @dev Allowance increase with safe math check.
    function safeIncreaseAllowance(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        uint256 allowance = token.allowance(address(this), spender);
        if (value > type(uint256).max - allowance) revert SafeIncreaseAllowanceFailed();
        forceApprove(token, spender, allowance + value);
    }

    /// @dev Allowance decrease with safe math check.
    function safeDecreaseAllowance(
        IERC20 token,
        address spender,
        uint256 value
    ) internal {
        uint256 allowance = token.allowance(address(this), spender);
        if (value > allowance) revert SafeDecreaseAllowanceFailed();
        forceApprove(token, spender, allowance - value);
    }

    function safePermit(IERC20 token, bytes calldata permit) internal {
        if (!tryPermit(token, msg.sender, address(this), permit)) RevertReasonForwarder.reRevert();
    }

    function safePermit(IERC20 token, address owner, address spender, bytes calldata permit) internal {
        if (!tryPermit(token, owner, spender, permit)) RevertReasonForwarder.reRevert();
    }

    function tryPermit(IERC20 token, bytes calldata permit) internal returns(bool success) {
        return tryPermit(token, msg.sender, address(this), permit);
    }

    function tryPermit(IERC20 token, address owner, address spender, bytes calldata permit) internal returns(bool success) {
        bytes4 permitSelector = IERC20Permit.permit.selector;
        bytes4 daiPermitSelector = IDaiLikePermit.permit.selector;
        bytes4 permit2Selector = IPermit2.permit.selector;
        assembly ("memory-safe") { // solhint-disable-line no-inline-assembly
            let ptr := mload(0x40)
            switch permit.length
            case 100 {
                mstore(ptr, permitSelector)
                mstore(add(ptr, 0x04), owner)
                mstore(add(ptr, 0x24), spender)

                // Compact IERC20Permit.permit(uint256 value, uint32 deadline, uint256 r, uint256 vs)
                {  // stack too deep
                    let deadline := shr(224, calldataload(add(permit.offset, 0x20)))
                    let vs := calldataload(add(permit.offset, 0x44))

                    calldatacopy(add(ptr, 0x44), permit.offset, 0x20) // value
                    mstore(add(ptr, 0x64), sub(deadline, 1))
                    mstore(add(ptr, 0x84), add(27, shr(255, vs)))
                    calldatacopy(add(ptr, 0xa4), add(permit.offset, 0x24), 0x20) // r
                    mstore(add(ptr, 0xc4), shr(1, shl(1, vs)))
                }
                // IERC20Permit.permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s)
                success := call(gas(), token, 0, ptr, 0xe4, 0, 0)
            }
            case 72 {
                mstore(ptr, daiPermitSelector)
                mstore(add(ptr, 0x04), owner)
                mstore(add(ptr, 0x24), spender)

                // Compact IDaiLikePermit.permit(uint32 nonce, uint32 expiry, uint256 r, uint256 vs)
                {  // stack too deep
                    let expiry := shr(224, calldataload(add(permit.offset, 0x04)))
                    let vs := calldataload(add(permit.offset, 0x28))

                    mstore(add(ptr, 0x44), shr(224, calldataload(permit.offset)))
                    mstore(add(ptr, 0x64), sub(expiry, 1))
                    mstore(add(ptr, 0x84), true)
                    mstore(add(ptr, 0xa4), add(27, shr(255, vs)))
                    calldatacopy(add(ptr, 0xc4), add(permit.offset, 0x08), 0x20) // r
                    mstore(add(ptr, 0xe4), shr(1, shl(1, vs)))
                }
                // IDaiLikePermit.permit(address holder, address spender, uint256 nonce, uint256 expiry, bool allowed, uint8 v, bytes32 r, bytes32 s)
                success := call(gas(), token, 0, ptr, 0x104, 0, 0)
            }
            case 224 {
                mstore(ptr, permitSelector)
                calldatacopy(add(ptr, 0x04), permit.offset, permit.length)
                // IERC20Permit.permit(address owner, address spender, uint256 value, uint256 deadline, uint8 v, bytes32 r, bytes32 s)
                success := call(gas(), token, 0, ptr, 0xe4, 0, 0)
            }
            case 256 {
                mstore(ptr, daiPermitSelector)
                calldatacopy(add(ptr, 0x04), permit.offset, permit.length)
                // IDaiLikePermit.permit(address holder, address spender, uint256 nonce, uint256 expiry, bool allowed, uint8 v, bytes32 r, bytes32 s)
                success := call(gas(), token, 0, ptr, 0x104, 0, 0)
            }
            case 96 {
                // Compact IPermit2.permit(uint160 amount, uint32 expiration, uint32 nonce, uint32 sigDeadline, uint256 r, uint256 vs)
                mstore(ptr, permit2Selector)
                mstore(add(ptr, 0x04), owner)
                mstore(add(ptr, 0x24), token)
                calldatacopy(add(ptr, 0x50), permit.offset, 0x14) // amount
                mstore(add(ptr, 0x64), and(0xffffffffffff, sub(shr(224, calldataload(add(permit.offset, 0x14))), 1))) // expiration
                mstore(add(ptr, 0x84), shr(224, calldataload(add(permit.offset, 0x18)))) // nonce
                mstore(add(ptr, 0xa4), spender)
                mstore(add(ptr, 0xc4), and(0xffffffffffff, sub(shr(224, calldataload(add(permit.offset, 0x1c))), 1))) // sigDeadline
                mstore(add(ptr, 0xe4), 0x100)
                mstore(add(ptr, 0x104), 0x40)
                calldatacopy(add(ptr, 0x124), add(permit.offset, 0x20), 0x20) // r
                calldatacopy(add(ptr, 0x144), add(permit.offset, 0x40), 0x20) // vs
                // IPermit2.permit(address owner, PermitSingle calldata permitSingle, bytes calldata signature)
                success := call(gas(), _PERMIT2, 0, ptr, 0x164, 0, 0)
            }
            case 352 {
                mstore(ptr, permit2Selector)
                calldatacopy(add(ptr, 0x04), permit.offset, permit.length)
                // IPermit2.permit(address owner, PermitSingle calldata permitSingle, bytes calldata signature)
                success := call(gas(), _PERMIT2, 0, ptr, 0x164, 0, 0)
            }
            default {
                mstore(ptr, _PERMIT_LENGHT_ERROR)
                revert(ptr, 4)
            }
        }
    }

    function _makeCall(
        IERC20 token,
        bytes4 selector,
        address to,
        uint256 amount
    ) private returns (bool success) {
        assembly ("memory-safe") { // solhint-disable-line no-inline-assembly
            let data := mload(0x40)

            mstore(data, selector)
            mstore(add(data, 0x04), to)
            mstore(add(data, 0x24), amount)
            success := call(gas(), token, 0, data, 0x44, 0x0, 0x20)
            if success {
                switch returndatasize()
                case 0 {
                    success := gt(extcodesize(token), 0)
                }
                default {
                    success := and(gt(returndatasize(), 31), eq(mload(0), 1))
                }
            }
        }
    }

    function safeDeposit(IWETH weth, uint256 amount) internal {
        if (amount > 0) {
            bytes4 selector = IWETH.deposit.selector;
            assembly ("memory-safe") { // solhint-disable-line no-inline-assembly
                mstore(0, selector)
                if iszero(call(gas(), weth, amount, 0, 4, 0, 0)) {
                    returndatacopy(0, 0, returndatasize())
                    revert(0, returndatasize())
                }
            }
        }
    }

    function safeWithdraw(IWETH weth, uint256 amount) internal {
        bytes4 selector = IWETH.withdraw.selector;
        assembly ("memory-safe") {  // solhint-disable-line no-inline-assembly
            mstore(0, selector)
            mstore(4, amount)
            if iszero(call(gas(), weth, 0, 0, 0x24, 0, 0)) {
                returndatacopy(0, 0, returndatasize())
                revert(0, returndatasize())
            }
        }
    }

    function safeWithdrawTo(IWETH weth, uint256 amount, address to) internal {
        safeWithdraw(weth, amount);
        if (to != address(this)) {
            assembly ("memory-safe") {  // solhint-disable-line no-inline-assembly
                if iszero(call(gas(), to, amount, 0, 0, 0, 0)) {
                    returndatacopy(0, 0, returndatasize())
                    revert(0, returndatasize())
                }
            }
        }
    }
}

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

/// @title Library with gas-efficient string operations
library StringUtil {
    function toHex(uint256 value) internal pure returns (string memory) {
        return toHex(abi.encodePacked(value));
    }

    function toHex(address value) internal pure returns (string memory) {
        return toHex(abi.encodePacked(value));
    }

    /// @dev this is the assembly adaptation of highly optimized toHex16 code from Mikhail Vladimirov
    /// https://stackoverflow.com/a/69266989
    function toHex(bytes memory data) internal pure returns (string memory result) {
        assembly ("memory-safe") { // solhint-disable-line no-inline-assembly
            function _toHex16(input) -> output {
                output := or(
                    and(input, 0xFFFFFFFFFFFFFFFF000000000000000000000000000000000000000000000000),
                    shr(64, and(input, 0x0000000000000000FFFFFFFFFFFFFFFF00000000000000000000000000000000))
                )
                output := or(
                    and(output, 0xFFFFFFFF000000000000000000000000FFFFFFFF000000000000000000000000),
                    shr(32, and(output, 0x00000000FFFFFFFF000000000000000000000000FFFFFFFF0000000000000000))
                )
                output := or(
                    and(output, 0xFFFF000000000000FFFF000000000000FFFF000000000000FFFF000000000000),
                    shr(16, and(output, 0x0000FFFF000000000000FFFF000000000000FFFF000000000000FFFF00000000))
                )
                output := or(
                    and(output, 0xFF000000FF000000FF000000FF000000FF000000FF000000FF000000FF000000),
                    shr(8, and(output, 0x00FF000000FF000000FF000000FF000000FF000000FF000000FF000000FF0000))
                )
                output := or(
                    shr(4, and(output, 0xF000F000F000F000F000F000F000F000F000F000F000F000F000F000F000F000)),
                    shr(8, and(output, 0x0F000F000F000F000F000F000F000F000F000F000F000F000F000F000F000F00))
                )
                output := add(
                    add(0x3030303030303030303030303030303030303030303030303030303030303030, output),
                    mul(
                        and(
                            shr(4, add(output, 0x0606060606060606060606060606060606060606060606060606060606060606)),
                            0x0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F0F
                        ),
                        7 // Change 7 to 39 for lower case output
                    )
                )
            }

            result := mload(0x40)
            let length := mload(data)
            let resultLength := shl(1, length)
            let toPtr := add(result, 0x22) // 32 bytes for length + 2 bytes for '0x'
            mstore(0x40, add(toPtr, resultLength)) // move free memory pointer
            mstore(add(result, 2), 0x3078) // 0x3078 is right aligned so we write to `result + 2`
            // to store the last 2 bytes in the beginning of the string
            mstore(result, add(resultLength, 2)) // extra 2 bytes for '0x'

            for {
                let fromPtr := add(data, 0x20)
                let endPtr := add(fromPtr, length)
            } lt(fromPtr, endPtr) {
                fromPtr := add(fromPtr, 0x20)
            } {
                let rawData := mload(fromPtr)
                let hexData := _toHex16(rawData)
                mstore(toPtr, hexData)
                toPtr := add(toPtr, 0x20)
                hexData := _toHex16(shl(128, rawData))
                mstore(toPtr, hexData)
                toPtr := add(toPtr, 0x20)
            }
        }
    }
}

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol";
import "../interfaces/IERC20MetadataUppercase.sol";
import "./SafeERC20.sol";
import "./StringUtil.sol";

/// @title Library, which allows usage of ETH as ERC20 and ERC20 itself. Uses SafeERC20 library for ERC20 interface.
library UniERC20 {
    using SafeERC20 for IERC20;

    error InsufficientBalance();
    error ApproveCalledOnETH();
    error NotEnoughValue();
    error FromIsNotSender();
    error ToIsNotThis();
    error ETHTransferFailed();

    uint256 private constant _RAW_CALL_GAS_LIMIT = 5000;
    IERC20 private constant _ETH_ADDRESS = IERC20(0xEeeeeEeeeEeEeeEeEeEeeEEEeeeeEeeeeeeeEEeE);
    IERC20 private constant _ZERO_ADDRESS = IERC20(address(0));

    /// @dev Returns true if `token` is ETH.
    function isETH(IERC20 token) internal pure returns (bool) {
        return (token == _ZERO_ADDRESS || token == _ETH_ADDRESS);
    }

    /// @dev Returns `account` ERC20 `token` balance.
    function uniBalanceOf(IERC20 token, address account) internal view returns (uint256) {
        if (isETH(token)) {
            return account.balance;
        } else {
            return token.balanceOf(account);
        }
    }

    /// @dev `token` transfer `to` `amount`.
    /// Note that this function does nothing in case of zero amount.
    function uniTransfer(
        IERC20 token,
        address payable to,
        uint256 amount
    ) internal {
        if (amount > 0) {
            if (isETH(token)) {
                if (address(this).balance < amount) revert InsufficientBalance();
                // solhint-disable-next-line avoid-low-level-calls
                (bool success, ) = to.call{value: amount, gas: _RAW_CALL_GAS_LIMIT}("");
                if (!success) revert ETHTransferFailed();
            } else {
                token.safeTransfer(to, amount);
            }
        }
    }

    /// @dev `token` transfer `from` `to` `amount`.
    /// Note that this function does nothing in case of zero amount.
    function uniTransferFrom(
        IERC20 token,
        address payable from,
        address to,
        uint256 amount
    ) internal {
        if (amount > 0) {
            if (isETH(token)) {
                if (msg.value < amount) revert NotEnoughValue();
                if (from != msg.sender) revert FromIsNotSender();
                if (to != address(this)) revert ToIsNotThis();
                if (msg.value > amount) {
                    // Return remainder if exist
                    unchecked {
                        // solhint-disable-next-line avoid-low-level-calls
                        (bool success, ) = from.call{value: msg.value - amount, gas: _RAW_CALL_GAS_LIMIT}("");
                        if (!success) revert ETHTransferFailed();
                    }
                }
            } else {
                token.safeTransferFrom(from, to, amount);
            }
        }
    }

    /// @dev Returns `token` symbol from ERC20 metadata.
    function uniSymbol(IERC20 token) internal view returns (string memory) {
        return _uniDecode(token, IERC20Metadata.symbol.selector, IERC20MetadataUppercase.SYMBOL.selector);
    }

    /// @dev Returns `token` name from ERC20 metadata.
    function uniName(IERC20 token) internal view returns (string memory) {
        return _uniDecode(token, IERC20Metadata.name.selector, IERC20MetadataUppercase.NAME.selector);
    }

    /// @dev Reverts if `token` is ETH, otherwise performs ERC20 forceApprove.
    function uniApprove(
        IERC20 token,
        address to,
        uint256 amount
    ) internal {
        if (isETH(token)) revert ApproveCalledOnETH();

        token.forceApprove(to, amount);
    }

    /// @dev 20K gas is provided to account for possible implementations of name/symbol
    /// (token implementation might be behind proxy or store the value in storage)
    function _uniDecode(
        IERC20 token,
        bytes4 lowerCaseSelector,
        bytes4 upperCaseSelector
    ) private view returns (string memory result) {
        if (isETH(token)) {
            return "ETH";
        }

        (bool success, bytes memory data) = address(token).staticcall{gas: 20000}(
            abi.encodeWithSelector(lowerCaseSelector)
        );
        if (!success) {
            (success, data) = address(token).staticcall{gas: 20000}(abi.encodeWithSelector(upperCaseSelector));
        }

        if (success && data.length >= 0x40) {
            (uint256 offset, uint256 len) = abi.decode(data, (uint256, uint256));
            /*
                return data is padded up to 32 bytes with ABI encoder also sometimes
                there is extra 32 bytes of zeros padded in the end:
                https://github.com/ethereum/solidity/issues/10170
                because of that we can't check for equality and instead check
                that overall data length is greater or equal than string length + extra 64 bytes
            */
            if (offset == 0x20 && data.length >= 0x40 + len) {
                assembly ("memory-safe") { // solhint-disable-line no-inline-assembly
                    result := add(data, 0x40)
                }
                return result;
            }
        }
        if (success && data.length == 32) {
            uint256 len = 0;
            while (len < data.length && data[len] >= 0x20 && data[len] <= 0x7E) {
                unchecked {
                    len++;
                }
            }

            if (len > 0) {
                assembly ("memory-safe") { // solhint-disable-line no-inline-assembly
                    mstore(data, len)
                }
                return string(data);
            }
        }

        return StringUtil.toHex(address(token));
    }
}

// SPDX-License-Identifier: MIT

pragma solidity ^0.8.0;

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

interface IVotable is IERC20 {
    /// @dev we assume that voting power is a function of balance that preserves order
    function votingPowerOf(address account) external view returns (uint256);
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.7.0) (access/Ownable.sol)

pragma solidity ^0.8.0;

import "../utils/Context.sol";

/**
 * @dev Contract module which provides a basic access control mechanism, where
 * there is an account (an owner) that can be granted exclusive access to
 * specific functions.
 *
 * By default, the owner account will be the one that deploys the contract. This
 * can later be changed with {transferOwnership}.
 *
 * This module is used through inheritance. It will make available the modifier
 * `onlyOwner`, which can be applied to your functions to restrict their use to
 * the owner.
 */
abstract contract Ownable is Context {
    address private _owner;

    event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);

    /**
     * @dev Initializes the contract setting the deployer as the initial owner.
     */
    constructor() {
        _transferOwnership(_msgSender());
    }

    /**
     * @dev Throws if called by any account other than the owner.
     */
    modifier onlyOwner() {
        _checkOwner();
        _;
    }

    /**
     * @dev Returns the address of the current owner.
     */
    function owner() public view virtual returns (address) {
        return _owner;
    }

    /**
     * @dev Throws if the sender is not the owner.
     */
    function _checkOwner() internal view virtual {
        require(owner() == _msgSender(), "Ownable: caller is not the owner");
    }

    /**
     * @dev Leaves the contract without owner. It will not be possible to call
     * `onlyOwner` functions anymore. Can only be called by the current owner.
     *
     * NOTE: Renouncing ownership will leave the contract without an owner,
     * thereby removing any functionality that is only available to the owner.
     */
    function renounceOwnership() public virtual onlyOwner {
        _transferOwnership(address(0));
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Can only be called by the current owner.
     */
    function transferOwnership(address newOwner) public virtual onlyOwner {
        require(newOwner != address(0), "Ownable: new owner is the zero address");
        _transferOwnership(newOwner);
    }

    /**
     * @dev Transfers ownership of the contract to a new account (`newOwner`).
     * Internal function without access restriction.
     */
    function _transferOwnership(address newOwner) internal virtual {
        address oldOwner = _owner;
        _owner = newOwner;
        emit OwnershipTransferred(oldOwner, newOwner);
    }
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/draft-IERC20Permit.sol)

pragma solidity ^0.8.0;

/**
 * @dev Interface of the ERC20 Permit extension allowing approvals to be made via signatures, as defined in
 * https://eips.ethereum.org/EIPS/eip-2612[EIP-2612].
 *
 * Adds the {permit} method, which can be used to change an account's ERC20 allowance (see {IERC20-allowance}) by
 * presenting a message signed by the account. By not relying on {IERC20-approve}, the token holder account doesn't
 * need to send a transaction, and thus is not required to hold Ether at all.
 */
interface IERC20Permit {
    /**
     * @dev Sets `value` as the allowance of `spender` over ``owner``'s tokens,
     * given ``owner``'s signed approval.
     *
     * IMPORTANT: The same issues {IERC20-approve} has related to transaction
     * ordering also apply here.
     *
     * Emits an {Approval} event.
     *
     * Requirements:
     *
     * - `spender` cannot be the zero address.
     * - `deadline` must be a timestamp in the future.
     * - `v`, `r` and `s` must be a valid `secp256k1` signature from `owner`
     * over the EIP712-formatted function arguments.
     * - the signature must use ``owner``'s current nonce (see {nonces}).
     *
     * For more information on the signature format, see the
     * https://eips.ethereum.org/EIPS/eip-2612#specification[relevant EIP
     * section].
     */
    function permit(
        address owner,
        address spender,
        uint256 value,
        uint256 deadline,
        uint8 v,
        bytes32 r,
        bytes32 s
    ) external;

    /**
     * @dev Returns the current nonce for `owner`. This value must be
     * included whenever a signature is generated for {permit}.
     *
     * Every successful call to {permit} increases ``owner``'s nonce by one. This
     * prevents a signature from being used multiple times.
     */
    function nonces(address owner) external view returns (uint256);

    /**
     * @dev Returns the domain separator used in the encoding of the signature for {permit}, as defined by {EIP712}.
     */
    // solhint-disable-next-line func-name-mixedcase
    function DOMAIN_SEPARATOR() external view returns (bytes32);
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)

pragma solidity ^0.8.0;

import "../IERC20.sol";

/**
 * @dev Interface for the optional metadata functions from the ERC20 standard.
 *
 * _Available since v4.1._
 */
interface IERC20Metadata is IERC20 {
    /**
     * @dev Returns the name of the token.
     */
    function name() external view returns (string memory);

    /**
     * @dev Returns the symbol of the token.
     */
    function symbol() external view returns (string memory);

    /**
     * @dev Returns the decimals places of the token.
     */
    function decimals() external view returns (uint8);
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.6.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);
}

// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)

pragma solidity ^0.8.0;

/**
 * @dev Provides information about the current execution context, including the
 * sender of the transaction and its data. While these are generally available
 * via msg.sender and msg.data, they should not be accessed in such a direct
 * manner, since when dealing with meta-transactions the account sending and
 * paying for execution may not be the actual sender (as far as an application
 * is concerned).
 *
 * This contract is only required for intermediate, library-like contracts.
 */
abstract contract Context {
    function _msgSender() internal view virtual returns (address) {
        return msg.sender;
    }

    function _msgData() internal view virtual returns (bytes calldata) {
        return msg.data;
    }
}

Settings
{
  "optimizer": {
    "enabled": true,
    "runs": 1000000
  },
  "viaIR": true,
  "outputSelection": {
    "*": {
      "*": [
        "evm.bytecode",
        "evm.deployedBytecode",
        "devdoc",
        "userdoc",
        "metadata",
        "abi"
      ]
    }
  },
  "metadata": {
    "useLiteralContent": true
  },
  "libraries": {}
}

Contract Security Audit

Contract ABI

API
[{"inputs":[{"internalType":"contract IVotable","name":"token_","type":"address"},{"internalType":"uint256","name":"resolverPercentageThreshold_","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyRegistered","type":"error"},{"inputs":[],"name":"BalanceLessThanThreshold","type":"error"},{"inputs":[],"name":"ETHTransferFailed","type":"error"},{"inputs":[],"name":"IndexOutOfBounds","type":"error"},{"inputs":[],"name":"InsufficientBalance","type":"error"},{"inputs":[],"name":"NotWhitelisted","type":"error"},{"inputs":[],"name":"OutputArrayTooSmall","type":"error"},{"inputs":[],"name":"PopFromEmptyArray","type":"error"},{"inputs":[],"name":"SafeTransferFailed","type":"error"},{"inputs":[],"name":"SamePromotee","type":"error"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"previousOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"promoter","type":"address"},{"indexed":false,"internalType":"uint256","name":"chainId","type":"uint256"},{"indexed":false,"internalType":"address","name":"promotee","type":"address"}],"name":"Promotion","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"addr","type":"address"}],"name":"Registered","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"resolverPercentageThreshold","type":"uint256"}],"name":"ResolverPercentageThresholdSet","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"addr","type":"address"}],"name":"Unregistered","type":"event"},{"inputs":[],"name":"BASIS_POINTS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"clean","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"chainId","type":"uint256"}],"name":"getPromotees","outputs":[{"internalType":"address[]","name":"promotees","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getWhitelist","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"chainId","type":"uint256"},{"internalType":"address","name":"promotee","type":"address"}],"name":"promote","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"},{"internalType":"uint256","name":"","type":"uint256"}],"name":"promotions","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"register","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract IERC20","name":"token_","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"rescueFunds","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"resolverPercentageThreshold","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint256","name":"resolverPercentageThreshold_","type":"uint256"}],"name":"setResolverPercentageThreshold","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"token","outputs":[{"internalType":"contract IVotable","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"nonpayable","type":"function"}]

60a0346100ef57601f61146d38819003918201601f19168301916001600160401b038311848410176100f45780849260409485528339810103126100ef578051906001600160a01b0380831683036100ef577fcbcd22f10b3a748cd1a2d091ce0b2108352aa00351115f173e159e24d97d280e92602080930151906000543360018060a01b0319821617600055604051933391167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0600080a3608052806002558152a1604051611362908161010b8239608051818181610130015281816101fb01528181610a0b01526110110152f35b600080fd5b634e487b7160e01b600052604160045260246000fdfe608060408181526004908136101561001657600080fd5b600092833560e01c9081631aa3a008146109be575080632af0516614610950578063715018a6146108b157806378e3214f1461068d5780638da5cb5b1461063c578063960462d1146105ff578063cfaa095114610593578063d01f63f51461054c578063e1f1c4a714610511578063e5136e941461046d578063f204bdb91461035a578063f2fde38b14610223578063fc0c546a146101b05763fc4333cd146100be57600080fd5b3461019b57827ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019b576002546020825180947f18160ddd0000000000000000000000000000000000000000000000000000000082528173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000165afa9182156101a75750839161016e575b61016b9250610fdc565b80f35b90506020823d821161019f575b8161018860209383610cb1565b8101031261019b5761016b915190610161565b8280fd5b3d915061017b565b513d85823e3d90fd5b83823461021f57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261021f576020905173ffffffffffffffffffffffffffffffffffffffff7f0000000000000000000000000000000000000000000000000000000000000000168152f35b5080fd5b50903461019b5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019b5761025c610bb9565b90610265610c32565b73ffffffffffffffffffffffffffffffffffffffff8092169283156102d75750508254827fffffffffffffffffffffffff00000000000000000000000000000000000000008216178455167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08380a380f35b90602060849251917f08c379a0000000000000000000000000000000000000000000000000000000008352820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152fd5b50903461019b57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019b578035916024359173ffffffffffffffffffffffffffffffffffffffff80841680940361046957839033875260016020528387208688526020528387205416146104425750916060917fb863cf86b291171e4b0332ea12b59af030f98a2c74a6d51effaf1109ae4c7f1e933386526001602052808620838752602052808620827fffffffffffffffffffffffff00000000000000000000000000000000000000008254161790558051923384526020840152820152a180f35b90517f53645587000000000000000000000000000000000000000000000000000000008152fd5b8580fd5b5091903461021f57602090817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019b5735906104ab610dfd565b92835192815b8481106104c9578651806104c58882610be1565b0390f35b60019073ffffffffffffffffffffffffffffffffffffffff806104ec838a610f26565b511685528286528885208486528652888520541661050a8289610f26565b52016104b1565b83823461021f57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261021f57602090516127108152f35b83823461021f57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261021f576104c590610588610dfd565b905191829182610be1565b50903461019b5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019b577fcbcd22f10b3a748cd1a2d091ce0b2108352aa00351115f173e159e24d97d280e9160209135906105f3610c32565b8160025551908152a180f35b83823461021f57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261021f576020906002549051908152f35b83823461021f57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261021f5773ffffffffffffffffffffffffffffffffffffffff60209254169051908152f35b503461019b57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019b57813573ffffffffffffffffffffffffffffffffffffffff8116908181036108ad5784602435926106ea610c32565b836106f3575080f35b801590811561088f575b50156107f95750508047106107d257838080809333611388f13d156107cd573d67ffffffffffffffff81116107a15782519061076160207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8401160183610cb1565b81528460203d92013e5b1561077b5750505b388080808480f35b517fb12d13eb000000000000000000000000000000000000000000000000000000008152fd5b6024856041867f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b61076b565b50517ff4d678b8000000000000000000000000000000000000000000000000000000008152fd5b6044602092938551907fa9059cbb0000000000000000000000000000000000000000000000000000000082523388830152602482015282855af1908161086d575b5015610847575050610773565b517ffb7f5079000000000000000000000000000000000000000000000000000000008152fd5b90503d1561088757506001835114601f3d11165b3861083a565b3b1515610881565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee915014386106fd565b8480fd5b833461094d57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261094d576108e8610c32565b8073ffffffffffffffffffffffffffffffffffffffff81547fffffffffffffffffffffffff000000000000000000000000000000000000000081168355167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b80fd5b83823461021f57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261021f576020918173ffffffffffffffffffffffffffffffffffffffff91826109a3610bb9565b16815260018552818120602435825285522054169051908152f35b905083913461019b57827ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019b576002549073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000000000000000000000000000000000000000000016947f18160ddd00000000000000000000000000000000000000000000000000000000845260209586858381845afa948515610b7d579087918796610b87575b50906024918451928380927f70a0823100000000000000000000000000000000000000000000000000000000825233878301525afa8015610b7d5785908790610b4c575b610ab9925085610f69565b15610b2557610ac733610d21565b15610afe575061016b93947f2d3734a8e47ac8316e500ac231c90a6e1848ca2285f40d07eaa52005e4b3a0e99151338152a1610fdc565b90517f3a81d6fc000000000000000000000000000000000000000000000000000000008152fd5b90517f63bd63ba000000000000000000000000000000000000000000000000000000008152fd5b50508681813d8311610b76575b610b638183610cb1565b810103126104695784610ab99151610aae565b503d610b59565b83513d88823e3d90fd5b8281939297503d8311610bb2575b610b9f8183610cb1565b8101031261046957519386906024610a6a565b503d610b95565b6004359073ffffffffffffffffffffffffffffffffffffffff82168203610bdc57565b600080fd5b6020908160408183019282815285518094520193019160005b828110610c08575050505090565b835173ffffffffffffffffffffffffffffffffffffffff1685529381019392810192600101610bfa565b73ffffffffffffffffffffffffffffffffffffffff600054163303610c5357565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602060248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152fd5b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff821117610cf257604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b73ffffffffffffffffffffffffffffffffffffffff1660009080825260046020526040822054610de15760016040918380526003602052828420908154918260a01c928315600014610dbb575050848052600360205274ffffffffffffffffffffffffffffffffffffffffff81740100000000000000000000000000000000000000000116848620555b8452600460205201912055600190565b740100000000000000000000000000000000000000000190558185528084862055610dab565b5090565b67ffffffffffffffff8111610cf25760051b60200190565b600090818052600391602090838252604090818120548060a01c92610e2184610de5565b92610e2e82519485610cb1565b848452610e3a85610de5565b977fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08786019901368a37849885518711610efd5786610e7e575b5050505050505050565b855115610ed05773ffffffffffffffffffffffffffffffffffffffff8095169052600196875b878110610eb15750610e74565b8089918552838352868686205416610ec9828a610f26565b5201610ea4565b6024837f4e487b710000000000000000000000000000000000000000000000000000000081526032600452fd5b600484517ff9a99b25000000000000000000000000000000000000000000000000000000008152fd5b8051821015610f3a5760209160051b010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9080159283159384610f7d575b5050505090565b9091929350612710808402938404141715610fad57828102928184041490151715610fad57101538808080610f76565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b906000908180526003916020938385526040918281205460a01c93819273ffffffffffffffffffffffffffffffffffffffff807f000000000000000000000000000000000000000000000000000000000000000016965b8086106110465750505050505050505050565b858552888a5281878620541687517f70a082310000000000000000000000000000000000000000000000000000000081528160048201528b816024818d5afa90811561114e578c929187918991611113575b50906110a49187610f69565b611106577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9291816110f67f75cd6de711483e11488a1cd9b66172abccb9e5c19572f92015a7880f0c8c0edc93611158565b508a51908152a101975b97611033565b5050979460010194611100565b92938092508391503d8311611147575b61112d8183610cb1565b8101031261114357518b919086906110a4611098565b8680fd5b503d611123565b89513d89823e3d90fd5b73ffffffffffffffffffffffffffffffffffffffff80911690600091808352602090600482526040928385205490811561132457858052600384528486205460a01c9081831061125c575b50505083805260038252828420548060a01c801561123357906001827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600496959401885260038552878781205511611203575b50845252812055600190565b7fffffffffffffffffffffffff0000000000000000000000000000000000000000908680520184862055386111f7565b600485517f06a2af9e000000000000000000000000000000000000000000000000000000008152fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8092018752858720541690820186805285872054908160a01c8110156112fb57829190806112e857507fffffffffffffffffffffffff000000000000000000000000000000000000000090888052600387521617858720555b855260048352838520553880806111a3565b91505086526003845280858720556112d6565b600487517f4e23d035000000000000000000000000000000000000000000000000000000008152fd5b50505050509056fea2646970667358221220e87881068d133097e15aecadd3bd09d2297669edb899658203bb5f7d2a32c71164736f6c63430008130033000000000000000000000000accfac2339e16dc80c50d2fa81b5c2b049b4f94700000000000000000000000000000000000000000000000000000000000003e8

Deployed Bytecode

0x608060408181526004908136101561001657600080fd5b600092833560e01c9081631aa3a008146109be575080632af0516614610950578063715018a6146108b157806378e3214f1461068d5780638da5cb5b1461063c578063960462d1146105ff578063cfaa095114610593578063d01f63f51461054c578063e1f1c4a714610511578063e5136e941461046d578063f204bdb91461035a578063f2fde38b14610223578063fc0c546a146101b05763fc4333cd146100be57600080fd5b3461019b57827ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019b576002546020825180947f18160ddd0000000000000000000000000000000000000000000000000000000082528173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000accfac2339e16dc80c50d2fa81b5c2b049b4f947165afa9182156101a75750839161016e575b61016b9250610fdc565b80f35b90506020823d821161019f575b8161018860209383610cb1565b8101031261019b5761016b915190610161565b8280fd5b3d915061017b565b513d85823e3d90fd5b83823461021f57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261021f576020905173ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000accfac2339e16dc80c50d2fa81b5c2b049b4f947168152f35b5080fd5b50903461019b5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019b5761025c610bb9565b90610265610c32565b73ffffffffffffffffffffffffffffffffffffffff8092169283156102d75750508254827fffffffffffffffffffffffff00000000000000000000000000000000000000008216178455167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08380a380f35b90602060849251917f08c379a0000000000000000000000000000000000000000000000000000000008352820152602660248201527f4f776e61626c653a206e6577206f776e657220697320746865207a65726f206160448201527f64647265737300000000000000000000000000000000000000000000000000006064820152fd5b50903461019b57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019b578035916024359173ffffffffffffffffffffffffffffffffffffffff80841680940361046957839033875260016020528387208688526020528387205416146104425750916060917fb863cf86b291171e4b0332ea12b59af030f98a2c74a6d51effaf1109ae4c7f1e933386526001602052808620838752602052808620827fffffffffffffffffffffffff00000000000000000000000000000000000000008254161790558051923384526020840152820152a180f35b90517f53645587000000000000000000000000000000000000000000000000000000008152fd5b8580fd5b5091903461021f57602090817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019b5735906104ab610dfd565b92835192815b8481106104c9578651806104c58882610be1565b0390f35b60019073ffffffffffffffffffffffffffffffffffffffff806104ec838a610f26565b511685528286528885208486528652888520541661050a8289610f26565b52016104b1565b83823461021f57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261021f57602090516127108152f35b83823461021f57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261021f576104c590610588610dfd565b905191829182610be1565b50903461019b5760207ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019b577fcbcd22f10b3a748cd1a2d091ce0b2108352aa00351115f173e159e24d97d280e9160209135906105f3610c32565b8160025551908152a180f35b83823461021f57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261021f576020906002549051908152f35b83823461021f57817ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261021f5773ffffffffffffffffffffffffffffffffffffffff60209254169051908152f35b503461019b57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019b57813573ffffffffffffffffffffffffffffffffffffffff8116908181036108ad5784602435926106ea610c32565b836106f3575080f35b801590811561088f575b50156107f95750508047106107d257838080809333611388f13d156107cd573d67ffffffffffffffff81116107a15782519061076160207fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0601f8401160183610cb1565b81528460203d92013e5b1561077b5750505b388080808480f35b517fb12d13eb000000000000000000000000000000000000000000000000000000008152fd5b6024856041867f4e487b7100000000000000000000000000000000000000000000000000000000835252fd5b61076b565b50517ff4d678b8000000000000000000000000000000000000000000000000000000008152fd5b6044602092938551907fa9059cbb0000000000000000000000000000000000000000000000000000000082523388830152602482015282855af1908161086d575b5015610847575050610773565b517ffb7f5079000000000000000000000000000000000000000000000000000000008152fd5b90503d1561088757506001835114601f3d11165b3861083a565b3b1515610881565b73eeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeeee915014386106fd565b8480fd5b833461094d57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261094d576108e8610c32565b8073ffffffffffffffffffffffffffffffffffffffff81547fffffffffffffffffffffffff000000000000000000000000000000000000000081168355167f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08280a380f35b80fd5b83823461021f57807ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261021f576020918173ffffffffffffffffffffffffffffffffffffffff91826109a3610bb9565b16815260018552818120602435825285522054169051908152f35b905083913461019b57827ffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffc36011261019b576002549073ffffffffffffffffffffffffffffffffffffffff7f000000000000000000000000accfac2339e16dc80c50d2fa81b5c2b049b4f94716947f18160ddd00000000000000000000000000000000000000000000000000000000845260209586858381845afa948515610b7d579087918796610b87575b50906024918451928380927f70a0823100000000000000000000000000000000000000000000000000000000825233878301525afa8015610b7d5785908790610b4c575b610ab9925085610f69565b15610b2557610ac733610d21565b15610afe575061016b93947f2d3734a8e47ac8316e500ac231c90a6e1848ca2285f40d07eaa52005e4b3a0e99151338152a1610fdc565b90517f3a81d6fc000000000000000000000000000000000000000000000000000000008152fd5b90517f63bd63ba000000000000000000000000000000000000000000000000000000008152fd5b50508681813d8311610b76575b610b638183610cb1565b810103126104695784610ab99151610aae565b503d610b59565b83513d88823e3d90fd5b8281939297503d8311610bb2575b610b9f8183610cb1565b8101031261046957519386906024610a6a565b503d610b95565b6004359073ffffffffffffffffffffffffffffffffffffffff82168203610bdc57565b600080fd5b6020908160408183019282815285518094520193019160005b828110610c08575050505090565b835173ffffffffffffffffffffffffffffffffffffffff1685529381019392810192600101610bfa565b73ffffffffffffffffffffffffffffffffffffffff600054163303610c5357565b60646040517f08c379a000000000000000000000000000000000000000000000000000000000815260206004820152602060248201527f4f776e61626c653a2063616c6c6572206973206e6f7420746865206f776e65726044820152fd5b90601f7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe0910116810190811067ffffffffffffffff821117610cf257604052565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b73ffffffffffffffffffffffffffffffffffffffff1660009080825260046020526040822054610de15760016040918380526003602052828420908154918260a01c928315600014610dbb575050848052600360205274ffffffffffffffffffffffffffffffffffffffffff81740100000000000000000000000000000000000000000116848620555b8452600460205201912055600190565b740100000000000000000000000000000000000000000190558185528084862055610dab565b5090565b67ffffffffffffffff8111610cf25760051b60200190565b600090818052600391602090838252604090818120548060a01c92610e2184610de5565b92610e2e82519485610cb1565b848452610e3a85610de5565b977fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffe08786019901368a37849885518711610efd5786610e7e575b5050505050505050565b855115610ed05773ffffffffffffffffffffffffffffffffffffffff8095169052600196875b878110610eb15750610e74565b8089918552838352868686205416610ec9828a610f26565b5201610ea4565b6024837f4e487b710000000000000000000000000000000000000000000000000000000081526032600452fd5b600484517ff9a99b25000000000000000000000000000000000000000000000000000000008152fd5b8051821015610f3a5760209160051b010190565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b9080159283159384610f7d575b5050505090565b9091929350612710808402938404141715610fad57828102928184041490151715610fad57101538808080610f76565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b906000908180526003916020938385526040918281205460a01c93819273ffffffffffffffffffffffffffffffffffffffff807f000000000000000000000000accfac2339e16dc80c50d2fa81b5c2b049b4f94716965b8086106110465750505050505050505050565b858552888a5281878620541687517f70a082310000000000000000000000000000000000000000000000000000000081528160048201528b816024818d5afa90811561114e578c929187918991611113575b50906110a49187610f69565b611106577fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff9291816110f67f75cd6de711483e11488a1cd9b66172abccb9e5c19572f92015a7880f0c8c0edc93611158565b508a51908152a101975b97611033565b5050979460010194611100565b92938092508391503d8311611147575b61112d8183610cb1565b8101031261114357518b919086906110a4611098565b8680fd5b503d611123565b89513d89823e3d90fd5b73ffffffffffffffffffffffffffffffffffffffff80911690600091808352602090600482526040928385205490811561132457858052600384528486205460a01c9081831061125c575b50505083805260038252828420548060a01c801561123357906001827fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff600496959401885260038552878781205511611203575b50845252812055600190565b7fffffffffffffffffffffffff0000000000000000000000000000000000000000908680520184862055386111f7565b600485517f06a2af9e000000000000000000000000000000000000000000000000000000008152fd5b7fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff8092018752858720541690820186805285872054908160a01c8110156112fb57829190806112e857507fffffffffffffffffffffffff000000000000000000000000000000000000000090888052600387521617858720555b855260048352838520553880806111a3565b91505086526003845280858720556112d6565b600487517f4e23d035000000000000000000000000000000000000000000000000000000008152fd5b50505050509056fea2646970667358221220e87881068d133097e15aecadd3bd09d2297669edb899658203bb5f7d2a32c71164736f6c63430008130033

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

000000000000000000000000accfac2339e16dc80c50d2fa81b5c2b049b4f94700000000000000000000000000000000000000000000000000000000000003e8

-----Decoded View---------------
Arg [0] : token_ (address): 0xAccfAc2339e16DC80c50d2fa81b5c2B049B4f947
Arg [1] : resolverPercentageThreshold_ (uint256): 1000

-----Encoded View---------------
2 Constructor Arguments found :
Arg [0] : 000000000000000000000000accfac2339e16dc80c50d2fa81b5c2b049b4f947
Arg [1] : 00000000000000000000000000000000000000000000000000000000000003e8


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

OVERVIEW

The DeFi ecosystem building financial freedom for everyone. 1inch products make it easier for users and builders to trade, hold and track digital assets - and 1inch protocols and APIs provide core infrastructure for the DeFi industry and beyond.

Loading...
Loading
[ Download: CSV Export  ]

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