Source Code
| Transaction Hash |
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Cross-Chain Transactions
Loading...
Loading
Contract Name:
BribeMarket
Compiler Version
v0.8.12+commit.f00d7308
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: MIT
pragma solidity 0.8.12;
import {AccessControl} from "@openzeppelin/contracts/access/AccessControl.sol";
import {ReentrancyGuard} from "@openzeppelin/contracts/security/ReentrancyGuard.sol";
import {IBribeVault} from "./interfaces/IBribeVault.sol";
import {Common} from "./libraries/Common.sol";
import {Errors} from "./libraries/Errors.sol";
contract BribeMarket is AccessControl, ReentrancyGuard {
bytes32 public constant TEAM_ROLE = keccak256("TEAM_ROLE");
uint256 public constant MAX_PERIODS = 10;
uint256 public constant MAX_PERIOD_DURATION = 30 days;
// Name (identifier) of the market, also used for rewardIdentifiers
// Immutable after initialization
string public PROTOCOL;
// Address of the bribeVault
// Immutable after initialization
address public BRIBE_VAULT;
// Maximum number of periods
uint256 public maxPeriods;
// Period duration
uint256 public periodDuration;
// Whitelisted bribe tokens
address[] private _allWhitelistedTokens;
// Blacklisted voters
address[] private _allBlacklistedVoters;
// Arbitrary bytes mapped to deadlines
mapping(bytes32 => uint256) public proposalDeadlines;
// Tracks whitelisted tokens
mapping(address => uint256) public indexOfWhitelistedToken;
// Tracks blacklisted voters
mapping(address => uint256) public indexOfBlacklistedVoter;
bool private _initialized;
event Initialize(
address bribeVault,
address admin,
string protocol,
uint256 maxPeriods,
uint256 periodDuration
);
event GrantTeamRole(address teamMember);
event RevokeTeamRole(address teamMember);
event SetProposals(bytes32[] proposals, uint256 indexed deadline);
event SetProposalsById(
uint256 indexed proposalIndex,
bytes32[] proposals,
uint256 indexed deadline
);
event SetProposalsByAddress(bytes32[] proposals, uint256 indexed deadline);
event AddWhitelistedTokens(address[] tokens);
event RemoveWhitelistedTokens(address[] tokens);
event SetMaxPeriods(uint256 maxPeriods);
event SetPeriodDuration(uint256 periodDuration);
event AddBlacklistedVoters(address[] voters);
event RemoveBlacklistedVoters(address[] voters);
modifier onlyAuthorized() {
if (
!hasRole(DEFAULT_ADMIN_ROLE, msg.sender) &&
!hasRole(TEAM_ROLE, msg.sender)
) revert Errors.NotAuthorized();
_;
}
modifier onlyInitializer() {
if (_initialized) revert Errors.AlreadyInitialized();
_;
_initialized = true;
}
/**
@notice Initialize the contract
@param _bribeVault Bribe vault address
@param _admin Admin address
@param _protocol Protocol name
@param _maxPeriods Maximum number of periods
@param _periodDuration Period duration
*/
function initialize(
address _bribeVault,
address _admin,
string calldata _protocol,
uint256 _maxPeriods,
uint256 _periodDuration
) external onlyInitializer {
if (_bribeVault == address(0)) revert Errors.InvalidAddress();
if (bytes(_protocol).length == 0) revert Errors.InvalidProtocol();
if (_maxPeriods == 0 || _maxPeriods > MAX_PERIODS)
revert Errors.InvalidMaxPeriod();
if (_periodDuration == 0 || _periodDuration > MAX_PERIOD_DURATION)
revert Errors.InvalidPeriodDuration();
BRIBE_VAULT = _bribeVault;
PROTOCOL = _protocol;
maxPeriods = _maxPeriods;
periodDuration = _periodDuration;
_grantRole(DEFAULT_ADMIN_ROLE, _admin);
emit Initialize(
_bribeVault,
_admin,
_protocol,
_maxPeriods,
_periodDuration
);
}
/**
@notice Set multiple proposals with arbitrary bytes data as identifiers under the same deadline
@param _identifiers bytes[] identifiers
@param _deadline uint256 Proposal deadline
*/
function setProposals(
bytes[] calldata _identifiers,
uint256 _deadline
) external onlyAuthorized {
uint256 identifiersLen = _identifiers.length;
if (identifiersLen == 0) revert Errors.InvalidAddress();
if (_deadline < block.timestamp) revert Errors.InvalidDeadline();
bytes32[] memory proposalIds = new bytes32[](identifiersLen);
uint256 i;
do {
if (_identifiers[i].length == 0) revert Errors.InvalidIdentifier();
proposalIds[i] = keccak256(abi.encodePacked(_identifiers[i]));
_setProposal(proposalIds[i], _deadline);
++i;
} while (i < identifiersLen);
emit SetProposals(proposalIds, _deadline);
}
/**
@notice Set proposals based on the index of the proposal and the number of choices
@param _proposalIndex uint256 Proposal index
@param _choiceCount uint256 Number of choices to be voted for
@param _deadline uint256 Proposal deadline
*/
function setProposalsById(
uint256 _proposalIndex,
uint256 _choiceCount,
uint256 _deadline
) external onlyAuthorized {
if (_choiceCount == 0) revert Errors.InvalidChoiceCount();
if (_deadline < block.timestamp) revert Errors.InvalidDeadline();
bytes32[] memory proposalIds = new bytes32[](_choiceCount);
uint256 i;
do {
proposalIds[i] = keccak256(abi.encodePacked(_proposalIndex, i));
_setProposal(proposalIds[i], _deadline);
++i;
} while (i < _choiceCount);
emit SetProposalsById(_proposalIndex, proposalIds, _deadline);
}
/**
@notice Set multiple proposals for many addresses under the same deadline
@param _addresses address[] addresses (eg. gauge addresses)
@param _deadline uint256 Proposal deadline
*/
function setProposalsByAddress(
address[] calldata _addresses,
uint256 _deadline
) external onlyAuthorized {
uint256 addressesLen = _addresses.length;
if (addressesLen == 0) revert Errors.InvalidAddress();
if (_deadline < block.timestamp) revert Errors.InvalidDeadline();
bytes32[] memory proposalIds = new bytes32[](addressesLen);
uint256 i;
do {
if (_addresses[i] == address(0)) revert Errors.InvalidAddress();
proposalIds[i] = keccak256(abi.encodePacked(_addresses[i]));
_setProposal(proposalIds[i], _deadline);
++i;
} while (i < addressesLen);
emit SetProposalsByAddress(proposalIds, _deadline);
}
/**
@notice Grant the team role to an address
@param _teamMember address Address to grant the teamMember role
*/
function grantTeamRole(
address _teamMember
) external onlyRole(DEFAULT_ADMIN_ROLE) {
if (_teamMember == address(0)) revert Errors.InvalidAddress();
_grantRole(TEAM_ROLE, _teamMember);
emit GrantTeamRole(_teamMember);
}
/**
@notice Revoke the team role from an address
@param _teamMember address Address to revoke the teamMember role
*/
function revokeTeamRole(
address _teamMember
) external onlyRole(DEFAULT_ADMIN_ROLE) {
if (!hasRole(TEAM_ROLE, _teamMember)) revert Errors.NotTeamMember();
_revokeRole(TEAM_ROLE, _teamMember);
emit RevokeTeamRole(_teamMember);
}
/**
@notice Set maximum periods for submitting bribes ahead of time
@param _periods uint256 Maximum periods
*/
function setMaxPeriods(
uint256 _periods
) external onlyRole(DEFAULT_ADMIN_ROLE) {
if (_periods == 0 || _periods > MAX_PERIODS)
revert Errors.InvalidMaxPeriod();
maxPeriods = _periods;
emit SetMaxPeriods(_periods);
}
/**
@notice Set period duration per voting round
@param _periodDuration uint256 Period duration
*/
function setPeriodDuration(
uint256 _periodDuration
) external onlyRole(DEFAULT_ADMIN_ROLE) {
if (_periodDuration == 0 || _periodDuration > MAX_PERIOD_DURATION)
revert Errors.InvalidPeriodDuration();
periodDuration = _periodDuration;
emit SetPeriodDuration(_periodDuration);
}
/**
@notice Add whitelisted tokens
@param _tokens address[] Tokens to add to whitelist
*/
function addWhitelistedTokens(
address[] calldata _tokens
) external onlyAuthorized {
uint256 tLen = _tokens.length;
for (uint256 i; i < tLen; ) {
if (_tokens[i] == address(0)) revert Errors.InvalidAddress();
if (_tokens[i] == BRIBE_VAULT)
revert Errors.NoWhitelistBribeVault();
if (isWhitelistedToken(_tokens[i]))
revert Errors.TokenWhitelisted();
// Perform creation op for the unordered key set
_allWhitelistedTokens.push(_tokens[i]);
indexOfWhitelistedToken[_tokens[i]] =
_allWhitelistedTokens.length -
1;
unchecked {
++i;
}
}
emit AddWhitelistedTokens(_tokens);
}
/**
@notice Remove whitelisted tokens
@param _tokens address[] Tokens to remove from whitelist
*/
function removeWhitelistedTokens(
address[] calldata _tokens
) external onlyAuthorized {
uint256 tLen = _tokens.length;
for (uint256 i; i < tLen; ) {
if (!isWhitelistedToken(_tokens[i]))
revert Errors.TokenNotWhitelisted();
// Perform deletion op for the unordered key set
// by swapping the affected row to the end/tail of the list
uint256 index = indexOfWhitelistedToken[_tokens[i]];
address tail = _allWhitelistedTokens[
_allWhitelistedTokens.length - 1
];
_allWhitelistedTokens[index] = tail;
indexOfWhitelistedToken[tail] = index;
delete indexOfWhitelistedToken[_tokens[i]];
_allWhitelistedTokens.pop();
unchecked {
++i;
}
}
emit RemoveWhitelistedTokens(_tokens);
}
/**
@notice Add blacklisted voters
@param _voters address[] Voters to add to blacklist
*/
function addBlacklistedVoters(
address[] calldata _voters
) external onlyRole(DEFAULT_ADMIN_ROLE) {
uint256 vLen = _voters.length;
for (uint256 i; i < vLen; ) {
if (_voters[i] == address(0)) revert Errors.InvalidAddress();
if (isBlacklistedVoter(_voters[i]))
revert Errors.VoterBlacklisted();
_allBlacklistedVoters.push(_voters[i]);
indexOfBlacklistedVoter[_voters[i]] =
_allBlacklistedVoters.length -
1;
unchecked {
++i;
}
}
emit AddBlacklistedVoters(_voters);
}
/**
@notice Remove blacklisted voters
@param _voters address[] Voters to remove from blacklist
*/
function removeBlacklistedVoters(
address[] calldata _voters
) external onlyRole(DEFAULT_ADMIN_ROLE) {
uint256 vLen = _voters.length;
for (uint256 i; i < vLen; ) {
if (!isBlacklistedVoter(_voters[i]))
revert Errors.VoterNotBlacklisted();
// Perform deletion op for the unordered key set
// by swapping the affected row to the end/tail of the list
uint256 index = indexOfBlacklistedVoter[_voters[i]];
address tail = _allBlacklistedVoters[
_allBlacklistedVoters.length - 1
];
_allBlacklistedVoters[index] = tail;
indexOfBlacklistedVoter[tail] = index;
delete indexOfBlacklistedVoter[_voters[i]];
_allBlacklistedVoters.pop();
unchecked {
++i;
}
}
emit RemoveBlacklistedVoters(_voters);
}
/**
@notice Deposit bribe for a proposal (ERC20 tokens only)
@param _proposal bytes32 Proposal
@param _token address Token
@param _amount uint256 Token amount
@param _maxTokensPerVote uint256 Max amount of token per vote
@param _periods uint256 Number of periods the bribe will be valid
*/
function depositBribe(
bytes32 _proposal,
address _token,
uint256 _amount,
uint256 _maxTokensPerVote,
uint256 _periods
) external nonReentrant {
_depositBribe(
_proposal,
_token,
_amount,
_maxTokensPerVote,
_periods,
0,
""
);
}
/**
@notice Deposit bribe for a proposal (ERC20 tokens only) using permit
@param _proposal bytes32 Proposal
@param _token address Token
@param _amount uint256 Token amount
@param _maxTokensPerVote uint256 Max amount of token per vote
@param _periods uint256 Number of periods the bribe will be valid
@param _permitDeadline uint256 Deadline for permit signature
@param _signature bytes Permit signature
*/
function depositBribeWithPermit(
bytes32 _proposal,
address _token,
uint256 _amount,
uint256 _maxTokensPerVote,
uint256 _periods,
uint256 _permitDeadline,
bytes memory _signature
) external nonReentrant {
_depositBribe(
_proposal,
_token,
_amount,
_maxTokensPerVote,
_periods,
_permitDeadline,
_signature
);
}
/**
@notice Return the list of currently whitelisted token addresses
*/
function getWhitelistedTokens() external view returns (address[] memory) {
return _allWhitelistedTokens;
}
/**
@notice Return the list of currently blacklisted voter addresses
*/
function getBlacklistedVoters() external view returns (address[] memory) {
return _allBlacklistedVoters;
}
/**
@notice Get bribe from BribeVault
@param _proposal bytes32 Proposal
@param _proposalDeadline uint256 Proposal deadline
@param _token address Token
@return bribeToken address Token address
@return bribeAmount address Token amount
*/
function getBribe(
bytes32 _proposal,
uint256 _proposalDeadline,
address _token
) external view returns (address bribeToken, uint256 bribeAmount) {
(bribeToken, bribeAmount) = IBribeVault(BRIBE_VAULT).getBribe(
keccak256(
abi.encodePacked(
address(this),
_proposal,
_proposalDeadline,
_token
)
)
);
}
/**
@notice Return whether the specified token is whitelisted
@param _token address Token address to be checked
*/
function isWhitelistedToken(address _token) public view returns (bool) {
if (_allWhitelistedTokens.length == 0) {
return false;
}
return
indexOfWhitelistedToken[_token] != 0 ||
_allWhitelistedTokens[0] == _token;
}
/**
@notice Return whether the specified address is blacklisted
@param _voter address Voter address to be checked
*/
function isBlacklistedVoter(address _voter) public view returns (bool) {
if (_allBlacklistedVoters.length == 0) {
return false;
}
return
indexOfBlacklistedVoter[_voter] != 0 ||
_allBlacklistedVoters[0] == _voter;
}
/**
@notice Deposit bribe for a proposal (ERC20 tokens only) with optional permit parameters
@param _proposal bytes32 Proposal
@param _token address Token
@param _amount uint256 Token amount
@param _maxTokensPerVote uint256 Max amount of token per vote
@param _periods uint256 Number of periods the bribe will be valid
@param _permitDeadline uint256 Deadline for permit signature
@param _signature bytes Permit signature
*/
function _depositBribe(
bytes32 _proposal,
address _token,
uint256 _amount,
uint256 _maxTokensPerVote,
uint256 _periods,
uint256 _permitDeadline,
bytes memory _signature
) internal {
uint256 proposalDeadline = proposalDeadlines[_proposal];
if (proposalDeadline < block.timestamp) revert Errors.DeadlinePassed();
if (_periods == 0 || _periods > maxPeriods)
revert Errors.InvalidPeriod();
if (_token == address(0)) revert Errors.InvalidAddress();
if (!isWhitelistedToken(_token)) revert Errors.TokenNotWhitelisted();
if (_amount == 0) revert Errors.InvalidAmount();
IBribeVault(BRIBE_VAULT).depositBribe(
Common.DepositBribeParams({
proposal: _proposal,
token: _token,
briber: msg.sender,
amount: _amount,
maxTokensPerVote: _maxTokensPerVote,
periods: _periods,
periodDuration: periodDuration,
proposalDeadline: proposalDeadline,
permitDeadline: _permitDeadline,
signature: _signature
})
);
}
/**
@notice Set a single proposal
@param _proposal bytes32 Proposal
@param _deadline uint256 Proposal deadline
*/
function _setProposal(bytes32 _proposal, uint256 _deadline) internal {
proposalDeadlines[_proposal] = _deadline;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (access/AccessControl.sol)
pragma solidity ^0.8.0;
import "./IAccessControl.sol";
import "../utils/Context.sol";
import "../utils/Strings.sol";
import "../utils/introspection/ERC165.sol";
/**
* @dev Contract module that allows children to implement role-based access
* control mechanisms. This is a lightweight version that doesn't allow enumerating role
* members except through off-chain means by accessing the contract event logs. Some
* applications may benefit from on-chain enumerability, for those cases see
* {AccessControlEnumerable}.
*
* Roles are referred to by their `bytes32` identifier. These should be exposed
* in the external API and be unique. The best way to achieve this is by
* using `public constant` hash digests:
*
* ```solidity
* bytes32 public constant MY_ROLE = keccak256("MY_ROLE");
* ```
*
* Roles can be used to represent a set of permissions. To restrict access to a
* function call, use {hasRole}:
*
* ```solidity
* function foo() public {
* require(hasRole(MY_ROLE, msg.sender));
* ...
* }
* ```
*
* Roles can be granted and revoked dynamically via the {grantRole} and
* {revokeRole} functions. Each role has an associated admin role, and only
* accounts that have a role's admin role can call {grantRole} and {revokeRole}.
*
* By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means
* that only accounts with this role will be able to grant or revoke other
* roles. More complex role relationships can be created by using
* {_setRoleAdmin}.
*
* WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to
* grant and revoke this role. Extra precautions should be taken to secure
* accounts that have been granted it. We recommend using {AccessControlDefaultAdminRules}
* to enforce additional security measures for this role.
*/
abstract contract AccessControl is Context, IAccessControl, ERC165 {
struct RoleData {
mapping(address => bool) members;
bytes32 adminRole;
}
mapping(bytes32 => RoleData) private _roles;
bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;
/**
* @dev Modifier that checks that an account has a specific role. Reverts
* with a standardized message including the required role.
*
* The format of the revert reason is given by the following regular expression:
*
* /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
*
* _Available since v4.1._
*/
modifier onlyRole(bytes32 role) {
_checkRole(role);
_;
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);
}
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) public view virtual override returns (bool) {
return _roles[role].members[account];
}
/**
* @dev Revert with a standard message if `_msgSender()` is missing `role`.
* Overriding this function changes the behavior of the {onlyRole} modifier.
*
* Format of the revert message is described in {_checkRole}.
*
* _Available since v4.6._
*/
function _checkRole(bytes32 role) internal view virtual {
_checkRole(role, _msgSender());
}
/**
* @dev Revert with a standard message if `account` is missing `role`.
*
* The format of the revert reason is given by the following regular expression:
*
* /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
*/
function _checkRole(bytes32 role, address account) internal view virtual {
if (!hasRole(role, account)) {
revert(
string(
abi.encodePacked(
"AccessControl: account ",
Strings.toHexString(account),
" is missing role ",
Strings.toHexString(uint256(role), 32)
)
)
);
}
}
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) {
return _roles[role].adminRole;
}
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*
* May emit a {RoleGranted} event.
*/
function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
_grantRole(role, account);
}
/**
* @dev Revokes `role` from `account`.
*
* If `account` had been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*
* May emit a {RoleRevoked} event.
*/
function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
_revokeRole(role, account);
}
/**
* @dev Revokes `role` from the calling account.
*
* Roles are often managed via {grantRole} and {revokeRole}: this function's
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* If the calling account had been revoked `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `account`.
*
* May emit a {RoleRevoked} event.
*/
function renounceRole(bytes32 role, address account) public virtual override {
require(account == _msgSender(), "AccessControl: can only renounce roles for self");
_revokeRole(role, account);
}
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event. Note that unlike {grantRole}, this function doesn't perform any
* checks on the calling account.
*
* May emit a {RoleGranted} event.
*
* [WARNING]
* ====
* This function should only be called from the constructor when setting
* up the initial roles for the system.
*
* Using this function in any other way is effectively circumventing the admin
* system imposed by {AccessControl}.
* ====
*
* NOTE: This function is deprecated in favor of {_grantRole}.
*/
function _setupRole(bytes32 role, address account) internal virtual {
_grantRole(role, account);
}
/**
* @dev Sets `adminRole` as ``role``'s admin role.
*
* Emits a {RoleAdminChanged} event.
*/
function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
bytes32 previousAdminRole = getRoleAdmin(role);
_roles[role].adminRole = adminRole;
emit RoleAdminChanged(role, previousAdminRole, adminRole);
}
/**
* @dev Grants `role` to `account`.
*
* Internal function without access restriction.
*
* May emit a {RoleGranted} event.
*/
function _grantRole(bytes32 role, address account) internal virtual {
if (!hasRole(role, account)) {
_roles[role].members[account] = true;
emit RoleGranted(role, account, _msgSender());
}
}
/**
* @dev Revokes `role` from `account`.
*
* Internal function without access restriction.
*
* May emit a {RoleRevoked} event.
*/
function _revokeRole(bytes32 role, address account) internal virtual {
if (hasRole(role, account)) {
_roles[role].members[account] = false;
emit RoleRevoked(role, account, _msgSender());
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)
pragma solidity ^0.8.0;
/**
* @dev External interface of AccessControl declared to support ERC165 detection.
*/
interface IAccessControl {
/**
* @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
*
* `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
* {RoleAdminChanged} not being emitted signaling this.
*
* _Available since v3.1._
*/
event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);
/**
* @dev Emitted when `account` is granted `role`.
*
* `sender` is the account that originated the contract call, an admin role
* bearer except when using {AccessControl-_setupRole}.
*/
event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Emitted when `account` is revoked `role`.
*
* `sender` is the account that originated the contract call:
* - if using `revokeRole`, it is the admin role bearer
* - if using `renounceRole`, it is the role bearer (i.e. `account`)
*/
event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) external view returns (bool);
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {AccessControl-_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) external view returns (bytes32);
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function grantRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from `account`.
*
* If `account` had been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function revokeRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from the calling account.
*
* Roles are often managed via {grantRole} and {revokeRole}: this function's
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* If the calling account had been granted `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `account`.
*/
function renounceRole(bytes32 role, address account) external;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (security/ReentrancyGuard.sol)
pragma solidity ^0.8.0;
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*/
abstract contract ReentrancyGuard {
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
uint256 private _status;
constructor() {
_status = _NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and making it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
_nonReentrantBefore();
_;
_nonReentrantAfter();
}
function _nonReentrantBefore() private {
// On the first call to nonReentrant, _status will be _NOT_ENTERED
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
// Any calls to nonReentrant after this point will fail
_status = _ENTERED;
}
function _nonReentrantAfter() private {
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = _NOT_ENTERED;
}
/**
* @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
* `nonReentrant` function in the call stack.
*/
function _reentrancyGuardEntered() internal view returns (bool) {
return _status == _ENTERED;
}
}// 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;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)
pragma solidity ^0.8.0;
import "./IERC165.sol";
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
* for the additional interface id that will be supported. For example:
*
* ```solidity
* function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
* return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
* }
* ```
*
* Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
*/
abstract contract ERC165 is IERC165 {
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/math/Math.sol)
pragma solidity ^0.8.0;
/**
* @dev Standard math utilities missing in the Solidity language.
*/
library Math {
enum Rounding {
Down, // Toward negative infinity
Up, // Toward infinity
Zero // Toward zero
}
/**
* @dev Returns the largest of two numbers.
*/
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a > b ? a : b;
}
/**
* @dev Returns the smallest of two numbers.
*/
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two numbers. The result is rounded towards
* zero.
*/
function average(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b) / 2 can overflow.
return (a & b) + (a ^ b) / 2;
}
/**
* @dev Returns the ceiling of the division of two numbers.
*
* This differs from standard division with `/` in that it rounds up instead
* of rounding down.
*/
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b - 1) / b can overflow on addition, so we distribute.
return a == 0 ? 0 : (a - 1) / b + 1;
}
/**
* @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
* @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
* with further edits by Uniswap Labs also under MIT license.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator) internal pure returns (uint256 result) {
unchecked {
// 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
// use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
// variables such that product = prod1 * 2^256 + prod0.
uint256 prod0; // Least significant 256 bits of the product
uint256 prod1; // Most significant 256 bits of the product
assembly {
let mm := mulmod(x, y, not(0))
prod0 := mul(x, y)
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
// Handle non-overflow cases, 256 by 256 division.
if (prod1 == 0) {
// Solidity will revert if denominator == 0, unlike the div opcode on its own.
// The surrounding unchecked block does not change this fact.
// See https://docs.soliditylang.org/en/latest/control-structures.html#checked-or-unchecked-arithmetic.
return prod0 / denominator;
}
// Make sure the result is less than 2^256. Also prevents denominator == 0.
require(denominator > prod1, "Math: mulDiv overflow");
///////////////////////////////////////////////
// 512 by 256 division.
///////////////////////////////////////////////
// Make division exact by subtracting the remainder from [prod1 prod0].
uint256 remainder;
assembly {
// Compute remainder using mulmod.
remainder := mulmod(x, y, denominator)
// Subtract 256 bit number from 512 bit number.
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
// Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
// See https://cs.stackexchange.com/q/138556/92363.
// Does not overflow because the denominator cannot be zero at this stage in the function.
uint256 twos = denominator & (~denominator + 1);
assembly {
// Divide denominator by twos.
denominator := div(denominator, twos)
// Divide [prod1 prod0] by twos.
prod0 := div(prod0, twos)
// Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
twos := add(div(sub(0, twos), twos), 1)
}
// Shift in bits from prod1 into prod0.
prod0 |= prod1 * twos;
// Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
// that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
// four bits. That is, denominator * inv = 1 mod 2^4.
uint256 inverse = (3 * denominator) ^ 2;
// Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
// in modular arithmetic, doubling the correct bits in each step.
inverse *= 2 - denominator * inverse; // inverse mod 2^8
inverse *= 2 - denominator * inverse; // inverse mod 2^16
inverse *= 2 - denominator * inverse; // inverse mod 2^32
inverse *= 2 - denominator * inverse; // inverse mod 2^64
inverse *= 2 - denominator * inverse; // inverse mod 2^128
inverse *= 2 - denominator * inverse; // inverse mod 2^256
// Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
// This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
// less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
// is no longer required.
result = prod0 * inverse;
return result;
}
}
/**
* @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
*/
function mulDiv(uint256 x, uint256 y, uint256 denominator, Rounding rounding) internal pure returns (uint256) {
uint256 result = mulDiv(x, y, denominator);
if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
result += 1;
}
return result;
}
/**
* @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.
*
* Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
*/
function sqrt(uint256 a) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
// For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
//
// We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
// `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
//
// This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
// → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
// → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
//
// Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
uint256 result = 1 << (log2(a) >> 1);
// At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
// since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
// every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
// into the expected uint128 result.
unchecked {
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
return min(result, a / result);
}
}
/**
* @notice Calculates sqrt(a), following the selected rounding direction.
*/
function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = sqrt(a);
return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
}
}
/**
* @dev Return the log in base 2, rounded down, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 128;
}
if (value >> 64 > 0) {
value >>= 64;
result += 64;
}
if (value >> 32 > 0) {
value >>= 32;
result += 32;
}
if (value >> 16 > 0) {
value >>= 16;
result += 16;
}
if (value >> 8 > 0) {
value >>= 8;
result += 8;
}
if (value >> 4 > 0) {
value >>= 4;
result += 4;
}
if (value >> 2 > 0) {
value >>= 2;
result += 2;
}
if (value >> 1 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 2, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log2(value);
return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 10, rounded down, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >= 10 ** 64) {
value /= 10 ** 64;
result += 64;
}
if (value >= 10 ** 32) {
value /= 10 ** 32;
result += 32;
}
if (value >= 10 ** 16) {
value /= 10 ** 16;
result += 16;
}
if (value >= 10 ** 8) {
value /= 10 ** 8;
result += 8;
}
if (value >= 10 ** 4) {
value /= 10 ** 4;
result += 4;
}
if (value >= 10 ** 2) {
value /= 10 ** 2;
result += 2;
}
if (value >= 10 ** 1) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log10(value);
return result + (rounding == Rounding.Up && 10 ** result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 256, rounded down, of a positive value.
* Returns 0 if given 0.
*
* Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
*/
function log256(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 16;
}
if (value >> 64 > 0) {
value >>= 64;
result += 8;
}
if (value >> 32 > 0) {
value >>= 32;
result += 4;
}
if (value >> 16 > 0) {
value >>= 16;
result += 2;
}
if (value >> 8 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 256, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log256(value);
return result + (rounding == Rounding.Up && 1 << (result << 3) < value ? 1 : 0);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/SignedMath.sol)
pragma solidity ^0.8.0;
/**
* @dev Standard signed math utilities missing in the Solidity language.
*/
library SignedMath {
/**
* @dev Returns the largest of two signed numbers.
*/
function max(int256 a, int256 b) internal pure returns (int256) {
return a > b ? a : b;
}
/**
* @dev Returns the smallest of two signed numbers.
*/
function min(int256 a, int256 b) internal pure returns (int256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two signed numbers without overflow.
* The result is rounded towards zero.
*/
function average(int256 a, int256 b) internal pure returns (int256) {
// Formula from the book "Hacker's Delight"
int256 x = (a & b) + ((a ^ b) >> 1);
return x + (int256(uint256(x) >> 255) & (a ^ b));
}
/**
* @dev Returns the absolute unsigned value of a signed value.
*/
function abs(int256 n) internal pure returns (uint256) {
unchecked {
// must be unchecked in order to support `n = type(int256).min`
return uint256(n >= 0 ? n : -n);
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.9.0) (utils/Strings.sol)
pragma solidity ^0.8.0;
import "./math/Math.sol";
import "./math/SignedMath.sol";
/**
* @dev String operations.
*/
library Strings {
bytes16 private constant _SYMBOLS = "0123456789abcdef";
uint8 private constant _ADDRESS_LENGTH = 20;
/**
* @dev Converts a `uint256` to its ASCII `string` decimal representation.
*/
function toString(uint256 value) internal pure returns (string memory) {
unchecked {
uint256 length = Math.log10(value) + 1;
string memory buffer = new string(length);
uint256 ptr;
/// @solidity memory-safe-assembly
assembly {
ptr := add(buffer, add(32, length))
}
while (true) {
ptr--;
/// @solidity memory-safe-assembly
assembly {
mstore8(ptr, byte(mod(value, 10), _SYMBOLS))
}
value /= 10;
if (value == 0) break;
}
return buffer;
}
}
/**
* @dev Converts a `int256` to its ASCII `string` decimal representation.
*/
function toString(int256 value) internal pure returns (string memory) {
return string(abi.encodePacked(value < 0 ? "-" : "", toString(SignedMath.abs(value))));
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
*/
function toHexString(uint256 value) internal pure returns (string memory) {
unchecked {
return toHexString(value, Math.log256(value) + 1);
}
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
*/
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = _SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
/**
* @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.
*/
function toHexString(address addr) internal pure returns (string memory) {
return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
}
/**
* @dev Returns true if the two strings are equal.
*/
function equal(string memory a, string memory b) internal pure returns (bool) {
return keccak256(bytes(a)) == keccak256(bytes(b));
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.12;
import "../libraries/Common.sol";
interface IBribeVault {
/**
@notice Deposit bribe (ERC20 only)
@param _depositParams DepositBribeParams Deposit data
*/
function depositBribe(
Common.DepositBribeParams calldata _depositParams
) external;
/**
@notice Get bribe information based on the specified identifier
@param _bribeIdentifier bytes32 The specified bribe identifier
*/
function getBribe(
bytes32 _bribeIdentifier
) external view returns (address token, uint256 amount);
/**
@notice Transfer fees to fee recipient and bribes to distributor and update rewards metadata
@param _rewardIdentifiers bytes32[] List of rewardIdentifiers
*/
function transferBribes(bytes32[] calldata _rewardIdentifiers) external;
/**
@notice Grant the depositor role to an address
@param _depositor address Address to grant the depositor role
*/
function grantDepositorRole(address _depositor) external;
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.12;
library Common {
/**
* @param identifier bytes32 Identifier of the distribution
* @param token address Address of the token to distribute
* @param merkleRoot bytes32 Merkle root of the distribution
* @param proof bytes32 Proof of the distribution
*/
struct Distribution {
bytes32 identifier;
address token;
bytes32 merkleRoot;
bytes32 proof;
}
/**
* @param proposal bytes32 Proposal to bribe
* @param token address Token to bribe with
* @param briber address Address of the briber
* @param amount uint256 Amount of tokens to bribe with
* @param maxTokensPerVote uint256 Maximum amount of tokens to use per vote
* @param periods uint256 Number of periods to bribe for
* @param periodDuration uint256 Duration of each period
* @param proposalDeadline uint256 Deadline for the proposal
* @param permitDeadline uint256 Deadline for the permit2 signature
* @param signature bytes Permit2 signature
*/
struct DepositBribeParams {
bytes32 proposal;
address token;
address briber;
uint256 amount;
uint256 maxTokensPerVote;
uint256 periods;
uint256 periodDuration;
uint256 proposalDeadline;
uint256 permitDeadline;
bytes signature;
}
/**
* @param rwIdentifier bytes32 Identifier for claiming reward
* @param fromToken address Address of token to swap from
* @param toToken address Address of token to swap to
* @param fromAmount uint256 Amount of fromToken to swap
* @param toAmount uint256 Amount of toToken to receive
* @param deadline uint256 Timestamp until which swap may be fulfilled
* @param callees address[] Array of addresses to call (DEX addresses)
* @param callLengths uint256[] Index of the beginning of each call in exchangeData
* @param values uint256[] Array of encoded values for each call in exchangeData
* @param exchangeData bytes Calldata to execute on callees
* @param rwMerkleProof bytes32[] Merkle proof for the reward claim
*/
struct ClaimAndSwapData {
bytes32 rwIdentifier;
address fromToken;
address toToken;
uint256 fromAmount;
uint256 toAmount;
uint256 deadline;
address[] callees;
uint256[] callLengths;
uint256[] values;
bytes exchangeData;
bytes32[] rwMerkleProof;
}
/**
* @param identifier bytes32 Identifier for claiming reward
* @param account address Address of the account to claim for
* @param amount uint256 Amount of tokens to claim
* @param merkleProof bytes32[] Merkle proof for the reward claim
*/
struct Claim {
bytes32 identifier;
address account;
uint256 amount;
bytes32[] merkleProof;
}
}// SPDX-License-Identifier: MIT
pragma solidity 0.8.12;
library Errors {
/**
* @notice max period 0 or greater than MAX_PERIODS
*/
error InvalidMaxPeriod();
/**
* @notice period duration 0 or greater than MAX_PERIOD_DURATION
*/
error InvalidPeriodDuration();
/**
* @notice address provided is not a contract
*/
error NotAContract();
/**
* @notice not authorized
*/
error NotAuthorized();
/**
* @notice contract already initialized
*/
error AlreadyInitialized();
/**
* @notice address(0)
*/
error InvalidAddress();
/**
* @notice empty bytes identifier
*/
error InvalidIdentifier();
/**
* @notice invalid protocol name
*/
error InvalidProtocol();
/**
* @notice invalid number of choices
*/
error InvalidChoiceCount();
/**
* @notice invalid input amount
*/
error InvalidAmount();
/**
* @notice not team member
*/
error NotTeamMember();
/**
* @notice cannot whitelist BRIBE_VAULT
*/
error NoWhitelistBribeVault();
/**
* @notice token already whitelisted
*/
error TokenWhitelisted();
/**
* @notice token not whitelisted
*/
error TokenNotWhitelisted();
/**
* @notice voter already blacklisted
*/
error VoterBlacklisted();
/**
* @notice voter not blacklisted
*/
error VoterNotBlacklisted();
/**
* @notice deadline has passed
*/
error DeadlinePassed();
/**
* @notice invalid period
*/
error InvalidPeriod();
/**
* @notice invalid deadline
*/
error InvalidDeadline();
/**
* @notice invalid max fee
*/
error InvalidMaxFee();
/**
* @notice invalid fee
*/
error InvalidFee();
/**
* @notice invalid fee recipient
*/
error InvalidFeeRecipient();
/**
* @notice invalid distributor
*/
error InvalidDistributor();
/**
* @notice invalid briber
*/
error InvalidBriber();
/**
* @notice address does not have DEPOSITOR_ROLE
*/
error NotDepositor();
/**
* @notice no array given
*/
error InvalidArray();
/**
* @notice invalid reward identifier
*/
error InvalidRewardIdentifier();
/**
* @notice bribe has already been transferred
*/
error BribeAlreadyTransferred();
/**
* @notice distribution does not exist
*/
error InvalidDistribution();
/**
* @notice invalid merkle root
*/
error InvalidMerkleRoot();
/**
* @notice token is address(0)
*/
error InvalidToken();
/**
* @notice claim does not exist
*/
error InvalidClaim();
/**
* @notice reward is not yet active for claiming
*/
error RewardInactive();
/**
* @notice timer duration is invalid
*/
error InvalidTimerDuration();
/**
* @notice merkle proof is invalid
*/
error InvalidProof();
/**
* @notice ETH transfer failed
*/
error ETHTransferFailed();
/**
* @notice Invalid operator address
*/
error InvalidOperator();
/**
* @notice call to TokenTransferProxy contract
*/
error TokenTransferProxyCall();
/**
* @notice calling TransferFrom
*/
error TransferFromCall();
/**
* @notice external call failed
*/
error ExternalCallFailure();
/**
* @notice returned tokens too few
*/
error InsufficientReturn();
/**
* @notice swapDeadline expired
*/
error DeadlineBreach();
/**
* @notice expected tokens returned are 0
*/
error ZeroExpectedReturns();
/**
* @notice arrays in SwapData.exchangeData have wrong lengths
*/
error ExchangeDataArrayMismatch();
}{
"optimizer": {
"enabled": true,
"runs": 200,
"details": {
"yulDetails": {
"optimizerSteps": "u"
}
}
},
"viaIR": true,
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[],"name":"AlreadyInitialized","type":"error"},{"inputs":[],"name":"DeadlinePassed","type":"error"},{"inputs":[],"name":"InvalidAddress","type":"error"},{"inputs":[],"name":"InvalidAmount","type":"error"},{"inputs":[],"name":"InvalidChoiceCount","type":"error"},{"inputs":[],"name":"InvalidDeadline","type":"error"},{"inputs":[],"name":"InvalidIdentifier","type":"error"},{"inputs":[],"name":"InvalidMaxPeriod","type":"error"},{"inputs":[],"name":"InvalidPeriod","type":"error"},{"inputs":[],"name":"InvalidPeriodDuration","type":"error"},{"inputs":[],"name":"InvalidProtocol","type":"error"},{"inputs":[],"name":"NoWhitelistBribeVault","type":"error"},{"inputs":[],"name":"NotAuthorized","type":"error"},{"inputs":[],"name":"NotTeamMember","type":"error"},{"inputs":[],"name":"TokenNotWhitelisted","type":"error"},{"inputs":[],"name":"TokenWhitelisted","type":"error"},{"inputs":[],"name":"VoterBlacklisted","type":"error"},{"inputs":[],"name":"VoterNotBlacklisted","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"voters","type":"address[]"}],"name":"AddBlacklistedVoters","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"tokens","type":"address[]"}],"name":"AddWhitelistedTokens","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"teamMember","type":"address"}],"name":"GrantTeamRole","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"bribeVault","type":"address"},{"indexed":false,"internalType":"address","name":"admin","type":"address"},{"indexed":false,"internalType":"string","name":"protocol","type":"string"},{"indexed":false,"internalType":"uint256","name":"maxPeriods","type":"uint256"},{"indexed":false,"internalType":"uint256","name":"periodDuration","type":"uint256"}],"name":"Initialize","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"voters","type":"address[]"}],"name":"RemoveBlacklistedVoters","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address[]","name":"tokens","type":"address[]"}],"name":"RemoveWhitelistedTokens","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"teamMember","type":"address"}],"name":"RevokeTeamRole","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"maxPeriods","type":"uint256"}],"name":"SetMaxPeriods","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"periodDuration","type":"uint256"}],"name":"SetPeriodDuration","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32[]","name":"proposals","type":"bytes32[]"},{"indexed":true,"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"SetProposals","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"bytes32[]","name":"proposals","type":"bytes32[]"},{"indexed":true,"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"SetProposalsByAddress","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint256","name":"proposalIndex","type":"uint256"},{"indexed":false,"internalType":"bytes32[]","name":"proposals","type":"bytes32[]"},{"indexed":true,"internalType":"uint256","name":"deadline","type":"uint256"}],"name":"SetProposalsById","type":"event"},{"inputs":[],"name":"BRIBE_VAULT","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_PERIODS","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MAX_PERIOD_DURATION","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PROTOCOL","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"TEAM_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"_voters","type":"address[]"}],"name":"addBlacklistedVoters","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_tokens","type":"address[]"}],"name":"addWhitelistedTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_proposal","type":"bytes32"},{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_maxTokensPerVote","type":"uint256"},{"internalType":"uint256","name":"_periods","type":"uint256"}],"name":"depositBribe","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_proposal","type":"bytes32"},{"internalType":"address","name":"_token","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"},{"internalType":"uint256","name":"_maxTokensPerVote","type":"uint256"},{"internalType":"uint256","name":"_periods","type":"uint256"},{"internalType":"uint256","name":"_permitDeadline","type":"uint256"},{"internalType":"bytes","name":"_signature","type":"bytes"}],"name":"depositBribeWithPermit","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"getBlacklistedVoters","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"_proposal","type":"bytes32"},{"internalType":"uint256","name":"_proposalDeadline","type":"uint256"},{"internalType":"address","name":"_token","type":"address"}],"name":"getBribe","outputs":[{"internalType":"address","name":"bribeToken","type":"address"},{"internalType":"uint256","name":"bribeAmount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"getWhitelistedTokens","outputs":[{"internalType":"address[]","name":"","type":"address[]"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_teamMember","type":"address"}],"name":"grantTeamRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"indexOfBlacklistedVoter","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"indexOfWhitelistedToken","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_bribeVault","type":"address"},{"internalType":"address","name":"_admin","type":"address"},{"internalType":"string","name":"_protocol","type":"string"},{"internalType":"uint256","name":"_maxPeriods","type":"uint256"},{"internalType":"uint256","name":"_periodDuration","type":"uint256"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_voter","type":"address"}],"name":"isBlacklistedVoter","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"isWhitelistedToken","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"maxPeriods","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"periodDuration","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"proposalDeadlines","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address[]","name":"_voters","type":"address[]"}],"name":"removeBlacklistedVoters","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_tokens","type":"address[]"}],"name":"removeWhitelistedTokens","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_teamMember","type":"address"}],"name":"revokeTeamRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_periods","type":"uint256"}],"name":"setMaxPeriods","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_periodDuration","type":"uint256"}],"name":"setPeriodDuration","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes[]","name":"_identifiers","type":"bytes[]"},{"internalType":"uint256","name":"_deadline","type":"uint256"}],"name":"setProposals","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address[]","name":"_addresses","type":"address[]"},{"internalType":"uint256","name":"_deadline","type":"uint256"}],"name":"setProposalsByAddress","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_proposalIndex","type":"uint256"},{"internalType":"uint256","name":"_choiceCount","type":"uint256"},{"internalType":"uint256","name":"_deadline","type":"uint256"}],"name":"setProposalsById","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes4","name":"interfaceId","type":"bytes4"}],"name":"supportsInterface","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}]Contract Creation Code
60806040523462000027575b620000156200003d565b6040516130b76200009782396130b790f35b6200003162000037565b6200000b565b50600080fd5b6200004762000080565b565b6200005962000059620000599290565b90565b62000059600162000049565b9062000059620000596200007c9262000049565b9055565b620000476200008e6200005c565b60016200006856fe60806040526004361015610018575b6100166107f9565b005b60003560e01c806301ffc9a7146107cf5780630a254640146107a5578063114e6e731461077d5780632129831014610753578063248a9ca3146107295780632f2ff15d146107015780632fa4d218146106d757806336568abe146106af57806342a835511461068757806349d5e604146106515780635155bafa146106275780635699fbad146106005780637c2d6e01146105d95780637fb84bed146105af57806384f389a8146105875780638d23507f146105595780638e8efaee1461052f5780638fef58911461050157806391b9b827146104cb57806391d14854146104a05780639970227014610475578063a217fddf1461044b578063ab37f4861461040f578063b0b38baa146103e5578063b470aade146103bb578063bcec454f14610393578063be309bca1461034e578063cd698e6914610326578063d547741f146102fe578063d59551d2146102d6578063da606ce2146102af578063e26f790014610279578063ea24a7681461023e578063ed99c0d114610216578063f52c395a146101ef5763f7e6b46b146101ae5761000e565b346101e2575b6101c86101c2366004610ff7565b91612c11565b906101de6101d560405190565b92839283611035565b0390f35b6101ea6107f9565b6101b4565b5034610209575b6100166102043660046109d9565b6121ad565b6102116107f9565b6101f6565b5034610231575b61001661022b366004610a1a565b91612127565b6102396107f9565b61021d565b503461026c575b6101de61025b6102563660046109d9565b610fe5565b6040515b9182918290815260200190565b6102746107f9565b610245565b50346102a2575b61028b36600461084a565b6101de610296612b80565b60405191829182610f66565b6102aa6107f9565b610280565b50346102c9575b6100166102c4366004610922565b6122bd565b6102d16107f9565b6102b6565b50346102f1575b6100166102eb366004610fa7565b91611f97565b6102f96107f9565b6102dd565b5034610319575b6100166103133660046109a8565b90611257565b6103216107f9565b610305565b5034610341575b61001661033b3660046108c8565b9061263d565b6103496107f9565b61032d565b5034610386575b61036036600461084a565b6101de61036b610f9b565b6040515b918291826001600160a01b03909116815260200190565b61038e6107f9565b610355565b50346103ae575b6100166103a83660046108c8565b906127f5565b6103b66107f9565b61039a565b50346103d8575b6103cd36600461084a565b6101de61025b610f77565b6103e06107f9565b6103c2565b5034610402575b6103f736600461084a565b6101de610296612b8a565b61040a6107f9565b6103ec565b503461043e575b6101de61042c6104273660046109d9565b612cdb565b60405191829182901515815260200190565b6104466107f9565b610416565b5034610468575b61045d36600461084a565b6101de61025b610eff565b6104706107f9565b610452565b5034610493575b61001661048a366004610ea4565b93929092612a32565b61049b6107f9565b61047c565b50346104be575b6101de61042c6104b83660046109a8565b906110a5565b6104c66107f9565b6104a7565b50346104f4575b6104dd36600461084a565b6101de6104e8610e28565b60405191829182610e93565b6104fc6107f9565b6104d2565b5034610522575b610016610516366004610c71565b95949094939193612af4565b61052a6107f9565b610508565b503461054c575b6101de61025b6105473660046109d9565b610b60565b6105546107f9565b610536565b503461057a575b61001661056e366004610ab4565b94939093929192611af7565b6105826107f9565b610560565b50346105a2575b61001661059c366004610a1a565b91611e26565b6105aa6107f9565b61058e565b50346105cc575b6105c136600461084a565b6101de61025b610a12565b6105d46107f9565b6105b6565b50346105f3575b6100166105ee366004610922565b612342565b6105fb6107f9565b6105e0565b503461061a575b6100166106153660046109d9565b612238565b6106226107f9565b610607565b5034610644575b61063936600461084a565b6101de61025b6109fa565b61064c6107f9565b61062e565b503461067a575b61066336600461084a565b6101de60008051602061305483398151915261025b565b6106826107f9565b610658565b50346106a2575b61001661069c3660046108c8565b906129d9565b6106aa6107f9565b61068e565b50346106ca575b6100166106c43660046109a8565b906112c6565b6106d26107f9565b6106b6565b50346106f4575b6101de61042c6106ef3660046109d9565b612d56565b6106fc6107f9565b6106de565b503461071c575b6100166107163660046109a8565b90611114565b6107246107f9565b610708565b5034610746575b6101de61025b610741366004610922565b6110d5565b61074e6107f9565b610730565b5034610770575b6101de61025b61076b366004610922565b610969565b6107786107f9565b61075a565b5034610798575b6100166107923660046108c8565b906128e7565b6107a06107f9565b610784565b50346107c2575b6107b736600461084a565b6101de61025b610874565b6107ca6107f9565b6107ac565b50346107ec575b6101de61042c6107e7366004610822565b611056565b6107f46107f9565b6107d6565b50600080fd5b6001600160e01b031981165b14156107f957565b90503590610820826107ff565b565b906108369160208183031261083957610813565b90565b6108416107f9565b610813565b9052565b600091031261085557565b6108206107f9565b6108366108366108369290565b610836600a61085d565b61083661086a565b909182601f830112156108bb575b602082359267ffffffffffffffff84116108ae575b01926020830284011161085557565b6108b66107f9565b61089f565b6108c36107f9565b61088a565b906108f191602081830312610902575b80359067ffffffffffffffff82116108f5575b0161087c565b9091565b6108fd6107f9565b6108eb565b61090a6107f9565b6108d8565b8061080b565b905035906108208261090f565b906108369160208183031261093657610915565b61093e6107f9565b610915565b905b600052602052604060002090565b610836916008021c81565b906108369154610953565b6108369061097b600891600092610943565b61095e565b6001600160a01b031690565b6001600160a01b03811661080b565b905035906108208261098c565b9190610836906040848203126109cc575b6109c38185610915565b9360200161099b565b6109d46107f9565b6109b9565b90610836916020818303126109ed5761099b565b6109f56107f9565b61099b565b6108366000600461095e565b61083662278d0061085d565b610836610a06565b91604083830312610a5e575b610836610a4683853567ffffffffffffffff8111610a51575b860161087c565b939094602001610915565b610a596107f9565b610a3f565b610a666107f9565b610a26565b909182601f83011215610aa7575b602082359267ffffffffffffffff8411610a9a575b01928284011161085557565b610aa26107f9565b610a8e565b610aaf6107f9565b610a79565b919060a083820312610b23575b610836610ace828561099b565b93610adc836020830161099b565b93610afd84604084013567ffffffffffffffff8111610b16575b8401610a6b565b939094610b0d8160608601610915565b93608001610915565b610b1e6107f9565b610af6565b610b2b6107f9565b610ac1565b61083690610980906001600160a01b031682565b61083690610b30565b61083690610b44565b9061094590610b4d565b6108369061097b600991600092610b56565b601f01601f191690565b50634e487b7160e01b600052604160045260246000fd5b90601f01601f1916810190811067ffffffffffffffff821117610bb557604052565b610bbd610b7c565b604052565b90610820610bcf60405190565b9283610b93565b610bf560209167ffffffffffffffff8111610bf957601f01601f191690565b0190565b610b72610b7c565b90826000939282370152565b92919061082091610c25610c2083610bd6565b610bc2565b94828652602086019183820111610c3b57610c01565b610c436107f9565b610c01565b906108369181601f82011215610c64575b602081359101610c0d565b610c6c6107f9565b610c59565b60e081830312610cf9575b610c868282610915565b92610c94836020840161099b565b92610ca28160408501610915565b92610cb08260608301610915565b92610836610cc18460808501610915565b93610ccf8160a08601610915565b9360c08101359067ffffffffffffffff8211610cec575b01610c48565b610cf46107f9565b610ce6565b610d016107f9565b610c7c565b50634e487b7160e01b600052600060045260246000fd5b50634e487b7160e01b600052602260045260246000fd5b9060016002830492168015610d57575b6020831014610d4f57565b610820610d1d565b91607f1691610d44565b80546000939291610d7e610d7483610d34565b8085529360200190565b9160018116908115610dd05750600114610d9757505050565b610daa9192939450600052602060002090565b916000925b818410610dbc5750500190565b805484840152602090930192600101610daf565b60ff191683525050602001925050565b9061083691610d61565b90610820610e0492610dfb60405190565b93848092610de0565b0383610b93565b60006108369211610e1b57610dea565b610e23610d06565b610dea565b61083660006002610e0b565b918091926000905b828210610e54575011610e4d575050565b6000910152565b91508060209183015181860152018291610e3c565b610e8a610b72602093610bf593610e7e815190565b80835293849260200190565b95869101610e34565b602080825261083692910190610e69565b919060a083820312610ee8575b610ebb8184610915565b92610ec9826020830161099b565b92610836610eda8460408501610915565b93610b0d8160608601610915565b610ef06107f9565b610eb1565b610836600061085d565b610836610ef5565b90610f27610f20610f16845190565b8084529260200190565b9260200190565b9060005b818110610f385750505090565b909192610f5e610f5760019286516001600160a01b0316815260200190565b9460200190565b929101610f2b565b602080825261083692910190610f07565b6108366000600561095e565b610836916008021c610980565b906108369154610f83565b61083660006003610f90565b9091606082840312610fd8575b610836610fc18484610915565b93610fcf8160208601610915565b93604001610915565b610fe06107f9565b610fb4565b6108369061097b600a91600092610b56565b9091606082840312611028575b6108366110118484610915565b9361101f8160208601610915565b9360400161099b565b6110306107f9565b611004565b6001600160a01b0390911681526040810192916108209160200152565b0152565b637965db0b60e01b6001600160e01b0319821614908115611075575090565b61083691506001600160e01b0319166301ffc9a760e01b1490565b610836905b60ff1690565b6108369054611090565b610836916110bf916110b960009182610943565b01610b56565b61109b565b6108369081565b61083690546110c4565b60016110ee610836926110e6600090565b506000610943565b016110cb565b906108209161110a611105826110d5565b61111e565b9061082091611316565b90610820916110f4565b6108209033906111ae565b6108369061085d565b610bf561114a92602092611144815190565b94859290565b93849101610e34565b611191610836939261118b61118b937f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000815260170190565b90611132565b7001034b99036b4b9b9b4b733903937b6329607d1b815260110190565b906111c06111bc82846110a5565b1590565b6111c8575050565b6112389250906108366111e66111e0611220946116a2565b92611129565b6111fb6020916111f58361085d565b90611542565b9261121461120860405190565b94859384019283611153565b90810382520382610b93565b60405162461bcd60e51b815291829160048301610e93565b0390fd5b906108209161124d611105826110d5565b906108209161138c565b906108209161123c565b1561126857565b5060405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b6064820152608490fd5b61082091906112e76112d733610980565b6001600160a01b03841614611261565b61138c565b9060ff905b9181191691161790565b9061130b61083661131292151590565b82546112ec565b9055565b906113246111bc82846110a5565b61132c575050565b61134660016113418360006110b98782610943565b6112fb565b339061137c6113766113767f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d9590565b92610b4d565b9261138660405190565b600090a4565b9061139781836110a5565b61139f575050565b6113b3600061134183826110b98782610943565b339061137c6113766113767ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9590565b50634e487b7160e01b600052601160045260246000fd5b90611404565b9190565b908060001904821181151516611418570290565b6114206113e3565b0290565b81198111611430570190565b610bf56113e3565b90611445610c2083610bd6565b918252565b369037565b9061082061146561145f84611438565b93610bd6565b601f19016020840161144a565b50634e487b7160e01b600052603260045260246000fd5b906001602091611497845190565b8110156114a5575b02010190565b6114ad611472565b61149f565b60019080156114bf570390565b6114c76113e3565b0390565b6110956108366108369290565b610836906114ec6114006108369460ff1690565b901c90565b156114f857565b5060405162461bcd60e51b815280611238600482016020808252818101527f537472696e67733a20686578206c656e67746820696e73756666696369656e74604082015260600190565b919060029061157361156e61155f8361155a8661085d565b6113fa565b6115688561085d565b90611424565b61144f565b91600091603061158b6115858561085d565b86611489565b536115c36115ba600f60fb1b9261155a6001958695881a6115b46115ae8861085d565b8b611489565b5361085d565b6115688361085d565b915b6115e6575b505061083692936115e06114006108369361085d565b146114f1565b90946115f18261085d565b8611156116705761165d611657839261163a61161d6f181899199a1a9b1b9c1cb0b131b232b360811b90565b611627600f61085d565b83166010811015611663575b1a60f81b90565b861a6116468a89611489565b5361165160046114cb565b906114d8565b966114b2565b916115c5565b61166b611472565b611633565b946115ca565b6108369081906001600160a01b031681565b61083660146114cb565b6108366108366108369260ff1690565b6116bf6116ba610836926116b4606090565b50610b44565b611676565b6111f56116ca611688565b611692565b94939291906116de600b61109b565b6116f7576116eb9561196d565b6108206001600b6112fb565b5050505050505061170760405190565b62dc149f60e41b8152600490fd5b6109806108366108369290565b61083690611715565b906001600160a01b03906112f1565b9061174a61083661131292610b4d565b825461172b565b9160001960089290920291821b911b6112f1565b91906117766108366113129361085d565b908354611751565b61082091600091611765565b818110611795575050565b806117a3600060019361177e565b0161178a565b9190601f81116117b857505050565b6117ca61082093600052602060002090565b906020601f8401819004830193106117ec575b6020601f90910104019061178a565b90915081906117dd565b919067ffffffffffffffff82116118c1575b61181c826118168554610d34565b856117a9565b600090601f83116001146118575761131292916000918361184c575b5050600019600883021c1916906002021790565b013590503880611838565b601f1983169161186c85600052602060002090565b92815b8181106118a957509160029391856001969410611890575b50505002019055565b0135600019601f84166008021c19169055388080611887565b9193602060018192878701358155019501920161186f565b6118c9610b7c565b611808565b9061082092916117f6565b90600019906112f1565b906118f36108366113129261085d565b82546118d9565b9190610b728161191181610bf59560209181520190565b8095610c01565b9161105291610820969897956080956119586119659461194860a089019560008a01906001600160a01b03169052565b6001600160a01b03166020880152565b85830360408701526118fa565b966060830152565b9291949093600061198061098082611722565b6001600160a01b03861614611ad7578361199a565b905090565b6119a66114008361085d565b14611ab7576119b48161085d565b82148015611aa4575b611a84576119ca9061085d565b82148015611a71575b611a5257611a4d926119e685600361173a565b6119f2818860026118ce565b6119fd8260046118e3565b611a088360056118e3565b611a1986611a14610ef5565b611316565b7fa80caddab9a93c4df4f67cd3ee3490472325e6903e29687fc5904cef451041f996611a4460405190565b96879687611918565b0390a1565b50505050505050611a6260405190565b634f08daf360e11b8152600490fd5b50611a7d610836610a06565b82116119d3565b5050505050505050611a9560405190565b63c17d8a0360e01b8152600490fd5b50611ab061083661086a565b82116119bd565b5050505050505050611ac860405190565b6301fc71f560e21b8152600490fd5b5050505050505050611ae860405190565b63e6c4247b60e01b8152600490fd5b9061082095949392916116cf565b9190611b0f610ef5565b611b1d6111bc3380936110a5565b9081611b4e575b50611b325761082092611cb6565b50505050611b3f60405190565b63ea8e4eb560e01b8152600490fd5b611b6b91506111bc906000805160206130548339815191526110a5565b38611b24565b6020809167ffffffffffffffff8111611b8957020190565b611b91610b7c565b020190565b90611445610c2083611b71565b90610820611465611bb384611b96565b93611b71565b903590601e193682900301821215611bfd575b01602081359167ffffffffffffffff8311611bf0575b019136829003831361085557565b611bf86107f9565b611be2565b611c056107f9565b611bcc565b906108f192602091811015611c23575b02810190611bb9565b611c2b611472565b611c1a565b9091610bf59083908093610c01565b909161083692611c30565b9060208091611497845190565b6001906000198114611430570190565b90611c76610f20610f16845190565b9060005b818110611c875750505090565b909192611c9d610f576001928651815260200190565b929101611c7a565b602080825261083692910190611c67565b929181926000611cc58161085d565b8514611e1757428310611df957611cdb85611ba3565b9160009560015b15611d9f575b8296611cf861199582898c611c0a565b611d046114008661085d565b14611d7e5780611d59611214611d39611d21611d78958c8f611c0a565b90611d2b60405190565b938492602084019283611c3f565b611d4b611d44825190565b9160200190565b20611d568389611c4a565b52565b611d7387611d6e611d6a848a611c4a565b5190565b613044565b611c57565b96611ce2565b505050505050505050611d9060405190565b63eb48439160e01b8152600490fd5b80871015611dac57611ce8565b5095505092509050611df4611de17f8c852cad34f901531c4a1328ddfefbc6152fbd45aa7eb38890e74f351d8493a69261085d565b92611deb60405190565b91829182611ca5565b0390a2565b505050505050611e0860405190565b631da7447960e21b8152600490fd5b505050505050611ae860405190565b906108209291611b05565b9190611e3b610ef5565b611e496111bc3380936110a5565b9081611e5e575b50611b325761082092611e87565b611e7b91506111bc906000805160206130548339815191526110a5565b38611e50565b01918252565b9190916000611e958161085d565b8414611f7a57428310611f6c57611eab84611ba3565b9460009460015b15611f15575b611f0f8396611efe611ec960405190565b611ee88160208101611214868c83602081611e81610bf5938396959052565b611ef3611d44825190565b20611d56838c611c4a565b611d7387611d6e611d6a848d611c4a565b95611eb2565b80861015611f2257611eb8565b5094935050611f67611f5d611f577fc3c3780ed921778d05400bdfaf133352f1c8ce56e4ce47391118f53a22103cce9361085d565b9361085d565b93611deb60405190565b0390a3565b5050505050611e0860405190565b5050505050611f8860405190565b633d25757960e01b8152600490fd5b906108209291611e31565b9190611fac610ef5565b611fba6111bc3380936110a5565b9081611fcf575b50611b325761082092612033565b611fec91506111bc906000805160206130548339815191526110a5565b38611fc1565b9160209181101561200257020190565b611b91611472565b356108368161098c565b610846906001600160a01b031660601b90565b610bf581601493612014565b909291839260006120438161085d565b8514611e1757428310611df95761205985611ba3565b9160009560015b156120e5575b829661207b612076828b8a611ff2565b61200a565b61209761208a61098087611722565b916001600160a01b031690565b146120d35780611d596120b16120766120cd948d8c611ff2565b611d396120bd60405190565b8092611214602083019182612027565b96612060565b505050505050505050611ae860405190565b808710156120f257612066565b5095505092509050611df4611de17fa9411f55f4ccd3f63f1f6236481c2f6b385a4221287184e89ca4c40792f8224e9261085d565b906108209291611fa2565b61082090612141611105610ef5565b61214e6109806000611722565b6001600160a01b038216146121a35761217581600080516020613054833981519152611316565b611a4d7fd36b0989e598a1b05388150a9a8c84925e2710d91910406b8735e01f3ed028179161036f60405190565b5050604051611ae8565b61082090612132565b610820906121c5611105610ef5565b6000805160206130548339815191526121e16111bc83836110a5565b61221d57816121ef9161138c565b611a4d7f708bd40f8f4d2ad60032caea0582161d35c50177cc0b2c575b5d483bd2902caa9161036f60405190565b50505061222960405190565b632793ed7d60e01b8152600490fd5b610820906121b6565b61082090612250611105610ef5565b61225a600061085d565b811480156122aa575b6122a0576122728160046118e3565b611a4d7fbff777c073bd9101dd1e419471fe91c54c9ffe380882bca8eb1fcf75d6086f779161025f60405190565b5050604051611a95565b506122b661083661086a565b8111612263565b61082090612241565b610820906122d5611105610ef5565b6122df600061085d565b8114801561232f575b612325576122f78160056118e3565b611a4d7f7d7455c70e1855cfeb6ff84fe7b6d37efcfdaee91c05f2e25a55368f50ba7b5a9161025f60405190565b5050604051611a62565b5061233b610836610a06565b81116122e8565b610820906122c6565b90612354610ef5565b6123626111bc3380936110a5565b9081612383575b5061237757610820916124e1565b505050611b3f60405190565b6123a091506111bc906000805160206130548339815191526110a5565b38612369565b61083690610980565b61083690546123a6565b6123d96001916123c7815490565b8410156123e257600052602060002090565b91020190600090565b6123ea611472565b600052602060002090565b916001600160a01b0360089290920291821b911b6112f1565b919061241f61083661131293610b4d565b9083546123f5565b9061244f6108209280549068010000000000000000821015612455575b6001820181556123b9565b9061240e565b61245d610b7c565b612444565b8181106114bf570390565b5061083690602081019061099b565b818352602090920191906000825b828210612498575050505090565b909192936124c76124c06001926124af888661246d565b6001600160a01b0316815260200190565b9560200190565b9392019061248a565b60208082526108369391019161247c565b909190829160005b835b81101561260157612500612076828786611ff2565b61251061208a6109806000611722565b146125f357612523612076828786611ff2565b61253361208a61098060036123af565b146125d657612549610427612076838887611ff2565b6125b9576124eb906125b2906125ac61258e61257e600661257a89612574612076888f865b94611ff2565b90612427565b5490565b612588600161085d565b90612462565b6125a760096125a1612076868d8c611ff2565b90610b56565b6118e3565b60010190565b90506124e9565b50505050506125c760405190565b63241d2edf60e01b8152600490fd5b50505050506125e460405190565b63a122bf3960e01b8152600490fd5b5050505050611ae860405190565b50929091507fe7e9e18eae0a1664f98ba7e59eda81692d5802c7e9bd75bb0261f3fc6fd4a49391611a4d61263460405190565b928392836124d0565b906108209161234b565b90612650610ef5565b61265e6111bc3380936110a5565b9081612673575b5061237757610820916126ef565b61269091506111bc906000805160206130548339815191526110a5565b38612665565b50634e487b7160e01b600052603160045260246000fd5b6108209160009161240e565b60016126c3825490565b80156126e2575b03906126df6126d983836123b9565b906126ad565b55565b6126ea612696565b6126ca565b909190829160005b835b8110156127c2576127146111bc610427612076848988611ff2565b6127a55761279e816125ac61279961275461083660006127948a6125a16120768f9b6126f99c60099461278f61275f61275a612754612076878787611ff2565b89610b56565b6110cb565b6125a78160069d8e61244f61278761278161277b61257e855490565b846123b9565b90610f90565b9384926123b9565b611ff2565b61177e565b6126b9565b90506126f7565b50505050506127b360405190565b6307c241ad60e51b8152600490fd5b50929091507fc18397a78d98d67911be09b9c32315c4b8db0454529f84f856e61f537494cbfc91611a4d61263460405190565b9061082091612647565b906108209161280f611105610ef5565b909190829160005b835b8110156128b45761282e612076828786611ff2565b61283e61208a6109806000611722565b146125f3576128546106ef612076838887611ff2565b6128975761281990612890906125ac61287d61257e600761257a89612574612076888f8661256e565b6125a7600a6125a1612076868d8c611ff2565b9050612817565b50505050506128a560405190565b6336650e8f60e11b8152600490fd5b50929091507f8ff2887f41c4af26bbcadf0889537a4641e2d1d6d9fa287feaf683a76096efd891611a4d61263460405190565b90610820916127ff565b9061082091612901611105610ef5565b909190829160005b835b8110156129a6576129266111bc6106ef612076848988611ff2565b61298957612982816125ac61279961275461083660006127948a6125a16120768f9b61290b9c600a9461278f61296661275a612754612076878787611ff2565b6125a78160079d8e61244f61278761278161277b61257e855490565b9050612909565b505050505061299760405190565b637463712b60e01b8152600490fd5b50929091507fa520ff964bc029411023e3f0e20bf29e54c023e5e23b0e28d0de3ae5d4231a9e91611a4d61263460405190565b90610820916128f1565b906129f8949392916129f3612a96565b612a12565b610820612ac8565b6108366000611438565b610836612a00565b92610820949192612a23600061085d565b93612a2c612a0a565b95612e44565b90610820949392916129e3565b610836600261085d565b15612a5057565b5060405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606490fd5b610820612aa360016110cb565b612ab7612aae612a3f565b91821415612a49565b60016118e3565b610836600161085d565b610820612ab7612abe565b906129f8969594939291612ae5612a96565b90610820969594939291612e44565b90610820969594939291612ad3565b90612b1e612b12610f16845490565b92600052602060002090565b9060005b818110612b2f5750505090565b909192612b4b612b446001926124af876123af565b9460010190565b929101612b22565b9061083691612b03565b90610820610e0492612b6e60405190565b93848092612b53565b61083690612b5d565b6108366006612b77565b6108366007612b77565b92612bb16020610bf594611e81601488611e81829b9a8699612014565b018092612014565b905051906108208261098c565b905051906108208261090f565b919061083690604084820312612bf7575b612bee8185612bb9565b93602001612bc6565b612bff6107f9565b612be4565b506040513d6000823e3d90fd5b91612c9992612c8b604093612c24600090565b50612c68612c3d612c38612c3860036123af565b610b4d565b93632c4ef0d595611214612c5030610b4d565b91612c5a60405190565b958694602086019485612b94565b612c73611d44825190565b2092612c7e60405190565b9586948593849360e01b90565b835260048301526024820190565b03915afa908115612cce575b600080919092612cb457509091565b90506108f19150612cc53d82610b93565b3d810190612bd3565b612cd6612c04565b612ca5565b600690612ce6825490565b600090612cf56114008361085d565b14612d5057612d0861275a836009610b56565b612d146114008361085d565b1415928315612d24575b50505090565b612d4792935061278161208a92612d3a926123b9565b926001600160a01b031690565b14388080612d1e565b91505090565b600790612d61825490565b600090612d706114008361085d565b14612d5057612d0861275a83600a610b56565b610836610140610bc2565b805182526020808201516001600160a01b03169083015261083691610140810191610120906040818101516001600160a01b031690840152612dd560608201516060850152565b612de460808201516080850152565b612df360a082015160a0850152565b612e0260c082015160c0850152565b612e1160e082015160e0850152565b612e22610100820151610100850152565b015190610120818403910152610e69565b602080825261083692910190612d8e565b9394959095612e5761275a866008610943565b42811061302357600097612e6a8961085d565b8814801561300e575b612fec57612e836109808a611722565b6001600160a01b03821614612fd957612e9e6111bc82612cdb565b612fc657612eab8961085d565b8514612fa4578897612ebd60036123af565b612ec690610b4d565b612ecf90610b4d565b96635c2a802b9633612ee160056110cb565b94612eea612d83565b9b612ef5908e8e0152565b6001600160a01b031660208c01526001600160a01b031660408b015260608a0152608089015260a088015260c087015260e0860152610100850152610120840152612f6194612f5691833b15612f97575b6040519687958694859360e01b90565b835260048301612e33565b03925af18015612f8a575b612f735750565b61082090612f813d82610b93565b3d81019061084a565b612f92612c04565b612f6c565b612f9f6107f9565b612f46565b50505050505050505050612fb760405190565b63162908e360e11b8152600490fd5b505050505050505050506127b360405190565b50505050505050505050611ae860405190565b50505050505050505050612fff60405190565b6302e8f35960e31b8152600490fd5b5061301c61083660046110cb565b8811612e73565b50505050505050505061303560405190565b63387b2e5560e11b8152600490fd5b906125a761082092600861094356fe5146a08baf902532d0ee2f909971144f12ca32651cd70cbee1117cddfb3b3b33a3646970667358221220929ba7a4e3cca97712cee99b9b10b2031bc193223d3173c44d9103f46c3e55df6c6578706572696d656e74616cf564736f6c634300080c0041
Deployed Bytecode
0x60806040526004361015610018575b6100166107f9565b005b60003560e01c806301ffc9a7146107cf5780630a254640146107a5578063114e6e731461077d5780632129831014610753578063248a9ca3146107295780632f2ff15d146107015780632fa4d218146106d757806336568abe146106af57806342a835511461068757806349d5e604146106515780635155bafa146106275780635699fbad146106005780637c2d6e01146105d95780637fb84bed146105af57806384f389a8146105875780638d23507f146105595780638e8efaee1461052f5780638fef58911461050157806391b9b827146104cb57806391d14854146104a05780639970227014610475578063a217fddf1461044b578063ab37f4861461040f578063b0b38baa146103e5578063b470aade146103bb578063bcec454f14610393578063be309bca1461034e578063cd698e6914610326578063d547741f146102fe578063d59551d2146102d6578063da606ce2146102af578063e26f790014610279578063ea24a7681461023e578063ed99c0d114610216578063f52c395a146101ef5763f7e6b46b146101ae5761000e565b346101e2575b6101c86101c2366004610ff7565b91612c11565b906101de6101d560405190565b92839283611035565b0390f35b6101ea6107f9565b6101b4565b5034610209575b6100166102043660046109d9565b6121ad565b6102116107f9565b6101f6565b5034610231575b61001661022b366004610a1a565b91612127565b6102396107f9565b61021d565b503461026c575b6101de61025b6102563660046109d9565b610fe5565b6040515b9182918290815260200190565b6102746107f9565b610245565b50346102a2575b61028b36600461084a565b6101de610296612b80565b60405191829182610f66565b6102aa6107f9565b610280565b50346102c9575b6100166102c4366004610922565b6122bd565b6102d16107f9565b6102b6565b50346102f1575b6100166102eb366004610fa7565b91611f97565b6102f96107f9565b6102dd565b5034610319575b6100166103133660046109a8565b90611257565b6103216107f9565b610305565b5034610341575b61001661033b3660046108c8565b9061263d565b6103496107f9565b61032d565b5034610386575b61036036600461084a565b6101de61036b610f9b565b6040515b918291826001600160a01b03909116815260200190565b61038e6107f9565b610355565b50346103ae575b6100166103a83660046108c8565b906127f5565b6103b66107f9565b61039a565b50346103d8575b6103cd36600461084a565b6101de61025b610f77565b6103e06107f9565b6103c2565b5034610402575b6103f736600461084a565b6101de610296612b8a565b61040a6107f9565b6103ec565b503461043e575b6101de61042c6104273660046109d9565b612cdb565b60405191829182901515815260200190565b6104466107f9565b610416565b5034610468575b61045d36600461084a565b6101de61025b610eff565b6104706107f9565b610452565b5034610493575b61001661048a366004610ea4565b93929092612a32565b61049b6107f9565b61047c565b50346104be575b6101de61042c6104b83660046109a8565b906110a5565b6104c66107f9565b6104a7565b50346104f4575b6104dd36600461084a565b6101de6104e8610e28565b60405191829182610e93565b6104fc6107f9565b6104d2565b5034610522575b610016610516366004610c71565b95949094939193612af4565b61052a6107f9565b610508565b503461054c575b6101de61025b6105473660046109d9565b610b60565b6105546107f9565b610536565b503461057a575b61001661056e366004610ab4565b94939093929192611af7565b6105826107f9565b610560565b50346105a2575b61001661059c366004610a1a565b91611e26565b6105aa6107f9565b61058e565b50346105cc575b6105c136600461084a565b6101de61025b610a12565b6105d46107f9565b6105b6565b50346105f3575b6100166105ee366004610922565b612342565b6105fb6107f9565b6105e0565b503461061a575b6100166106153660046109d9565b612238565b6106226107f9565b610607565b5034610644575b61063936600461084a565b6101de61025b6109fa565b61064c6107f9565b61062e565b503461067a575b61066336600461084a565b6101de60008051602061305483398151915261025b565b6106826107f9565b610658565b50346106a2575b61001661069c3660046108c8565b906129d9565b6106aa6107f9565b61068e565b50346106ca575b6100166106c43660046109a8565b906112c6565b6106d26107f9565b6106b6565b50346106f4575b6101de61042c6106ef3660046109d9565b612d56565b6106fc6107f9565b6106de565b503461071c575b6100166107163660046109a8565b90611114565b6107246107f9565b610708565b5034610746575b6101de61025b610741366004610922565b6110d5565b61074e6107f9565b610730565b5034610770575b6101de61025b61076b366004610922565b610969565b6107786107f9565b61075a565b5034610798575b6100166107923660046108c8565b906128e7565b6107a06107f9565b610784565b50346107c2575b6107b736600461084a565b6101de61025b610874565b6107ca6107f9565b6107ac565b50346107ec575b6101de61042c6107e7366004610822565b611056565b6107f46107f9565b6107d6565b50600080fd5b6001600160e01b031981165b14156107f957565b90503590610820826107ff565b565b906108369160208183031261083957610813565b90565b6108416107f9565b610813565b9052565b600091031261085557565b6108206107f9565b6108366108366108369290565b610836600a61085d565b61083661086a565b909182601f830112156108bb575b602082359267ffffffffffffffff84116108ae575b01926020830284011161085557565b6108b66107f9565b61089f565b6108c36107f9565b61088a565b906108f191602081830312610902575b80359067ffffffffffffffff82116108f5575b0161087c565b9091565b6108fd6107f9565b6108eb565b61090a6107f9565b6108d8565b8061080b565b905035906108208261090f565b906108369160208183031261093657610915565b61093e6107f9565b610915565b905b600052602052604060002090565b610836916008021c81565b906108369154610953565b6108369061097b600891600092610943565b61095e565b6001600160a01b031690565b6001600160a01b03811661080b565b905035906108208261098c565b9190610836906040848203126109cc575b6109c38185610915565b9360200161099b565b6109d46107f9565b6109b9565b90610836916020818303126109ed5761099b565b6109f56107f9565b61099b565b6108366000600461095e565b61083662278d0061085d565b610836610a06565b91604083830312610a5e575b610836610a4683853567ffffffffffffffff8111610a51575b860161087c565b939094602001610915565b610a596107f9565b610a3f565b610a666107f9565b610a26565b909182601f83011215610aa7575b602082359267ffffffffffffffff8411610a9a575b01928284011161085557565b610aa26107f9565b610a8e565b610aaf6107f9565b610a79565b919060a083820312610b23575b610836610ace828561099b565b93610adc836020830161099b565b93610afd84604084013567ffffffffffffffff8111610b16575b8401610a6b565b939094610b0d8160608601610915565b93608001610915565b610b1e6107f9565b610af6565b610b2b6107f9565b610ac1565b61083690610980906001600160a01b031682565b61083690610b30565b61083690610b44565b9061094590610b4d565b6108369061097b600991600092610b56565b601f01601f191690565b50634e487b7160e01b600052604160045260246000fd5b90601f01601f1916810190811067ffffffffffffffff821117610bb557604052565b610bbd610b7c565b604052565b90610820610bcf60405190565b9283610b93565b610bf560209167ffffffffffffffff8111610bf957601f01601f191690565b0190565b610b72610b7c565b90826000939282370152565b92919061082091610c25610c2083610bd6565b610bc2565b94828652602086019183820111610c3b57610c01565b610c436107f9565b610c01565b906108369181601f82011215610c64575b602081359101610c0d565b610c6c6107f9565b610c59565b60e081830312610cf9575b610c868282610915565b92610c94836020840161099b565b92610ca28160408501610915565b92610cb08260608301610915565b92610836610cc18460808501610915565b93610ccf8160a08601610915565b9360c08101359067ffffffffffffffff8211610cec575b01610c48565b610cf46107f9565b610ce6565b610d016107f9565b610c7c565b50634e487b7160e01b600052600060045260246000fd5b50634e487b7160e01b600052602260045260246000fd5b9060016002830492168015610d57575b6020831014610d4f57565b610820610d1d565b91607f1691610d44565b80546000939291610d7e610d7483610d34565b8085529360200190565b9160018116908115610dd05750600114610d9757505050565b610daa9192939450600052602060002090565b916000925b818410610dbc5750500190565b805484840152602090930192600101610daf565b60ff191683525050602001925050565b9061083691610d61565b90610820610e0492610dfb60405190565b93848092610de0565b0383610b93565b60006108369211610e1b57610dea565b610e23610d06565b610dea565b61083660006002610e0b565b918091926000905b828210610e54575011610e4d575050565b6000910152565b91508060209183015181860152018291610e3c565b610e8a610b72602093610bf593610e7e815190565b80835293849260200190565b95869101610e34565b602080825261083692910190610e69565b919060a083820312610ee8575b610ebb8184610915565b92610ec9826020830161099b565b92610836610eda8460408501610915565b93610b0d8160608601610915565b610ef06107f9565b610eb1565b610836600061085d565b610836610ef5565b90610f27610f20610f16845190565b8084529260200190565b9260200190565b9060005b818110610f385750505090565b909192610f5e610f5760019286516001600160a01b0316815260200190565b9460200190565b929101610f2b565b602080825261083692910190610f07565b6108366000600561095e565b610836916008021c610980565b906108369154610f83565b61083660006003610f90565b9091606082840312610fd8575b610836610fc18484610915565b93610fcf8160208601610915565b93604001610915565b610fe06107f9565b610fb4565b6108369061097b600a91600092610b56565b9091606082840312611028575b6108366110118484610915565b9361101f8160208601610915565b9360400161099b565b6110306107f9565b611004565b6001600160a01b0390911681526040810192916108209160200152565b0152565b637965db0b60e01b6001600160e01b0319821614908115611075575090565b61083691506001600160e01b0319166301ffc9a760e01b1490565b610836905b60ff1690565b6108369054611090565b610836916110bf916110b960009182610943565b01610b56565b61109b565b6108369081565b61083690546110c4565b60016110ee610836926110e6600090565b506000610943565b016110cb565b906108209161110a611105826110d5565b61111e565b9061082091611316565b90610820916110f4565b6108209033906111ae565b6108369061085d565b610bf561114a92602092611144815190565b94859290565b93849101610e34565b611191610836939261118b61118b937f416363657373436f6e74726f6c3a206163636f756e7420000000000000000000815260170190565b90611132565b7001034b99036b4b9b9b4b733903937b6329607d1b815260110190565b906111c06111bc82846110a5565b1590565b6111c8575050565b6112389250906108366111e66111e0611220946116a2565b92611129565b6111fb6020916111f58361085d565b90611542565b9261121461120860405190565b94859384019283611153565b90810382520382610b93565b60405162461bcd60e51b815291829160048301610e93565b0390fd5b906108209161124d611105826110d5565b906108209161138c565b906108209161123c565b1561126857565b5060405162461bcd60e51b815260206004820152602f60248201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560448201526e103937b632b9903337b91039b2b63360891b6064820152608490fd5b61082091906112e76112d733610980565b6001600160a01b03841614611261565b61138c565b9060ff905b9181191691161790565b9061130b61083661131292151590565b82546112ec565b9055565b906113246111bc82846110a5565b61132c575050565b61134660016113418360006110b98782610943565b6112fb565b339061137c6113766113767f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d9590565b92610b4d565b9261138660405190565b600090a4565b9061139781836110a5565b61139f575050565b6113b3600061134183826110b98782610943565b339061137c6113766113767ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b9590565b50634e487b7160e01b600052601160045260246000fd5b90611404565b9190565b908060001904821181151516611418570290565b6114206113e3565b0290565b81198111611430570190565b610bf56113e3565b90611445610c2083610bd6565b918252565b369037565b9061082061146561145f84611438565b93610bd6565b601f19016020840161144a565b50634e487b7160e01b600052603260045260246000fd5b906001602091611497845190565b8110156114a5575b02010190565b6114ad611472565b61149f565b60019080156114bf570390565b6114c76113e3565b0390565b6110956108366108369290565b610836906114ec6114006108369460ff1690565b901c90565b156114f857565b5060405162461bcd60e51b815280611238600482016020808252818101527f537472696e67733a20686578206c656e67746820696e73756666696369656e74604082015260600190565b919060029061157361156e61155f8361155a8661085d565b6113fa565b6115688561085d565b90611424565b61144f565b91600091603061158b6115858561085d565b86611489565b536115c36115ba600f60fb1b9261155a6001958695881a6115b46115ae8861085d565b8b611489565b5361085d565b6115688361085d565b915b6115e6575b505061083692936115e06114006108369361085d565b146114f1565b90946115f18261085d565b8611156116705761165d611657839261163a61161d6f181899199a1a9b1b9c1cb0b131b232b360811b90565b611627600f61085d565b83166010811015611663575b1a60f81b90565b861a6116468a89611489565b5361165160046114cb565b906114d8565b966114b2565b916115c5565b61166b611472565b611633565b946115ca565b6108369081906001600160a01b031681565b61083660146114cb565b6108366108366108369260ff1690565b6116bf6116ba610836926116b4606090565b50610b44565b611676565b6111f56116ca611688565b611692565b94939291906116de600b61109b565b6116f7576116eb9561196d565b6108206001600b6112fb565b5050505050505061170760405190565b62dc149f60e41b8152600490fd5b6109806108366108369290565b61083690611715565b906001600160a01b03906112f1565b9061174a61083661131292610b4d565b825461172b565b9160001960089290920291821b911b6112f1565b91906117766108366113129361085d565b908354611751565b61082091600091611765565b818110611795575050565b806117a3600060019361177e565b0161178a565b9190601f81116117b857505050565b6117ca61082093600052602060002090565b906020601f8401819004830193106117ec575b6020601f90910104019061178a565b90915081906117dd565b919067ffffffffffffffff82116118c1575b61181c826118168554610d34565b856117a9565b600090601f83116001146118575761131292916000918361184c575b5050600019600883021c1916906002021790565b013590503880611838565b601f1983169161186c85600052602060002090565b92815b8181106118a957509160029391856001969410611890575b50505002019055565b0135600019601f84166008021c19169055388080611887565b9193602060018192878701358155019501920161186f565b6118c9610b7c565b611808565b9061082092916117f6565b90600019906112f1565b906118f36108366113129261085d565b82546118d9565b9190610b728161191181610bf59560209181520190565b8095610c01565b9161105291610820969897956080956119586119659461194860a089019560008a01906001600160a01b03169052565b6001600160a01b03166020880152565b85830360408701526118fa565b966060830152565b9291949093600061198061098082611722565b6001600160a01b03861614611ad7578361199a565b905090565b6119a66114008361085d565b14611ab7576119b48161085d565b82148015611aa4575b611a84576119ca9061085d565b82148015611a71575b611a5257611a4d926119e685600361173a565b6119f2818860026118ce565b6119fd8260046118e3565b611a088360056118e3565b611a1986611a14610ef5565b611316565b7fa80caddab9a93c4df4f67cd3ee3490472325e6903e29687fc5904cef451041f996611a4460405190565b96879687611918565b0390a1565b50505050505050611a6260405190565b634f08daf360e11b8152600490fd5b50611a7d610836610a06565b82116119d3565b5050505050505050611a9560405190565b63c17d8a0360e01b8152600490fd5b50611ab061083661086a565b82116119bd565b5050505050505050611ac860405190565b6301fc71f560e21b8152600490fd5b5050505050505050611ae860405190565b63e6c4247b60e01b8152600490fd5b9061082095949392916116cf565b9190611b0f610ef5565b611b1d6111bc3380936110a5565b9081611b4e575b50611b325761082092611cb6565b50505050611b3f60405190565b63ea8e4eb560e01b8152600490fd5b611b6b91506111bc906000805160206130548339815191526110a5565b38611b24565b6020809167ffffffffffffffff8111611b8957020190565b611b91610b7c565b020190565b90611445610c2083611b71565b90610820611465611bb384611b96565b93611b71565b903590601e193682900301821215611bfd575b01602081359167ffffffffffffffff8311611bf0575b019136829003831361085557565b611bf86107f9565b611be2565b611c056107f9565b611bcc565b906108f192602091811015611c23575b02810190611bb9565b611c2b611472565b611c1a565b9091610bf59083908093610c01565b909161083692611c30565b9060208091611497845190565b6001906000198114611430570190565b90611c76610f20610f16845190565b9060005b818110611c875750505090565b909192611c9d610f576001928651815260200190565b929101611c7a565b602080825261083692910190611c67565b929181926000611cc58161085d565b8514611e1757428310611df957611cdb85611ba3565b9160009560015b15611d9f575b8296611cf861199582898c611c0a565b611d046114008661085d565b14611d7e5780611d59611214611d39611d21611d78958c8f611c0a565b90611d2b60405190565b938492602084019283611c3f565b611d4b611d44825190565b9160200190565b20611d568389611c4a565b52565b611d7387611d6e611d6a848a611c4a565b5190565b613044565b611c57565b96611ce2565b505050505050505050611d9060405190565b63eb48439160e01b8152600490fd5b80871015611dac57611ce8565b5095505092509050611df4611de17f8c852cad34f901531c4a1328ddfefbc6152fbd45aa7eb38890e74f351d8493a69261085d565b92611deb60405190565b91829182611ca5565b0390a2565b505050505050611e0860405190565b631da7447960e21b8152600490fd5b505050505050611ae860405190565b906108209291611b05565b9190611e3b610ef5565b611e496111bc3380936110a5565b9081611e5e575b50611b325761082092611e87565b611e7b91506111bc906000805160206130548339815191526110a5565b38611e50565b01918252565b9190916000611e958161085d565b8414611f7a57428310611f6c57611eab84611ba3565b9460009460015b15611f15575b611f0f8396611efe611ec960405190565b611ee88160208101611214868c83602081611e81610bf5938396959052565b611ef3611d44825190565b20611d56838c611c4a565b611d7387611d6e611d6a848d611c4a565b95611eb2565b80861015611f2257611eb8565b5094935050611f67611f5d611f577fc3c3780ed921778d05400bdfaf133352f1c8ce56e4ce47391118f53a22103cce9361085d565b9361085d565b93611deb60405190565b0390a3565b5050505050611e0860405190565b5050505050611f8860405190565b633d25757960e01b8152600490fd5b906108209291611e31565b9190611fac610ef5565b611fba6111bc3380936110a5565b9081611fcf575b50611b325761082092612033565b611fec91506111bc906000805160206130548339815191526110a5565b38611fc1565b9160209181101561200257020190565b611b91611472565b356108368161098c565b610846906001600160a01b031660601b90565b610bf581601493612014565b909291839260006120438161085d565b8514611e1757428310611df95761205985611ba3565b9160009560015b156120e5575b829661207b612076828b8a611ff2565b61200a565b61209761208a61098087611722565b916001600160a01b031690565b146120d35780611d596120b16120766120cd948d8c611ff2565b611d396120bd60405190565b8092611214602083019182612027565b96612060565b505050505050505050611ae860405190565b808710156120f257612066565b5095505092509050611df4611de17fa9411f55f4ccd3f63f1f6236481c2f6b385a4221287184e89ca4c40792f8224e9261085d565b906108209291611fa2565b61082090612141611105610ef5565b61214e6109806000611722565b6001600160a01b038216146121a35761217581600080516020613054833981519152611316565b611a4d7fd36b0989e598a1b05388150a9a8c84925e2710d91910406b8735e01f3ed028179161036f60405190565b5050604051611ae8565b61082090612132565b610820906121c5611105610ef5565b6000805160206130548339815191526121e16111bc83836110a5565b61221d57816121ef9161138c565b611a4d7f708bd40f8f4d2ad60032caea0582161d35c50177cc0b2c575b5d483bd2902caa9161036f60405190565b50505061222960405190565b632793ed7d60e01b8152600490fd5b610820906121b6565b61082090612250611105610ef5565b61225a600061085d565b811480156122aa575b6122a0576122728160046118e3565b611a4d7fbff777c073bd9101dd1e419471fe91c54c9ffe380882bca8eb1fcf75d6086f779161025f60405190565b5050604051611a95565b506122b661083661086a565b8111612263565b61082090612241565b610820906122d5611105610ef5565b6122df600061085d565b8114801561232f575b612325576122f78160056118e3565b611a4d7f7d7455c70e1855cfeb6ff84fe7b6d37efcfdaee91c05f2e25a55368f50ba7b5a9161025f60405190565b5050604051611a62565b5061233b610836610a06565b81116122e8565b610820906122c6565b90612354610ef5565b6123626111bc3380936110a5565b9081612383575b5061237757610820916124e1565b505050611b3f60405190565b6123a091506111bc906000805160206130548339815191526110a5565b38612369565b61083690610980565b61083690546123a6565b6123d96001916123c7815490565b8410156123e257600052602060002090565b91020190600090565b6123ea611472565b600052602060002090565b916001600160a01b0360089290920291821b911b6112f1565b919061241f61083661131293610b4d565b9083546123f5565b9061244f6108209280549068010000000000000000821015612455575b6001820181556123b9565b9061240e565b61245d610b7c565b612444565b8181106114bf570390565b5061083690602081019061099b565b818352602090920191906000825b828210612498575050505090565b909192936124c76124c06001926124af888661246d565b6001600160a01b0316815260200190565b9560200190565b9392019061248a565b60208082526108369391019161247c565b909190829160005b835b81101561260157612500612076828786611ff2565b61251061208a6109806000611722565b146125f357612523612076828786611ff2565b61253361208a61098060036123af565b146125d657612549610427612076838887611ff2565b6125b9576124eb906125b2906125ac61258e61257e600661257a89612574612076888f865b94611ff2565b90612427565b5490565b612588600161085d565b90612462565b6125a760096125a1612076868d8c611ff2565b90610b56565b6118e3565b60010190565b90506124e9565b50505050506125c760405190565b63241d2edf60e01b8152600490fd5b50505050506125e460405190565b63a122bf3960e01b8152600490fd5b5050505050611ae860405190565b50929091507fe7e9e18eae0a1664f98ba7e59eda81692d5802c7e9bd75bb0261f3fc6fd4a49391611a4d61263460405190565b928392836124d0565b906108209161234b565b90612650610ef5565b61265e6111bc3380936110a5565b9081612673575b5061237757610820916126ef565b61269091506111bc906000805160206130548339815191526110a5565b38612665565b50634e487b7160e01b600052603160045260246000fd5b6108209160009161240e565b60016126c3825490565b80156126e2575b03906126df6126d983836123b9565b906126ad565b55565b6126ea612696565b6126ca565b909190829160005b835b8110156127c2576127146111bc610427612076848988611ff2565b6127a55761279e816125ac61279961275461083660006127948a6125a16120768f9b6126f99c60099461278f61275f61275a612754612076878787611ff2565b89610b56565b6110cb565b6125a78160069d8e61244f61278761278161277b61257e855490565b846123b9565b90610f90565b9384926123b9565b611ff2565b61177e565b6126b9565b90506126f7565b50505050506127b360405190565b6307c241ad60e51b8152600490fd5b50929091507fc18397a78d98d67911be09b9c32315c4b8db0454529f84f856e61f537494cbfc91611a4d61263460405190565b9061082091612647565b906108209161280f611105610ef5565b909190829160005b835b8110156128b45761282e612076828786611ff2565b61283e61208a6109806000611722565b146125f3576128546106ef612076838887611ff2565b6128975761281990612890906125ac61287d61257e600761257a89612574612076888f8661256e565b6125a7600a6125a1612076868d8c611ff2565b9050612817565b50505050506128a560405190565b6336650e8f60e11b8152600490fd5b50929091507f8ff2887f41c4af26bbcadf0889537a4641e2d1d6d9fa287feaf683a76096efd891611a4d61263460405190565b90610820916127ff565b9061082091612901611105610ef5565b909190829160005b835b8110156129a6576129266111bc6106ef612076848988611ff2565b61298957612982816125ac61279961275461083660006127948a6125a16120768f9b61290b9c600a9461278f61296661275a612754612076878787611ff2565b6125a78160079d8e61244f61278761278161277b61257e855490565b9050612909565b505050505061299760405190565b637463712b60e01b8152600490fd5b50929091507fa520ff964bc029411023e3f0e20bf29e54c023e5e23b0e28d0de3ae5d4231a9e91611a4d61263460405190565b90610820916128f1565b906129f8949392916129f3612a96565b612a12565b610820612ac8565b6108366000611438565b610836612a00565b92610820949192612a23600061085d565b93612a2c612a0a565b95612e44565b90610820949392916129e3565b610836600261085d565b15612a5057565b5060405162461bcd60e51b815260206004820152601f60248201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c006044820152606490fd5b610820612aa360016110cb565b612ab7612aae612a3f565b91821415612a49565b60016118e3565b610836600161085d565b610820612ab7612abe565b906129f8969594939291612ae5612a96565b90610820969594939291612e44565b90610820969594939291612ad3565b90612b1e612b12610f16845490565b92600052602060002090565b9060005b818110612b2f5750505090565b909192612b4b612b446001926124af876123af565b9460010190565b929101612b22565b9061083691612b03565b90610820610e0492612b6e60405190565b93848092612b53565b61083690612b5d565b6108366006612b77565b6108366007612b77565b92612bb16020610bf594611e81601488611e81829b9a8699612014565b018092612014565b905051906108208261098c565b905051906108208261090f565b919061083690604084820312612bf7575b612bee8185612bb9565b93602001612bc6565b612bff6107f9565b612be4565b506040513d6000823e3d90fd5b91612c9992612c8b604093612c24600090565b50612c68612c3d612c38612c3860036123af565b610b4d565b93632c4ef0d595611214612c5030610b4d565b91612c5a60405190565b958694602086019485612b94565b612c73611d44825190565b2092612c7e60405190565b9586948593849360e01b90565b835260048301526024820190565b03915afa908115612cce575b600080919092612cb457509091565b90506108f19150612cc53d82610b93565b3d810190612bd3565b612cd6612c04565b612ca5565b600690612ce6825490565b600090612cf56114008361085d565b14612d5057612d0861275a836009610b56565b612d146114008361085d565b1415928315612d24575b50505090565b612d4792935061278161208a92612d3a926123b9565b926001600160a01b031690565b14388080612d1e565b91505090565b600790612d61825490565b600090612d706114008361085d565b14612d5057612d0861275a83600a610b56565b610836610140610bc2565b805182526020808201516001600160a01b03169083015261083691610140810191610120906040818101516001600160a01b031690840152612dd560608201516060850152565b612de460808201516080850152565b612df360a082015160a0850152565b612e0260c082015160c0850152565b612e1160e082015160e0850152565b612e22610100820151610100850152565b015190610120818403910152610e69565b602080825261083692910190612d8e565b9394959095612e5761275a866008610943565b42811061302357600097612e6a8961085d565b8814801561300e575b612fec57612e836109808a611722565b6001600160a01b03821614612fd957612e9e6111bc82612cdb565b612fc657612eab8961085d565b8514612fa4578897612ebd60036123af565b612ec690610b4d565b612ecf90610b4d565b96635c2a802b9633612ee160056110cb565b94612eea612d83565b9b612ef5908e8e0152565b6001600160a01b031660208c01526001600160a01b031660408b015260608a0152608089015260a088015260c087015260e0860152610100850152610120840152612f6194612f5691833b15612f97575b6040519687958694859360e01b90565b835260048301612e33565b03925af18015612f8a575b612f735750565b61082090612f813d82610b93565b3d81019061084a565b612f92612c04565b612f6c565b612f9f6107f9565b612f46565b50505050505050505050612fb760405190565b63162908e360e11b8152600490fd5b505050505050505050506127b360405190565b50505050505050505050611ae860405190565b50505050505050505050612fff60405190565b6302e8f35960e31b8152600490fd5b5061301c61083660046110cb565b8811612e73565b50505050505050505061303560405190565b63387b2e5560e11b8152600490fd5b906125a761082092600861094356fe5146a08baf902532d0ee2f909971144f12ca32651cd70cbee1117cddfb3b3b33a3646970667358221220929ba7a4e3cca97712cee99b9b10b2031bc193223d3173c44d9103f46c3e55df6c6578706572696d656e74616cf564736f6c634300080c0041
Loading...
Loading
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in FRAX
0
Multichain Portfolio | 35 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
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.