Overview
ETH Balance
0 ETH
Eth Value
$0.00Latest 25 from a total of 177 transactions
| Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
| Promote | 23733655 | 9 days ago | IN | 0 ETH | 0.00014859 | ||||
| Promote | 23726218 | 10 days ago | IN | 0 ETH | 0.00013424 | ||||
| Promote | 23674069 | 17 days ago | IN | 0 ETH | 0.00003248 | ||||
| Promote | 23625650 | 24 days ago | IN | 0 ETH | 0.00004654 | ||||
| Promote | 23602879 | 27 days ago | IN | 0 ETH | 0.00004649 | ||||
| Promote | 23596044 | 28 days ago | IN | 0 ETH | 0.00013895 | ||||
| Promote | 23594957 | 28 days ago | IN | 0 ETH | 0.00003489 | ||||
| Promote | 23591421 | 29 days ago | IN | 0 ETH | 0.00014057 | ||||
| Promote | 23591235 | 29 days ago | IN | 0 ETH | 0.00009964 | ||||
| Promote | 23585960 | 29 days ago | IN | 0 ETH | 0.00004903 | ||||
| Register | 23558707 | 33 days ago | IN | 0 ETH | 0.00023939 | ||||
| Promote | 23558243 | 33 days ago | IN | 0 ETH | 0.00005109 | ||||
| Register | 23483847 | 44 days ago | IN | 0 ETH | 0.00045517 | ||||
| Register | 23469301 | 46 days ago | IN | 0 ETH | 0.00142794 | ||||
| Register | 23451547 | 48 days ago | IN | 0 ETH | 0.00014798 | ||||
| Promote | 23445850 | 49 days ago | IN | 0 ETH | 0.00004837 | ||||
| Clean | 23445795 | 49 days ago | IN | 0 ETH | 0.00007244 | ||||
| Promote | 23387777 | 57 days ago | IN | 0 ETH | 0.00001247 | ||||
| Promote | 23381669 | 58 days ago | IN | 0 ETH | 0.00002547 | ||||
| Promote | 23338812 | 64 days ago | IN | 0 ETH | 0.00002409 | ||||
| Register | 23333716 | 65 days ago | IN | 0 ETH | 0.00040551 | ||||
| Register | 23326029 | 66 days ago | IN | 0 ETH | 0.00040587 | ||||
| Promote | 23324637 | 66 days ago | IN | 0 ETH | 0.00002058 | ||||
| Register | 23323394 | 66 days ago | IN | 0 ETH | 0.00004229 | ||||
| Promote | 23322747 | 66 days ago | IN | 0 ETH | 0.00002071 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
WhitelistRegistry
Compiler Version
v0.8.19+commit.7dd6d404
Optimization Enabled:
Yes with 1000000 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// 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++;
}
}
}
}
}// 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;
}
}// 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;
}
}{
"optimizer": {
"enabled": true,
"runs": 1000000
},
"viaIR": true,
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"metadata": {
"useLiteralContent": true
},
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
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"}]Contract Creation Code
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
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.Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.