Contract Address Details

0xFAF457Fb4A978Be059506F6CD41f9B30fCa753b0

GovernanceStaking G$ Staking For GOOD (sG$) Last Balance Update: Block #18695323
Created by 0x465917–f52057 at 0x750a38–5882cd

Balance

0 Fuse

Fetching tokens...

Contract name:
GovernanceStaking




Optimization enabled
true
Compiler version
v0.8.8+commit.dddeac2f




Optimization runs
0
EVM Version
default




Verified at
2021-12-20 09:49:36.799553Z

Constructor Arguments

000000000000000000000000e26867ddd22f9342d9f0d566d182f2c960683971

Arg [0] (address) : 0xe26867ddd22f9342d9f0d566d182f2c960683971

              

Contract source code

// Sources flattened with hardhat v2.6.4 https://hardhat.org
// File @openzeppelin/contracts-upgradeable/token/ERC20/IERC20Upgradeable.sol@v4.3.2
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20Upgradeable {
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address recipient, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `sender` to `recipient` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address sender,
address recipient,
uint256 amount
) external returns (bool);
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
}
// File @openzeppelin/contracts-upgradeable/token/ERC20/extensions/IERC20MetadataUpgradeable.sol@v4.3.2
/**
* @dev Interface for the optional metadata functions from the ERC20 standard.
*
* _Available since v4.1._
*/
interface IERC20MetadataUpgradeable is IERC20Upgradeable {
/**
* @dev Returns the name of the token.
*/
function name() external view returns (string memory);
/**
* @dev Returns the symbol of the token.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the decimals places of the token.
*/
function decimals() external view returns (uint8);
}
// File @openzeppelin/contracts-upgradeable/proxy/utils/Initializable.sol@v4.3.2
/**
* @dev This is a base contract to aid in writing upgradeable contracts, or any kind of contract that will be deployed
* behind a proxy. Since a proxied contract can't have a constructor, it's common to move constructor logic to an
* external initializer function, usually called `initialize`. It then becomes necessary to protect this initializer
* function so it can only be called once. The {initializer} modifier provided by this contract will have this effect.
*
* TIP: To avoid leaving the proxy in an uninitialized state, the initializer function should be called as early as
* possible by providing the encoded function call as the `_data` argument to {ERC1967Proxy-constructor}.
*
* CAUTION: When used with inheritance, manual care must be taken to not invoke a parent initializer twice, or to ensure
* that all initializers are idempotent. This is not verified automatically as constructors are by Solidity.
*/
abstract contract Initializable {
/**
* @dev Indicates that the contract has been initialized.
*/
bool private _initialized;
/**
* @dev Indicates that the contract is in the process of being initialized.
*/
bool private _initializing;
/**
* @dev Modifier to protect an initializer function from being invoked twice.
*/
modifier initializer() {
require(_initializing || !_initialized, "Initializable: contract is already initialized");
bool isTopLevelCall = !_initializing;
if (isTopLevelCall) {
_initializing = true;
_initialized = true;
}
_;
if (isTopLevelCall) {
_initializing = false;
}
}
}
// File @openzeppelin/contracts-upgradeable/utils/ContextUpgradeable.sol@v4.3.2
/**
* @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 ContextUpgradeable is Initializable {
function __Context_init() internal initializer {
__Context_init_unchained();
}
function __Context_init_unchained() internal initializer {
}
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
uint256[50] private __gap;
}
// File @openzeppelin/contracts-upgradeable/token/ERC20/ERC20Upgradeable.sol@v4.3.2
/**
* @dev Implementation of the {IERC20} interface.
*
* This implementation is agnostic to the way tokens are created. This means
* that a supply mechanism has to be added in a derived contract using {_mint}.
* For a generic mechanism see {ERC20PresetMinterPauser}.
*
* TIP: For a detailed writeup see our guide
* https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How
* to implement supply mechanisms].
*
* We have followed general OpenZeppelin Contracts guidelines: functions revert
* instead returning `false` on failure. This behavior is nonetheless
* conventional and does not conflict with the expectations of ERC20
* applications.
*
* Additionally, an {Approval} event is emitted on calls to {transferFrom}.
* This allows applications to reconstruct the allowance for all accounts just
* by listening to said events. Other implementations of the EIP may not emit
* these events, as it isn't required by the specification.
*
* Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
* functions have been added to mitigate the well-known issues around setting
* allowances. See {IERC20-approve}.
*/
contract ERC20Upgradeable is Initializable, ContextUpgradeable, IERC20Upgradeable, IERC20MetadataUpgradeable {
mapping(address => uint256) private _balances;
mapping(address => mapping(address => uint256)) private _allowances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
/**
* @dev Sets the values for {name} and {symbol}.
*
* The default value of {decimals} is 18. To select a different value for
* {decimals} you should overload it.
*
* All two of these values are immutable: they can only be set once during
* construction.
*/
function __ERC20_init(string memory name_, string memory symbol_) internal initializer {
__Context_init_unchained();
__ERC20_init_unchained(name_, symbol_);
}
function __ERC20_init_unchained(string memory name_, string memory symbol_) internal initializer {
_name = name_;
_symbol = symbol_;
}
/**
* @dev Returns the name of the token.
*/
function name() public view virtual override returns (string memory) {
return _name;
}
/**
* @dev Returns the symbol of the token, usually a shorter version of the
* name.
*/
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
/**
* @dev Returns the number of decimals used to get its user representation.
* For example, if `decimals` equals `2`, a balance of `505` tokens should
* be displayed to a user as `5.05` (`505 / 10 ** 2`).
*
* Tokens usually opt for a value of 18, imitating the relationship between
* Ether and Wei. This is the value {ERC20} uses, unless this function is
* overridden;
*
* NOTE: This information is only used for _display_ purposes: it in
* no way affects any of the arithmetic of the contract, including
* {IERC20-balanceOf} and {IERC20-transfer}.
*/
function decimals() public view virtual override returns (uint8) {
return 18;
}
/**
* @dev See {IERC20-totalSupply}.
*/
function totalSupply() public view virtual override returns (uint256) {
return _totalSupply;
}
/**
* @dev See {IERC20-balanceOf}.
*/
function balanceOf(address account) public view virtual override returns (uint256) {
return _balances[account];
}
/**
* @dev See {IERC20-transfer}.
*
* Requirements:
*
* - `recipient` cannot be the zero address.
* - the caller must have a balance of at least `amount`.
*/
function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
_transfer(_msgSender(), recipient, amount);
return true;
}
/**
* @dev See {IERC20-allowance}.
*/
function allowance(address owner, address spender) public view virtual override returns (uint256) {
return _allowances[owner][spender];
}
/**
* @dev See {IERC20-approve}.
*
* Requirements:
*
* - `spender` cannot be the zero address.
*/
function approve(address spender, uint256 amount) public virtual override returns (bool) {
_approve(_msgSender(), spender, amount);
return true;
}
/**
* @dev See {IERC20-transferFrom}.
*
* Emits an {Approval} event indicating the updated allowance. This is not
* required by the EIP. See the note at the beginning of {ERC20}.
*
* Requirements:
*
* - `sender` and `recipient` cannot be the zero address.
* - `sender` must have a balance of at least `amount`.
* - the caller must have allowance for ``sender``'s tokens of at least
* `amount`.
*/
function transferFrom(
address sender,
address recipient,
uint256 amount
) public virtual override returns (bool) {
_transfer(sender, recipient, amount);
uint256 currentAllowance = _allowances[sender][_msgSender()];
require(currentAllowance >= amount, "ERC20: transfer amount exceeds allowance");
unchecked {
_approve(sender, _msgSender(), currentAllowance - amount);
}
return true;
}
/**
* @dev Atomically increases the allowance granted to `spender` by the caller.
*
* This is an alternative to {approve} that can be used as a mitigation for
* problems described in {IERC20-approve}.
*
* Emits an {Approval} event indicating the updated allowance.
*
* Requirements:
*
* - `spender` cannot be the zero address.
*/
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender] + addedValue);
return true;
}
/**
* @dev Atomically decreases the allowance granted to `spender` by the caller.
*
* This is an alternative to {approve} that can be used as a mitigation for
* problems described in {IERC20-approve}.
*
* Emits an {Approval} event indicating the updated allowance.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `spender` must have allowance for the caller of at least
* `subtractedValue`.
*/
function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
uint256 currentAllowance = _allowances[_msgSender()][spender];
require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
unchecked {
_approve(_msgSender(), spender, currentAllowance - subtractedValue);
}
return true;
}
/**
* @dev Moves `amount` of tokens from `sender` to `recipient`.
*
* This internal function is equivalent to {transfer}, and can be used to
* e.g. implement automatic token fees, slashing mechanisms, etc.
*
* Emits a {Transfer} event.
*
* Requirements:
*
* - `sender` cannot be the zero address.
* - `recipient` cannot be the zero address.
* - `sender` must have a balance of at least `amount`.
*/
function _transfer(
address sender,
address recipient,
uint256 amount
) internal virtual {
require(sender != address(0), "ERC20: transfer from the zero address");
require(recipient != address(0), "ERC20: transfer to the zero address");
_beforeTokenTransfer(sender, recipient, amount);
uint256 senderBalance = _balances[sender];
require(senderBalance >= amount, "ERC20: transfer amount exceeds balance");
unchecked {
_balances[sender] = senderBalance - amount;
}
_balances[recipient] += amount;
emit Transfer(sender, recipient, amount);
_afterTokenTransfer(sender, recipient, amount);
}
/** @dev Creates `amount` tokens and assigns them to `account`, increasing
* the total supply.
*
* Emits a {Transfer} event with `from` set to the zero address.
*
* Requirements:
*
* - `account` cannot be the zero address.
*/
function _mint(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: mint to the zero address");
_beforeTokenTransfer(address(0), account, amount);
_totalSupply += amount;
_balances[account] += amount;
emit Transfer(address(0), account, amount);
_afterTokenTransfer(address(0), account, amount);
}
/**
* @dev Destroys `amount` tokens from `account`, reducing the
* total supply.
*
* Emits a {Transfer} event with `to` set to the zero address.
*
* Requirements:
*
* - `account` cannot be the zero address.
* - `account` must have at least `amount` tokens.
*/
function _burn(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: burn from the zero address");
_beforeTokenTransfer(account, address(0), amount);
uint256 accountBalance = _balances[account];
require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
unchecked {
_balances[account] = accountBalance - amount;
}
_totalSupply -= amount;
emit Transfer(account, address(0), amount);
_afterTokenTransfer(account, address(0), amount);
}
/**
* @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
*
* This internal function is equivalent to `approve`, and can be used to
* e.g. set automatic allowances for certain subsystems, etc.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `owner` cannot be the zero address.
* - `spender` cannot be the zero address.
*/
function _approve(
address owner,
address spender,
uint256 amount
) internal virtual {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
/**
* @dev Hook that is called before any transfer of tokens. This includes
* minting and burning.
*
* Calling conditions:
*
* - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
* will be transferred to `to`.
* - when `from` is zero, `amount` tokens will be minted for `to`.
* - when `to` is zero, `amount` of ``from``'s tokens will be burned.
* - `from` and `to` are never both zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _beforeTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual {}
/**
* @dev Hook that is called after any transfer of tokens. This includes
* minting and burning.
*
* Calling conditions:
*
* - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
* has been transferred to `to`.
* - when `from` is zero, `amount` tokens have been minted for `to`.
* - when `to` is zero, `amount` of ``from``'s tokens have been burned.
* - `from` and `to` are never both zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _afterTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual {}
uint256[45] private __gap;
}
// File @openzeppelin/contracts-upgradeable/proxy/beacon/IBeaconUpgradeable.sol@v4.3.2
/**
* @dev This is the interface that {BeaconProxy} expects of its beacon.
*/
interface IBeaconUpgradeable {
/**
* @dev Must return an address that can be used as a delegate call target.
*
* {BeaconProxy} will check that this address is a contract.
*/
function implementation() external view returns (address);
}
// File @openzeppelin/contracts-upgradeable/utils/AddressUpgradeable.sol@v4.3.2
/**
* @dev Collection of functions related to the address type
*/
library AddressUpgradeable {
/**
* @dev Returns true if `account` is a contract.
*
* [IMPORTANT]
* ====
* It is unsafe to assume that an address for which this function returns
* false is an externally-owned account (EOA) and not a contract.
*
* Among others, `isContract` will return false for the following
* types of addresses:
*
* - an externally-owned account
* - a contract in construction
* - an address where a contract will be created
* - an address where a contract lived, but was destroyed
* ====
*/
function isContract(address account) internal view returns (bool) {
// This method relies on extcodesize, which returns 0 for contracts in
// construction, since the code is only stored at the end of the
// constructor execution.
uint256 size;
assembly {
size := extcodesize(account)
}
return size > 0;
}
/**
* @dev Replacement for Solidity's `transfer`: sends `amount` wei to
* `recipient`, forwarding all available gas and reverting on errors.
*
* https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
* of certain opcodes, possibly making contracts go over the 2300 gas limit
* imposed by `transfer`, making them unable to receive funds via
* `transfer`. {sendValue} removes this limitation.
*
* https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
*
* IMPORTANT: because control is transferred to `recipient`, care must be
* taken to not create reentrancy vulnerabilities. Consider using
* {ReentrancyGuard} or the
* https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern].
*/
function sendValue(address payable recipient, uint256 amount) internal {
require(address(this).balance >= amount, "Address: insufficient balance");
(bool success, ) = recipient.call{value: amount}("");
require(success, "Address: unable to send value, recipient may have reverted");
}
/**
* @dev Performs a Solidity function call using a low level `call`. A
* plain `call` is an unsafe replacement for a function call: use this
* function instead.
*
* If `target` reverts with a revert reason, it is bubbled up by this
* function (like regular Solidity function calls).
*
* Returns the raw returned data. To convert to the expected return value,
* use https://solidity.readthedocs.io/en/latest/units-and-global-variables.html?highlight=abi.decode#abi-encoding-and-decoding-functions[`abi.decode`].
*
* Requirements:
*
* - `target` must be a contract.
* - calling `target` with `data` must not revert.
*
* _Available since v3.1._
*/
function functionCall(address target, bytes memory data) internal returns (bytes memory) {
return functionCall(target, data, "Address: low-level call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`], but with
* `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCall(
address target,
bytes memory data,
string memory errorMessage
) internal returns (bytes memory) {
return functionCallWithValue(target, data, 0, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but also transferring `value` wei to `target`.
*
* Requirements:
*
* - the calling contract must have an ETH balance of at least `value`.
* - the called Solidity function must be `payable`.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value
) internal returns (bytes memory) {
return functionCallWithValue(target, data, value, "Address: low-level call with value failed");
}
/**
* @dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[`functionCallWithValue`], but
* with `errorMessage` as a fallback revert reason when `target` reverts.
*
* _Available since v3.1._
*/
function functionCallWithValue(
address target,
bytes memory data,
uint256 value,
string memory errorMessage
) internal returns (bytes memory) {
require(address(this).balance >= value, "Address: insufficient balance for call");
require(isContract(target), "Address: call to non-contract");
(bool success, bytes memory returndata) = target.call{value: value}(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(address target, bytes memory data) internal view returns (bytes memory) {
return functionStaticCall(target, data, "Address: low-level static call failed");
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a static call.
*
* _Available since v3.3._
*/
function functionStaticCall(
address target,
bytes memory data,
string memory errorMessage
) internal view returns (bytes memory) {
require(isContract(target), "Address: static call to non-contract");
(bool success, bytes memory returndata) = target.staticcall(data);
return verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Tool to verifies that a low level call was successful, and revert if it wasn't, either by bubbling the
* revert reason using the provided one.
*
* _Available since v4.3._
*/
function verifyCallResult(
bool success,
bytes memory returndata,
string memory errorMessage
) internal pure returns (bytes memory) {
if (success) {
return returndata;
} else {
// Look for revert reason and bubble it up if present
if (returndata.length > 0) {
// The easiest way to bubble the revert reason is using memory via assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}
// File @openzeppelin/contracts-upgradeable/utils/StorageSlotUpgradeable.sol@v4.3.2
/**
* @dev Library for reading and writing primitive types to specific storage slots.
*
* Storage slots are often used to avoid storage conflict when dealing with upgradeable contracts.
* This library helps with reading and writing to such slots without the need for inline assembly.
*
* The functions in this library return Slot structs that contain a `value` member that can be used to read or write.
*
* Example usage to set ERC1967 implementation slot:
* ```
* contract ERC1967 {
* bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
*
* function _getImplementation() internal view returns (address) {
* return StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value;
* }
*
* function _setImplementation(address newImplementation) internal {
* require(Address.isContract(newImplementation), "ERC1967: new implementation is not a contract");
* StorageSlot.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
* }
* }
* ```
*
* _Available since v4.1 for `address`, `bool`, `bytes32`, and `uint256`._
*/
library StorageSlotUpgradeable {
struct AddressSlot {
address value;
}
struct BooleanSlot {
bool value;
}
struct Bytes32Slot {
bytes32 value;
}
struct Uint256Slot {
uint256 value;
}
/**
* @dev Returns an `AddressSlot` with member `value` located at `slot`.
*/
function getAddressSlot(bytes32 slot) internal pure returns (AddressSlot storage r) {
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `BooleanSlot` with member `value` located at `slot`.
*/
function getBooleanSlot(bytes32 slot) internal pure returns (BooleanSlot storage r) {
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `Bytes32Slot` with member `value` located at `slot`.
*/
function getBytes32Slot(bytes32 slot) internal pure returns (Bytes32Slot storage r) {
assembly {
r.slot := slot
}
}
/**
* @dev Returns an `Uint256Slot` with member `value` located at `slot`.
*/
function getUint256Slot(bytes32 slot) internal pure returns (Uint256Slot storage r) {
assembly {
r.slot := slot
}
}
}
// File @openzeppelin/contracts-upgradeable/proxy/ERC1967/ERC1967UpgradeUpgradeable.sol@v4.3.2
/**
* @dev This abstract contract provides getters and event emitting update functions for
* https://eips.ethereum.org/EIPS/eip-1967[EIP1967] slots.
*
* _Available since v4.1._
*
* @custom:oz-upgrades-unsafe-allow delegatecall
*/
abstract contract ERC1967UpgradeUpgradeable is Initializable {
function __ERC1967Upgrade_init() internal initializer {
__ERC1967Upgrade_init_unchained();
}
function __ERC1967Upgrade_init_unchained() internal initializer {
}
// This is the keccak-256 hash of "eip1967.proxy.rollback" subtracted by 1
bytes32 private constant _ROLLBACK_SLOT = 0x4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143;
/**
* @dev Storage slot with the address of the current implementation.
* This is the keccak-256 hash of "eip1967.proxy.implementation" subtracted by 1, and is
* validated in the constructor.
*/
bytes32 internal constant _IMPLEMENTATION_SLOT = 0x360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc;
/**
* @dev Emitted when the implementation is upgraded.
*/
event Upgraded(address indexed implementation);
/**
* @dev Returns the current implementation address.
*/
function _getImplementation() internal view returns (address) {
return StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value;
}
/**
* @dev Stores a new address in the EIP1967 implementation slot.
*/
function _setImplementation(address newImplementation) private {
require(AddressUpgradeable.isContract(newImplementation), "ERC1967: new implementation is not a contract");
StorageSlotUpgradeable.getAddressSlot(_IMPLEMENTATION_SLOT).value = newImplementation;
}
/**
* @dev Perform implementation upgrade
*
* Emits an {Upgraded} event.
*/
function _upgradeTo(address newImplementation) internal {
_setImplementation(newImplementation);
emit Upgraded(newImplementation);
}
/**
* @dev Perform implementation upgrade with additional setup call.
*
* Emits an {Upgraded} event.
*/
function _upgradeToAndCall(
address newImplementation,
bytes memory data,
bool forceCall
) internal {
_upgradeTo(newImplementation);
if (data.length > 0 || forceCall) {
_functionDelegateCall(newImplementation, data);
}
}
/**
* @dev Perform implementation upgrade with security checks for UUPS proxies, and additional setup call.
*
* Emits an {Upgraded} event.
*/
function _upgradeToAndCallSecure(
address newImplementation,
bytes memory data,
bool forceCall
) internal {
address oldImplementation = _getImplementation();
// Initial upgrade and setup call
_setImplementation(newImplementation);
if (data.length > 0 || forceCall) {
_functionDelegateCall(newImplementation, data);
}
// Perform rollback test if not already in progress
StorageSlotUpgradeable.BooleanSlot storage rollbackTesting = StorageSlotUpgradeable.getBooleanSlot(_ROLLBACK_SLOT);
if (!rollbackTesting.value) {
// Trigger rollback using upgradeTo from the new implementation
rollbackTesting.value = true;
_functionDelegateCall(
newImplementation,
abi.encodeWithSignature("upgradeTo(address)", oldImplementation)
);
rollbackTesting.value = false;
// Check rollback was effective
require(oldImplementation == _getImplementation(), "ERC1967Upgrade: upgrade breaks further upgrades");
// Finally reset to the new implementation and log the upgrade
_upgradeTo(newImplementation);
}
}
/**
* @dev Storage slot with the admin of the contract.
* This is the keccak-256 hash of "eip1967.proxy.admin" subtracted by 1, and is
* validated in the constructor.
*/
bytes32 internal constant _ADMIN_SLOT = 0xb53127684a568b3173ae13b9f8a6016e243e63b6e8ee1178d6a717850b5d6103;
/**
* @dev Emitted when the admin account has changed.
*/
event AdminChanged(address previousAdmin, address newAdmin);
/**
* @dev Returns the current admin.
*/
function _getAdmin() internal view returns (address) {
return StorageSlotUpgradeable.getAddressSlot(_ADMIN_SLOT).value;
}
/**
* @dev Stores a new address in the EIP1967 admin slot.
*/
function _setAdmin(address newAdmin) private {
require(newAdmin != address(0), "ERC1967: new admin is the zero address");
StorageSlotUpgradeable.getAddressSlot(_ADMIN_SLOT).value = newAdmin;
}
/**
* @dev Changes the admin of the proxy.
*
* Emits an {AdminChanged} event.
*/
function _changeAdmin(address newAdmin) internal {
emit AdminChanged(_getAdmin(), newAdmin);
_setAdmin(newAdmin);
}
/**
* @dev The storage slot of the UpgradeableBeacon contract which defines the implementation for this proxy.
* This is bytes32(uint256(keccak256('eip1967.proxy.beacon')) - 1)) and is validated in the constructor.
*/
bytes32 internal constant _BEACON_SLOT = 0xa3f0ad74e5423aebfd80d3ef4346578335a9a72aeaee59ff6cb3582b35133d50;
/**
* @dev Emitted when the beacon is upgraded.
*/
event BeaconUpgraded(address indexed beacon);
/**
* @dev Returns the current beacon.
*/
function _getBeacon() internal view returns (address) {
return StorageSlotUpgradeable.getAddressSlot(_BEACON_SLOT).value;
}
/**
* @dev Stores a new beacon in the EIP1967 beacon slot.
*/
function _setBeacon(address newBeacon) private {
require(AddressUpgradeable.isContract(newBeacon), "ERC1967: new beacon is not a contract");
require(
AddressUpgradeable.isContract(IBeaconUpgradeable(newBeacon).implementation()),
"ERC1967: beacon implementation is not a contract"
);
StorageSlotUpgradeable.getAddressSlot(_BEACON_SLOT).value = newBeacon;
}
/**
* @dev Perform beacon upgrade with additional setup call. Note: This upgrades the address of the beacon, it does
* not upgrade the implementation contained in the beacon (see {UpgradeableBeacon-_setImplementation} for that).
*
* Emits a {BeaconUpgraded} event.
*/
function _upgradeBeaconToAndCall(
address newBeacon,
bytes memory data,
bool forceCall
) internal {
_setBeacon(newBeacon);
emit BeaconUpgraded(newBeacon);
if (data.length > 0 || forceCall) {
_functionDelegateCall(IBeaconUpgradeable(newBeacon).implementation(), data);
}
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-string-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function _functionDelegateCall(address target, bytes memory data) private returns (bytes memory) {
require(AddressUpgradeable.isContract(target), "Address: delegate call to non-contract");
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = target.delegatecall(data);
return AddressUpgradeable.verifyCallResult(success, returndata, "Address: low-level delegate call failed");
}
uint256[50] private __gap;
}
// File @openzeppelin/contracts-upgradeable/proxy/utils/UUPSUpgradeable.sol@v4.3.2
/**
* @dev An upgradeability mechanism designed for UUPS proxies. The functions included here can perform an upgrade of an
* {ERC1967Proxy}, when this contract is set as the implementation behind such a proxy.
*
* A security mechanism ensures that an upgrade does not turn off upgradeability accidentally, although this risk is
* reinstated if the upgrade retains upgradeability but removes the security mechanism, e.g. by replacing
* `UUPSUpgradeable` with a custom implementation of upgrades.
*
* The {_authorizeUpgrade} function must be overridden to include access restriction to the upgrade mechanism.
*
* _Available since v4.1._
*/
abstract contract UUPSUpgradeable is Initializable, ERC1967UpgradeUpgradeable {
function __UUPSUpgradeable_init() internal initializer {
__ERC1967Upgrade_init_unchained();
__UUPSUpgradeable_init_unchained();
}
function __UUPSUpgradeable_init_unchained() internal initializer {
}
/// @custom:oz-upgrades-unsafe-allow state-variable-immutable state-variable-assignment
address private immutable __self = address(this);
/**
* @dev Check that the execution is being performed through a delegatecall call and that the execution context is
* a proxy contract with an implementation (as defined in ERC1967) pointing to self. This should only be the case
* for UUPS and transparent proxies that are using the current contract as their implementation. Execution of a
* function through ERC1167 minimal proxies (clones) would not normally pass this test, but is not guaranteed to
* fail.
*/
modifier onlyProxy() {
require(address(this) != __self, "Function must be called through delegatecall");
require(_getImplementation() == __self, "Function must be called through active proxy");
_;
}
/**
* @dev Upgrade the implementation of the proxy to `newImplementation`.
*
* Calls {_authorizeUpgrade}.
*
* Emits an {Upgraded} event.
*/
function upgradeTo(address newImplementation) external virtual onlyProxy {
_authorizeUpgrade(newImplementation);
_upgradeToAndCallSecure(newImplementation, new bytes(0), false);
}
/**
* @dev Upgrade the implementation of the proxy to `newImplementation`, and subsequently execute the function call
* encoded in `data`.
*
* Calls {_authorizeUpgrade}.
*
* Emits an {Upgraded} event.
*/
function upgradeToAndCall(address newImplementation, bytes memory data) external payable virtual onlyProxy {
_authorizeUpgrade(newImplementation);
_upgradeToAndCallSecure(newImplementation, data, true);
}
/**
* @dev Function that should revert when `msg.sender` is not authorized to upgrade the contract. Called by
* {upgradeTo} and {upgradeToAndCall}.
*
* Normally, this function will use an xref:access.adoc[access control] modifier such as {Ownable-onlyOwner}.
*
* ```solidity
* function _authorizeUpgrade(address) internal override onlyOwner {}
* ```
*/
function _authorizeUpgrade(address newImplementation) internal virtual;
uint256[50] private __gap;
}
// File contracts/DAOStackInterfaces.sol
interface Avatar {
function nativeToken() external view returns (address);
function nativeReputation() external view returns (address);
function owner() external view returns (address);
}
interface Controller {
event RegisterScheme(address indexed _sender, address indexed _scheme);
event UnregisterScheme(address indexed _sender, address indexed _scheme);
function genericCall(
address _contract,
bytes calldata _data,
address _avatar,
uint256 _value
) external returns (bool, bytes memory);
function avatar() external view returns (address);
function unregisterScheme(address _scheme, address _avatar)
external
returns (bool);
function unregisterSelf(address _avatar) external returns (bool);
function registerScheme(
address _scheme,
bytes32 _paramsHash,
bytes4 _permissions,
address _avatar
) external returns (bool);
function isSchemeRegistered(address _scheme, address _avatar)
external
view
returns (bool);
function getSchemePermissions(address _scheme, address _avatar)
external
view
returns (bytes4);
function addGlobalConstraint(
address _constraint,
bytes32 _paramHash,
address _avatar
) external returns (bool);
function mintTokens(
uint256 _amount,
address _beneficiary,
address _avatar
) external returns (bool);
function externalTokenTransfer(
address _token,
address _recipient,
uint256 _amount,
address _avatar
) external returns (bool);
function sendEther(
uint256 _amountInWei,
address payable _to,
address _avatar
) external returns (bool);
}
interface GlobalConstraintInterface {
enum CallPhase {
Pre,
Post,
PreAndPost
}
function pre(
address _scheme,
bytes32 _params,
bytes32 _method
) external returns (bool);
/**
* @dev when return if this globalConstraints is pre, post or both.
* @return CallPhase enum indication Pre, Post or PreAndPost.
*/
function when() external returns (CallPhase);
}
interface ReputationInterface {
function balanceOf(address _user) external view returns (uint256);
function balanceOfAt(address _user, uint256 _blockNumber)
external
view
returns (uint256);
function getVotes(address _user) external view returns (uint256);
function getVotesAt(
address _user,
bool _global,
uint256 _blockNumber
) external view returns (uint256);
function totalSupply() external view returns (uint256);
function totalSupplyAt(uint256 _blockNumber)
external
view
returns (uint256);
function delegateOf(address _user) external returns (address);
}
interface SchemeRegistrar {
function proposeScheme(
Avatar _avatar,
address _scheme,
bytes32 _parametersHash,
bytes4 _permissions,
string memory _descriptionHash
) external returns (bytes32);
event NewSchemeProposal(
address indexed _avatar,
bytes32 indexed _proposalId,
address indexed _intVoteInterface,
address _scheme,
bytes32 _parametersHash,
bytes4 _permissions,
string _descriptionHash
);
}
interface IntVoteInterface {
event NewProposal(
bytes32 indexed _proposalId,
address indexed _organization,
uint256 _numOfChoices,
address _proposer,
bytes32 _paramsHash
);
event ExecuteProposal(
bytes32 indexed _proposalId,
address indexed _organization,
uint256 _decision,
uint256 _totalReputation
);
event VoteProposal(
bytes32 indexed _proposalId,
address indexed _organization,
address indexed _voter,
uint256 _vote,
uint256 _reputation
);
event CancelProposal(
bytes32 indexed _proposalId,
address indexed _organization
);
event CancelVoting(
bytes32 indexed _proposalId,
address indexed _organization,
address indexed _voter
);
/**
* @dev register a new proposal with the given parameters. Every proposal has a unique ID which is being
* generated by calculating keccak256 of a incremented counter.
* @param _numOfChoices number of voting choices
* @param _proposalParameters defines the parameters of the voting machine used for this proposal
* @param _proposer address
* @param _organization address - if this address is zero the msg.sender will be used as the organization address.
* @return proposal's id.
*/
function propose(
uint256 _numOfChoices,
bytes32 _proposalParameters,
address _proposer,
address _organization
) external returns (bytes32);
function vote(
bytes32 _proposalId,
uint256 _vote,
uint256 _rep,
address _voter
) external returns (bool);
function cancelVote(bytes32 _proposalId) external;
function getNumberOfChoices(bytes32 _proposalId)
external
view
returns (uint256);
function isVotable(bytes32 _proposalId) external view returns (bool);
/**
* @dev voteStatus returns the reputation voted for a proposal for a specific voting choice.
* @param _proposalId the ID of the proposal
* @param _choice the index in the
* @return voted reputation for the given choice
*/
function voteStatus(bytes32 _proposalId, uint256 _choice)
external
view
returns (uint256);
/**
* @dev isAbstainAllow returns if the voting machine allow abstain (0)
* @return bool true or false
*/
function isAbstainAllow() external pure returns (bool);
/**
* @dev getAllowedRangeOfChoices returns the allowed range of choices for a voting machine.
* @return min - minimum number of choices
max - maximum number of choices
*/
function getAllowedRangeOfChoices()
external
pure
returns (uint256 min, uint256 max);
}
// File contracts/utils/DataTypes.sol
library DataTypes {
// refer to the whitepaper, section 1.1 basic concepts for a formal description of these properties.
struct ReserveData {
//stores the reserve configuration
ReserveConfigurationMap configuration;
//the liquidity index. Expressed in ray
uint128 liquidityIndex;
//variable borrow index. Expressed in ray
uint128 variableBorrowIndex;
//the current supply rate. Expressed in ray
uint128 currentLiquidityRate;
//the current variable borrow rate. Expressed in ray
uint128 currentVariableBorrowRate;
//the current stable borrow rate. Expressed in ray
uint128 currentStableBorrowRate;
uint40 lastUpdateTimestamp;
//tokens addresses
address aTokenAddress;
address stableDebtTokenAddress;
address variableDebtTokenAddress;
//address of the interest rate strategy
address interestRateStrategyAddress;
//the id of the reserve. Represents the position in the list of the active reserves
uint8 id;
}
struct ReserveConfigurationMap {
//bit 0-15: LTV
//bit 16-31: Liq. threshold
//bit 32-47: Liq. bonus
//bit 48-55: Decimals
//bit 56: Reserve is active
//bit 57: reserve is frozen
//bit 58: borrowing is enabled
//bit 59: stable rate borrowing enabled
//bit 60-63: reserved
//bit 64-79: reserve factor
uint256 data;
}
enum InterestRateMode { NONE, STABLE, VARIABLE }
}
// File contracts/Interfaces.sol
pragma experimental ABIEncoderV2;
interface ERC20 {
function balanceOf(address addr) external view returns (uint256);
function transfer(address to, uint256 amount) external returns (bool);
function approve(address spender, uint256 amount) external returns (bool);
function decimals() external view returns (uint8);
function mint(address to, uint256 mintAmount) external returns (uint256);
function totalSupply() external view returns (uint256);
function allowance(address owner, address spender)
external
view
returns (uint256);
function transferFrom(
address sender,
address recipient,
uint256 amount
) external returns (bool);
function name() external view returns (string memory);
function symbol() external view returns (string memory);
event Transfer(address indexed from, address indexed to, uint256 amount);
event Transfer(
address indexed from,
address indexed to,
uint256 amount,
bytes data
);
}
interface cERC20 is ERC20 {
function mint(uint256 mintAmount) external returns (uint256);
function redeemUnderlying(uint256 mintAmount) external returns (uint256);
function redeem(uint256 mintAmount) external returns (uint256);
function exchangeRateCurrent() external returns (uint256);
function exchangeRateStored() external view returns (uint256);
function underlying() external returns (address);
}
interface IGoodDollar is ERC20 {
function getFees(uint256 value) external view returns (uint256, bool);
function burn(uint256 amount) external;
function burnFrom(address account, uint256 amount) external;
function renounceMinter() external;
function addMinter(address minter) external;
function isMinter(address minter) external view returns (bool);
function transferAndCall(
address to,
uint256 value,
bytes calldata data
) external returns (bool);
function formula() external view returns (address);
}
interface IERC2917 is ERC20 {
/// @dev This emit when interests amount per block is changed by the owner of the contract.
/// It emits with the old interests amount and the new interests amount.
event InterestRatePerBlockChanged(uint256 oldValue, uint256 newValue);
/// @dev This emit when a users' productivity has changed
/// It emits with the user's address and the the value after the change.
event ProductivityIncreased(address indexed user, uint256 value);
/// @dev This emit when a users' productivity has changed
/// It emits with the user's address and the the value after the change.
event ProductivityDecreased(address indexed user, uint256 value);
/// @dev Return the current contract's interests rate per block.
/// @return The amount of interests currently producing per each block.
function interestsPerBlock() external view returns (uint256);
/// @notice Change the current contract's interests rate.
/// @dev Note the best practice will be restrict the gross product provider's contract address to call this.
/// @return The true/fase to notice that the value has successfully changed or not, when it succeed, it will emite the InterestRatePerBlockChanged event.
function changeInterestRatePerBlock(uint256 value) external returns (bool);
/// @notice It will get the productivity of given user.
/// @dev it will return 0 if user has no productivity proved in the contract.
/// @return user's productivity and overall productivity.
function getProductivity(address user)
external
view
returns (uint256, uint256);
/// @notice increase a user's productivity.
/// @dev Note the best practice will be restrict the callee to prove of productivity's contract address.
/// @return true to confirm that the productivity added success.
function increaseProductivity(address user, uint256 value)
external
returns (bool);
/// @notice decrease a user's productivity.
/// @dev Note the best practice will be restrict the callee to prove of productivity's contract address.
/// @return true to confirm that the productivity removed success.
function decreaseProductivity(address user, uint256 value)
external
returns (bool);
/// @notice take() will return the interests that callee will get at current block height.
/// @dev it will always calculated by block.number, so it will change when block height changes.
/// @return amount of the interests that user are able to mint() at current block height.
function take() external view returns (uint256);
/// @notice similar to take(), but with the block height joined to calculate return.
/// @dev for instance, it returns (_amount, _block), which means at block height _block, the callee has accumulated _amount of interests.
/// @return amount of interests and the block height.
function takeWithBlock() external view returns (uint256, uint256);
/// @notice mint the avaiable interests to callee.
/// @dev once it mint, the amount of interests will transfer to callee's address.
/// @return the amount of interests minted.
function mint() external returns (uint256);
}
interface Staking {
struct Staker {
// The staked DAI amount
uint256 stakedDAI;
// The latest block number which the
// staker has staked tokens
uint256 lastStake;
}
function stakeDAI(uint256 amount) external;
function withdrawStake() external;
function stakers(address staker) external view returns (Staker memory);
}
interface Uniswap {
function swapExactETHForTokens(
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external payable returns (uint256[] memory amounts);
function swapExactTokensForETH(
uint256 amountIn,
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external returns (uint256[] memory amounts);
function swapExactTokensForTokens(
uint256 amountIn,
uint256 amountOutMin,
address[] calldata path,
address to,
uint256 deadline
) external returns (uint256[] memory amounts);
function WETH() external pure returns (address);
function factory() external pure returns (address);
function quote(
uint256 amountA,
uint256 reserveA,
uint256 reserveB
) external pure returns (uint256 amountB);
function getAmountIn(
uint256 amountOut,
uint256 reserveIn,
uint256 reserveOut
) external pure returns (uint256 amountIn);
function getAmountOut(
uint256 amountI,
uint256 reserveIn,
uint256 reserveOut
) external pure returns (uint256 amountOut);
function getAmountsOut(uint256 amountIn, address[] memory path)
external
pure
returns (uint256[] memory amounts);
}
interface UniswapFactory {
function getPair(address tokenA, address tokenB)
external
view
returns (address);
}
interface UniswapPair {
function getReserves()
external
view
returns (
uint112 reserve0,
uint112 reserve1,
uint32 blockTimestampLast
);
function kLast() external view returns (uint256);
function token0() external view returns (address);
function token1() external view returns (address);
function totalSupply() external view returns (uint256);
function balanceOf(address owner) external view returns (uint256);
}
interface Reserve {
function buy(
address _buyWith,
uint256 _tokenAmount,
uint256 _minReturn
) external returns (uint256);
}
interface IIdentity {
function isWhitelisted(address user) external view returns (bool);
function addWhitelistedWithDID(address account, string memory did) external;
function removeWhitelisted(address account) external;
function addIdentityAdmin(address account) external returns (bool);
function setAvatar(address _avatar) external;
function isIdentityAdmin(address account) external view returns (bool);
function owner() external view returns (address);
event WhitelistedAdded(address user);
}
interface IUBIScheme {
function currentDay() external view returns (uint256);
function periodStart() external view returns (uint256);
function hasClaimed(address claimer) external view returns (bool);
}
interface IFirstClaimPool {
function awardUser(address user) external returns (uint256);
function claimAmount() external view returns (uint256);
}
interface ProxyAdmin {
function getProxyImplementation(address proxy)
external
view
returns (address);
function getProxyAdmin(address proxy) external view returns (address);
function upgrade(address proxy, address implementation) external;
function owner() external view returns (address);
function transferOwnership(address newOwner) external;
}
/**
* @dev Interface for chainlink oracles to obtain price datas
*/
interface AggregatorV3Interface {
function decimals() external view returns (uint8);
function description() external view returns (string memory);
function version() external view returns (uint256);
// getRoundData and latestRoundData should both raise "No data present"
// if they do not have data to report, instead of returning unset values
// which could be misinterpreted as actual reported values.
function getRoundData(uint80 _roundId)
external
view
returns (
uint80 roundId,
int256 answer,
uint256 startedAt,
uint256 updatedAt,
uint80 answeredInRound
);
function latestAnswer() external view returns (int256);
}
/**
@dev interface for AAVE lending Pool
*/
interface ILendingPool {
/**
* @dev Deposits an `amount` of underlying asset into the reserve, receiving in return overlying aTokens.
* - E.g. User deposits 100 USDC and gets in return 100 aUSDC
* @param asset The address of the underlying asset to deposit
* @param amount The amount to be deposited
* @param onBehalfOf The address that will receive the aTokens, same as msg.sender if the user
* wants to receive them on his own wallet, or a different address if the beneficiary of aTokens
* is a different wallet
* @param referralCode Code used to register the integrator originating the operation, for potential rewards.
* 0 if the action is executed directly by the user, without any middle-man
**/
function deposit(
address asset,
uint256 amount,
address onBehalfOf,
uint16 referralCode
) external;
/**
* @dev Withdraws an `amount` of underlying asset from the reserve, burning the equivalent aTokens owned
* E.g. User has 100 aUSDC, calls withdraw() and receives 100 USDC, burning the 100 aUSDC
* @param asset The address of the underlying asset to withdraw
* @param amount The underlying amount to be withdrawn
* - Send the value type(uint256).max in order to withdraw the whole aToken balance
* @param to Address that will receive the underlying, same as msg.sender if the user
* wants to receive it on his own wallet, or a different address if the beneficiary is a
* different wallet
* @return The final amount withdrawn
**/
function withdraw(
address asset,
uint256 amount,
address to
) external returns (uint256);
/**
* @dev Returns the state and configuration of the reserve
* @param asset The address of the underlying asset of the reserve
* @return The state of the reserve
**/
function getReserveData(address asset)
external
view
returns (DataTypes.ReserveData memory);
}
interface IDonationStaking {
function stakeDonations() external payable;
}
interface INameService {
function getAddress(string memory _name) external view returns (address);
}
interface IAaveIncentivesController {
/**
* @dev Claims reward for an user, on all the assets of the lending pool, accumulating the pending rewards
* @param amount Amount of rewards to claim
* @param to Address that will be receiving the rewards
* @return Rewards claimed
**/
function claimRewards(
address[] calldata assets,
uint256 amount,
address to
) external returns (uint256);
/**
* @dev Returns the total of rewards of an user, already accrued + not yet accrued
* @param user The address of the user
* @return The rewards
**/
function getRewardsBalance(address[] calldata assets, address user)
external
view
returns (uint256);
}
interface IGoodStaking {
function collectUBIInterest(address recipient)
external
returns (
uint256,
uint256,
uint256
);
function iToken() external view returns (address);
function currentGains(
bool _returnTokenBalanceInUSD,
bool _returnTokenGainsInUSD
)
external
view
returns (
uint256,
uint256,
uint256,
uint256,
uint256
);
function getRewardEarned(address user) external view returns (uint256);
function getGasCostForInterestTransfer() external view returns (uint256);
function rewardsMinted(
address user,
uint256 rewardsPerBlock,
uint256 blockStart,
uint256 blockEnd
) external returns (uint256);
}
interface IHasRouter {
function getRouter() external view returns (Uniswap);
}
interface IAdminWallet {
function addAdmins(address payable[] memory _admins) external;
function removeAdmins(address[] memory _admins) external;
function owner() external view returns (address);
function transferOwnership(address _owner) external;
}
// File contracts/utils/DAOContract.sol
/**
@title Simple contract that keeps DAO contracts registery
*/
contract DAOContract {
Controller public dao;
address public avatar;
INameService public nameService;
function _onlyAvatar() internal view {
require(
address(dao.avatar()) == msg.sender,
"only avatar can call this method"
);
}
function setDAO(INameService _ns) internal {
nameService = _ns;
updateAvatar();
}
function updateAvatar() public {
dao = Controller(nameService.getAddress("CONTROLLER"));
avatar = dao.avatar();
}
function nativeToken() public view returns (IGoodDollar) {
return IGoodDollar(nameService.getAddress("GOODDOLLAR"));
}
uint256[50] private gap;
}
// File contracts/utils/DAOUpgradeableContract.sol
/**
@title Simple contract that adds upgradability to DAOContract
*/
contract DAOUpgradeableContract is Initializable, UUPSUpgradeable, DAOContract {
function _authorizeUpgrade(address) internal virtual override {
_onlyAvatar();
}
}
// File contracts/utils/NameService.sol
/**
@title Simple name to address resolver
*/
contract NameService is Initializable, UUPSUpgradeable {
mapping(bytes32 => address) public addresses;
Controller public dao;
event AddressChanged(string name ,address addr);
function initialize(
Controller _dao,
bytes32[] memory _nameHashes,
address[] memory _addresses
) public virtual initializer {
dao = _dao;
for (uint256 i = 0; i < _nameHashes.length; i++) {
addresses[_nameHashes[i]] = _addresses[i];
}
addresses[keccak256(bytes("CONTROLLER"))] = address(_dao);
addresses[keccak256(bytes("AVATAR"))] = address(_dao.avatar());
}
function _authorizeUpgrade(address) internal override {
_onlyAvatar();
}
function _onlyAvatar() internal view {
require(
address(dao.avatar()) == msg.sender,
"only avatar can call this method"
);
}
function setAddress(string memory name, address addr) external {
_onlyAvatar();
addresses[keccak256(bytes(name))] = addr;
emit AddressChanged(name, addr);
}
function setAddresses(bytes32[] calldata hash, address[] calldata addrs)
external
{
_onlyAvatar();
for (uint256 i = 0; i < hash.length; i++) {
addresses[hash[i]] = addrs[i];
}
}
function getAddress(string memory name) external view returns (address) {
return addresses[keccak256(bytes(name))];
}
}
// File contracts/utils/DSMath.sol
/// math.sol -- mixin for inline numerical wizardry
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
contract DSMath {
function rmul(uint256 x, uint256 y) internal pure returns (uint256 z) {
z = (x * y) / 10**27;
}
function rdiv(uint256 x, uint256 y) internal pure returns (uint256 z) {
z = (x * (10**27)) / y;
}
}
// File contracts/governance/MultiBaseGovernanceShareField.sol
/***
* supports accounting for multiple staking contracts to calculate GDAO rewards
*/
abstract contract MultiBaseGovernanceShareField is DSMath {
// Total Amount of stakes
mapping(address => uint256) totalProductivity;
// Reward amount of the each share
mapping(address => uint256) accAmountPerShare;
// Amount of the rewards which minted so far
mapping(address => uint256) public rewardsMintedSoFar;
// Amount of the rewards with pending and minted ones together
mapping(address => uint256) public totalRewardsAccumulated;
// Block number of last reward calculation made
mapping(address => uint256) public lastRewardBlock;
// Rewards amount that will be provided each block
mapping(address => uint256) public rewardsPerBlock;
struct UserInfo {
uint256 amount; // How many tokens the user has staked.
uint256 rewardDebt; // Rewards that accounted already so should be substracted while calculating rewards of staker
uint256 rewardEarn; // Reward earn and not minted
uint256 rewardMinted; // rewards sent to the user
}
mapping(address => mapping(address => UserInfo)) public contractToUsers;
function getChainBlocksPerMonth() public virtual returns (uint256);
/**
* @dev Calculate rewards per block from monthly amount of rewards and set it
* @param _monthlyAmount total rewards which will distribute monthly
*/
function _setMonthlyRewards(address _contract, uint256 _monthlyAmount)
internal
{
rewardsPerBlock[_contract] = _monthlyAmount / getChainBlocksPerMonth();
}
/**
* @dev Update reward variables of the given pool to be up-to-date.
* Make reward calculations according to passed blocks and updates rewards by
* multiplying passed blocks since last calculation with rewards per block value
* and add it to accumalated amount per share by dividing total productivity
*/
function _update(
address _contract,
uint256 _blockStart,
uint256 _blockEnd
) internal virtual {
if (totalProductivity[_contract] == 0) {
lastRewardBlock[_contract] = block.number;
return;
}
(uint256 _lastRewardBlock, uint256 _accAmountPerShare) = _calcUpdate(
_contract,
_blockStart,
_blockEnd
);
accAmountPerShare[_contract] = _accAmountPerShare;
lastRewardBlock[_contract] = _lastRewardBlock;
}
/**
* @dev helper to calculate global rewards accumulated per block so far
* @param _contract the contract to calcualte the rewards for
* @param _blockStart the block from which the contract is eligble for rewards
* @param _blockEnd the block from which the contract is no longer eligble for rewards
*/
function _calcUpdate(
address _contract,
uint256 _blockStart,
uint256 _blockEnd
)
internal
view
returns (uint256 _lastRewardBlock, uint256 _accAmountPerShare)
{
_accAmountPerShare = accAmountPerShare[_contract];
_lastRewardBlock = lastRewardBlock[_contract];
_lastRewardBlock = _lastRewardBlock < _blockStart &&
block.number >= _blockStart
? _blockStart
: _lastRewardBlock;
uint256 curRewardBlock = block.number > _blockEnd
? _blockEnd
: block.number;
if (curRewardBlock < _blockStart || _lastRewardBlock >= _blockEnd)
return (_lastRewardBlock, _accAmountPerShare);
uint256 multiplier = curRewardBlock - _lastRewardBlock; // Blocks passed since last reward block
uint256 reward = multiplier * rewardsPerBlock[_contract]; // rewardsPerBlock is in GDAO which is in 18 decimals
_accAmountPerShare += (reward * 1e27) / totalProductivity[_contract]; // totalProductivity in 18decimals and reward in 18 decimals so rdiv result in 27decimals
_lastRewardBlock = curRewardBlock;
}
/**
* @dev Audit user's rewards and calculate their earned rewards based on stake_amount * accAmountPerShare
*/
function _audit(
address _contract,
address _user,
uint256 _updatedAmount
) internal virtual {
UserInfo storage userInfo = contractToUsers[_contract][_user];
if (userInfo.amount > 0) {
uint256 pending = (userInfo.amount * accAmountPerShare[_contract]) /
1e27 -
userInfo.rewardDebt; // Divide 1e27(because userinfo.amount in 18 decimals and accAmountPerShare is in 27decimals) since rewardDebt in 18 decimals so we can calculate how much reward earned in that cycle
userInfo.rewardEarn = userInfo.rewardEarn + pending; // Add user's earned rewards to user's account so it can be minted later
totalRewardsAccumulated[_contract] =
totalRewardsAccumulated[_contract] +
pending;
}
userInfo.amount = _updatedAmount;
userInfo.rewardDebt =
(_updatedAmount * accAmountPerShare[_contract]) /
1e27; // Divide to 1e27 to keep rewardDebt in 18 decimals since accAmountPerShare is in 27 decimals and amount is 18 decimals
}
/**
* @dev This function increase user's productivity and updates the global productivity.
* This function increase user's productivity and updates the global productivity.
* the users' actual share percentage will calculated by:
* Formula: user_productivity / global_productivity
*/
function _increaseProductivity(
address _contract,
address _user,
uint256 _value,
uint256 _blockStart,
uint256 _blockEnd
) internal virtual returns (bool) {
_update(_contract, _blockStart, _blockEnd);
_audit(_contract, _user, contractToUsers[_contract][_user].amount + _value);
totalProductivity[_contract] = totalProductivity[_contract] + _value;
return true;
}
/**
* @dev This function will decreases user's productivity by value, and updates the global productivity
* it will record which block this is happenning and accumulates the area of (productivity * time)
*/
function _decreaseProductivity(
address _contract,
address _user,
uint256 _value,
uint256 _blockStart,
uint256 _blockEnd
) internal virtual returns (bool) {
_update(_contract, _blockStart, _blockEnd);
_audit(_contract, _user, contractToUsers[_contract][_user].amount - _value);
totalProductivity[_contract] = totalProductivity[_contract] - _value;
return true;
}
/**
* @dev Query user's pending reward with updated variables
* @param _contract the contract to calcualte the rewards for
* @param _blockStart the block from which the contract is eligble for rewards
* @param _blockEnd the block from which the contract is no longer eligble for rewards
* @param _user the user to calculate rewards for
* @return returns amount of user's earned but not minted rewards
*/
function getUserPendingReward(
address _contract,
uint256 _blockStart,
uint256 _blockEnd,
address _user
) public view returns (uint256) {
UserInfo memory userInfo = contractToUsers[_contract][_user];
uint256 pending = 0;
if (totalProductivity[_contract] != 0) {
(, uint256 _accAmountPerShare) = _calcUpdate(
_contract,
_blockStart,
_blockEnd
);
pending = userInfo.rewardEarn;
pending +=
(userInfo.amount * _accAmountPerShare) /
1e27 -
userInfo.rewardDebt; // Divide 1e27(because userinfo.amount in 18 decimals and accAmountPerShare is in 27decimals) since rewardDebt in 18 decimals so we can calculate how much reward earned in that cycle
}
return pending;
}
/**
@dev Calculate earned rewards of the user and update their reward info
* @param _contract address of the contract for accounting
* @param _user address of the user that will be accounted
* @param _blockStart the block from which the contract is eligble for rewards
* @param _blockEnd the block from which the contract is no longer eligble for rewards
* @return returns minted amount
*/
function _issueEarnedRewards(
address _contract,
address _user,
uint256 _blockStart,
uint256 _blockEnd
) internal returns (uint256) {
_update(_contract, _blockStart, _blockEnd);
_audit(_contract, _user, contractToUsers[_contract][_user].amount);
UserInfo storage userInfo = contractToUsers[_contract][_user];
uint256 amount = userInfo.rewardEarn;
userInfo.rewardEarn = 0;
userInfo.rewardMinted += amount;
rewardsMintedSoFar[_contract] = rewardsMintedSoFar[_contract] + amount;
return amount;
}
/**
* @return Returns how much productivity a user has and total productivity.
*/
function getProductivity(address _contract, address _user)
public
view
virtual
returns (uint256, uint256)
{
return (
contractToUsers[_contract][_user].amount,
totalProductivity[_contract]
);
}
/**
* @return Returns the current gross product rate.
*/
function totalRewardsPerShare(address _contract)
public
view
virtual
returns (uint256)
{
return accAmountPerShare[_contract];
}
// for upgrades
uint256[50] private _gap;
}
// File @openzeppelin/contracts-upgradeable/security/ReentrancyGuardUpgradeable.sol@v4.3.2
/**
* @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 ReentrancyGuardUpgradeable is Initializable {
// 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;
function __ReentrancyGuard_init() internal initializer {
__ReentrancyGuard_init_unchained();
}
function __ReentrancyGuard_init_unchained() internal initializer {
_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 make it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
// On the first call to nonReentrant, _notEntered will be true
require(_status != _ENTERED, "ReentrancyGuard: reentrant call");
// Any calls to nonReentrant after this point will fail
_status = _ENTERED;
_;
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = _NOT_ENTERED;
}
uint256[49] private __gap;
}
// File contracts/governance/GovarnanceStaking.sol
/**
* @title Staking contract that allows citizens to stake G$ to get GDAO rewards
*/
contract GovernanceStaking is
ERC20Upgradeable,
MultiBaseGovernanceShareField,
DAOUpgradeableContract,
ReentrancyGuardUpgradeable
{
uint256 public constant FUSE_MONTHLY_BLOCKS = 12 * 60 * 24 * 30;
// Token address
ERC20 token;
/**
* @dev Emitted when `staker` withdraws their rewards `value` tokens
*/
event ReputationEarned(address indexed staker, uint256 value);
/**
* @dev Constructor
* @param _ns The address of the INameService contract
*/
constructor(INameService _ns) {
setDAO(_ns);
token = ERC20(nameService.getAddress("GOODDOLLAR"));
__ERC20_init("G$ Staking For GOOD", "sG$");
rewardsPerBlock[address(this)] = (2 ether * 1e6) / FUSE_MONTHLY_BLOCKS; // (2M monthly GDAO as specified in specs, divided by blocks in month )
}
/**
* @dev this contract runs on fuse
*/
function getChainBlocksPerMonth() public pure override returns (uint256) {
return 518400; //12 * 60 * 24 * 30
}
/**
* @dev Allows a staker to deposit Tokens. Notice that `approve` is
* needed to be executed before the execution of this method.
* Can be executed only when the contract is not paused.
* @param _amount The amount of GD to stake
*/
function stake(uint256 _amount) external {
require(_amount > 0, "You need to stake a positive token amount");
require(
token.transferFrom(_msgSender(), address(this), _amount),
"transferFrom failed, make sure you approved token transfer"
);
_increaseProductivity(
address(this),
_msgSender(),
_amount,
0,
block.number
);
_mint(_msgSender(), _amount); // mint Staking token for staker
_mintRewards(_msgSender());
}
/**
* @dev Withdraws the sender staked Token.
*/
function withdrawStake(uint256 _amount) external nonReentrant {
(uint256 userProductivity, ) = getProductivity(address(this), _msgSender());
if (_amount == 0) _amount = userProductivity;
require(_amount > 0, "Should withdraw positive amount");
require(userProductivity >= _amount, "Not enough token staked");
uint256 tokenWithdraw = _amount;
_burn(_msgSender(), _amount); // burn their staking tokens
_decreaseProductivity(
address(this),
_msgSender(),
_amount,
0,
block.number
);
_mintRewards(_msgSender());
require(
token.transfer(_msgSender(), tokenWithdraw),
"withdraw transfer failed"
);
}
/**
* @dev Staker can withdraw their rewards without withdraw their stake
*/
function withdrawRewards() public nonReentrant returns (uint256) {
return _mintRewards(_msgSender());
}
/**
* @dev Mint rewards of the staker
* @param user Receipent address of the rewards
* @return Returns amount of the minted rewards
*/
function _mintRewards(address user) internal returns (uint256) {
uint256 amount = _issueEarnedRewards(address(this), user, 0, block.number);
if (amount > 0) {
ERC20(nameService.getAddress("REPUTATION")).mint(user, amount);
emit ReputationEarned(_msgSender(), amount);
}
return amount;
}
/**
* @dev Returns the number of decimals used to get its user representation.
*/
function decimals() public view virtual override returns (uint8) {
return 2;
}
/**
* @dev override _transfer to handle rewards calculations when transfer the stake
*/
function _transfer(
address from,
address to,
uint256 value
) internal override {
_decreaseProductivity(address(this), from, value, 0, block.number);
_increaseProductivity(address(this), to, value, 0, block.number);
_mintRewards(from);
_mintRewards(to);
super._transfer(from, to, value);
}
/**
* @dev Calculate rewards per block from monthly amount of rewards and set it
* @param _monthlyAmount total rewards which will distribute monthly
*/
function setMonthlyRewards(uint256 _monthlyAmount) public {
_onlyAvatar();
_setMonthlyRewards(address(this), _monthlyAmount);
}
/// @dev helper function for multibase
function getRewardsPerBlock() public view returns (uint256) {
return rewardsPerBlock[address(this)];
}
/// @dev helper function for multibase
function getProductivity(address _user)
public
view
returns (uint256, uint256)
{
return getProductivity(address(this), _user);
}
/// @dev helper function for multibase
function getUserPendingReward(address _user) public view returns (uint256) {
return getUserPendingReward(address(this), 0, block.number, _user);
}
/// @dev helper function for multibase
function users(address _user) public view returns (UserInfo memory) {
return contractToUsers[address(this)][_user];
}
function totalRewardsPerShare() public view returns (uint256) {
return totalRewardsPerShare(address(this));
}
}

Contract ABI

[{"type":"constructor","stateMutability":"nonpayable","inputs":[{"type":"address","name":"_ns","internalType":"contract INameService"}]},{"type":"event","name":"AdminChanged","inputs":[{"type":"address","name":"previousAdmin","internalType":"address","indexed":false},{"type":"address","name":"newAdmin","internalType":"address","indexed":false}],"anonymous":false},{"type":"event","name":"Approval","inputs":[{"type":"address","name":"owner","internalType":"address","indexed":true},{"type":"address","name":"spender","internalType":"address","indexed":true},{"type":"uint256","name":"value","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"BeaconUpgraded","inputs":[{"type":"address","name":"beacon","internalType":"address","indexed":true}],"anonymous":false},{"type":"event","name":"ReputationEarned","inputs":[{"type":"address","name":"staker","internalType":"address","indexed":true},{"type":"uint256","name":"value","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"Transfer","inputs":[{"type":"address","name":"from","internalType":"address","indexed":true},{"type":"address","name":"to","internalType":"address","indexed":true},{"type":"uint256","name":"value","internalType":"uint256","indexed":false}],"anonymous":false},{"type":"event","name":"Upgraded","inputs":[{"type":"address","name":"implementation","internalType":"address","indexed":true}],"anonymous":false},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"FUSE_MONTHLY_BLOCKS","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"allowance","inputs":[{"type":"address","name":"owner","internalType":"address"},{"type":"address","name":"spender","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"approve","inputs":[{"type":"address","name":"spender","internalType":"address"},{"type":"uint256","name":"amount","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"address"}],"name":"avatar","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"balanceOf","inputs":[{"type":"address","name":"account","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"amount","internalType":"uint256"},{"type":"uint256","name":"rewardDebt","internalType":"uint256"},{"type":"uint256","name":"rewardEarn","internalType":"uint256"},{"type":"uint256","name":"rewardMinted","internalType":"uint256"}],"name":"contractToUsers","inputs":[{"type":"address","name":"","internalType":"address"},{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract Controller"}],"name":"dao","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint8","name":"","internalType":"uint8"}],"name":"decimals","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"decreaseAllowance","inputs":[{"type":"address","name":"spender","internalType":"address"},{"type":"uint256","name":"subtractedValue","internalType":"uint256"}]},{"type":"function","stateMutability":"pure","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getChainBlocksPerMonth","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"},{"type":"uint256","name":"","internalType":"uint256"}],"name":"getProductivity","inputs":[{"type":"address","name":"_user","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"},{"type":"uint256","name":"","internalType":"uint256"}],"name":"getProductivity","inputs":[{"type":"address","name":"_contract","internalType":"address"},{"type":"address","name":"_user","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getRewardsPerBlock","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getUserPendingReward","inputs":[{"type":"address","name":"_contract","internalType":"address"},{"type":"uint256","name":"_blockStart","internalType":"uint256"},{"type":"uint256","name":"_blockEnd","internalType":"uint256"},{"type":"address","name":"_user","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"getUserPendingReward","inputs":[{"type":"address","name":"_user","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"increaseAllowance","inputs":[{"type":"address","name":"spender","internalType":"address"},{"type":"uint256","name":"addedValue","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"lastRewardBlock","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"name","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract INameService"}],"name":"nameService","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"address","name":"","internalType":"contract IGoodDollar"}],"name":"nativeToken","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"rewardsMintedSoFar","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"rewardsPerBlock","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"setMonthlyRewards","inputs":[{"type":"uint256","name":"_monthlyAmount","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"stake","inputs":[{"type":"uint256","name":"_amount","internalType":"uint256"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"string","name":"","internalType":"string"}],"name":"symbol","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalRewardsAccumulated","inputs":[{"type":"address","name":"","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalRewardsPerShare","inputs":[{"type":"address","name":"_contract","internalType":"address"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalRewardsPerShare","inputs":[]},{"type":"function","stateMutability":"view","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"totalSupply","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"transfer","inputs":[{"type":"address","name":"recipient","internalType":"address"},{"type":"uint256","name":"amount","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"bool","name":"","internalType":"bool"}],"name":"transferFrom","inputs":[{"type":"address","name":"sender","internalType":"address"},{"type":"address","name":"recipient","internalType":"address"},{"type":"uint256","name":"amount","internalType":"uint256"}]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"updateAvatar","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"upgradeTo","inputs":[{"type":"address","name":"newImplementation","internalType":"address"}]},{"type":"function","stateMutability":"payable","outputs":[],"name":"upgradeToAndCall","inputs":[{"type":"address","name":"newImplementation","internalType":"address"},{"type":"bytes","name":"data","internalType":"bytes"}]},{"type":"function","stateMutability":"view","outputs":[{"type":"tuple","name":"","internalType":"struct MultiBaseGovernanceShareField.UserInfo","components":[{"type":"uint256","name":"amount","internalType":"uint256"},{"type":"uint256","name":"rewardDebt","internalType":"uint256"},{"type":"uint256","name":"rewardEarn","internalType":"uint256"},{"type":"uint256","name":"rewardMinted","internalType":"uint256"}]}],"name":"users","inputs":[{"type":"address","name":"_user","internalType":"address"}]},{"type":"function","stateMutability":"nonpayable","outputs":[{"type":"uint256","name":"","internalType":"uint256"}],"name":"withdrawRewards","inputs":[]},{"type":"function","stateMutability":"nonpayable","outputs":[],"name":"withdrawStake","inputs":[{"type":"uint256","name":"_amount","internalType":"uint256"}]}]
            

Deployed ByteCode

0x6080604052600436106101aa5760003560e01c806306fdde03146101af578063095ea7b3146101da5780630c1cd7f31461020a57806318160ddd146102365780631b3c90a81461024b578063213b329e1461026257806322dec37b1461027857806323b872dd146102a557806325d5971f146102c557806328e964e9146102e55780632e42a8961461031a578063313ce5671461038757806331903da1146103a35780633659cfe6146103d057806339509351146103f05780633d9a12cc146104105780633e6326fc146104305780634162169f1461045e57806347b3e7e81461047f5780634f1db7f6146104ac5780634f1ef286146104cc5780635aef7de6146104df57806370a08231146105005780637bcbb9ff14610536578063846141b31461055657806395d89b4114610583578063a457c2d714610598578063a694fc3a146105b8578063a87430ba146105d8578063a9059cbb1461062b578063b46aa5271461064b578063bf8e9b6e14610662578063c671062914610677578063c76279a214610697578063c7b8981c146106b7578063dd62ed3e146106cc578063e1758bd814610712575b600080fd5b3480156101bb57600080fd5b506101c4610727565b6040516101d191906121e6565b60405180910390f35b3480156101e657600080fd5b506101fa6101f536600461222e565b6107b9565b60405190151581526020016101d1565b34801561021657600080fd5b50306000908152606a60205260409020545b6040519081526020016101d1565b34801561024257600080fd5b50603554610228565b34801561025757600080fd5b506102606107cf565b005b34801561026e57600080fd5b506207e900610228565b34801561028457600080fd5b5061022861029336600461225a565b60676020526000908152604090205481565b3480156102b157600080fd5b506101fa6102c0366004612277565b610917565b3480156102d157600080fd5b506102606102e03660046122b8565b6109c8565b3480156102f157600080fd5b5061030561030036600461225a565b610b9d565b604080519283526020830191909152016101d1565b34801561032657600080fd5b506103676103353660046122d1565b606b60209081526000928352604080842090915290825290208054600182015460028301546003909301549192909184565b6040805194855260208501939093529183015260608201526080016101d1565b34801561039357600080fd5b50604051600281526020016101d1565b3480156103af57600080fd5b506102286103be36600461225a565b60686020526000908152604090205481565b3480156103dc57600080fd5b506102606103eb36600461225a565b610bb3565b3480156103fc57600080fd5b506101fa61040b36600461222e565b610c7c565b34801561041c57600080fd5b5061022861042b36600461230a565b610cb8565b34801561043c57600080fd5b5061010454610451906001600160a01b031681565b6040516101d19190612354565b34801561046a57600080fd5b5061010254610451906001600160a01b031681565b34801561048b57600080fd5b5061022861049a36600461225a565b606a6020526000908152604090205481565b3480156104b857600080fd5b506103056104c73660046122d1565b610d7e565b6102606104da36600461237e565b610db7565b3480156104eb57600080fd5b5061010354610451906001600160a01b031681565b34801561050c57600080fd5b5061022861051b36600461225a565b6001600160a01b031660009081526033602052604090205490565b34801561054257600080fd5b5061022861055136600461225a565b610e71565b34801561056257600080fd5b5061022861057136600461225a565b60696020526000908152604090205481565b34801561058f57600080fd5b506101c4610e8c565b3480156105a457600080fd5b506101fa6105b336600461222e565b610e9b565b3480156105c457600080fd5b506102606105d33660046122b8565b610f34565b3480156105e457600080fd5b506105f86105f336600461225a565b6110c0565b6040516101d191908151815260208083015190820152604080830151908201526060918201519181019190915260800190565b34801561063757600080fd5b506101fa61064636600461222e565b611145565b34801561065757600080fd5b506102286207e90081565b34801561066e57600080fd5b50610228611152565b34801561068357600080fd5b5061022861069236600461225a565b611162565b3480156106a357600080fd5b506102606106b23660046122b8565b611177565b3480156106c357600080fd5b50610228611189565b3480156106d857600080fd5b506102286106e73660046122d1565b6001600160a01b03918216600090815260346020908152604080832093909416825291909152205490565b34801561071e57600080fd5b506104516111c9565b60606036805461073690612441565b80601f016020809104026020016040519081016040528092919081815260200182805461076290612441565b80156107af5780601f10610784576101008083540402835291602001916107af565b820191906000526020600020905b81548152906001019060200180831161079257829003601f168201915b5050505050905090565b60006107c6338484611261565b50600192915050565b6101045460405163bf40fac160e01b815260206004820152600a60248201526921a7a72a2927a62622a960b11b60448201526001600160a01b039091169063bf40fac19060640160206040518083038186803b15801561082e57600080fd5b505afa158015610842573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610866919061247c565b61010280546001600160a01b0319166001600160a01b0392909216918217905560408051632d77bef360e11b81529051635aef7de691600480820192602092909190829003018186803b1580156108bc57600080fd5b505afa1580156108d0573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108f4919061247c565b61010380546001600160a01b0319166001600160a01b0392909216919091179055565b6000610924848484611385565b6001600160a01b0384166000908152603460209081526040808320338452909152902054828110156109ae5760405162461bcd60e51b815260206004820152602860248201527f45524332303a207472616e7366657220616d6f756e74206578636565647320616044820152676c6c6f77616e636560c01b60648201526084015b60405180910390fd5b6109bb8533858403611261565b60019150505b9392505050565b60026101375414156109ec5760405162461bcd60e51b81526004016109a590612499565b60026101375560006109fe3033610d7e565b50905081610a0a578091505b60008211610a5a5760405162461bcd60e51b815260206004820152601f60248201527f53686f756c6420776974686472617720706f73697469766520616d6f756e740060448201526064016109a5565b81811015610aa45760405162461bcd60e51b8152602060048201526017602482015276139bdd08195b9bdd59da081d1bdad95b881cdd185ad959604a1b60448201526064016109a5565b81610aaf33846113c7565b610abd303385600043611503565b50610ac733611597565b50610169546001600160a01b031663a9059cbb33836040518363ffffffff1660e01b8152600401610af99291906124d0565b602060405180830381600087803b158015610b1357600080fd5b505af1158015610b27573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b4b91906124e9565b610b925760405162461bcd60e51b81526020600482015260186024820152771dda5d1a191c985dc81d1c985b9cd9995c8819985a5b195960421b60448201526064016109a5565b505060016101375550565b600080610baa3084610d7e565b91509150915091565b306001600160a01b037f000000000000000000000000faf457fb4a978be059506f6cd41f9b30fca753b0161415610bfc5760405162461bcd60e51b81526004016109a59061250b565b7f000000000000000000000000faf457fb4a978be059506f6cd41f9b30fca753b06001600160a01b0316610c2e611701565b6001600160a01b031614610c545760405162461bcd60e51b81526004016109a590612545565b610c5d8161171d565b60408051600080825260208201909252610c7991839190611725565b50565b3360008181526034602090815260408083206001600160a01b038716845290915281205490916107c6918590610cb3908690612595565b611261565b6001600160a01b038085166000818152606b60209081526040808320948616835293815283822084516080810186528154815260018201548184015260028201548187015260039091015460608201529282526065905291822054829015610d74576000610d2788888861186c565b915050826040015191508260200151676765c793fa10079d601b1b828560000151610d5291906125ad565b610d5c91906125cc565b610d6691906125ee565b610d709083612595565b9150505b9695505050505050565b6001600160a01b039182166000818152606b60209081526040808320949095168252928352838120549181526065909252919020549091565b306001600160a01b037f000000000000000000000000faf457fb4a978be059506f6cd41f9b30fca753b0161415610e005760405162461bcd60e51b81526004016109a59061250b565b7f000000000000000000000000faf457fb4a978be059506f6cd41f9b30fca753b06001600160a01b0316610e32611701565b6001600160a01b031614610e585760405162461bcd60e51b81526004016109a590612545565b610e618261171d565b610e6d82826001611725565b5050565b6001600160a01b031660009081526066602052604090205490565b60606037805461073690612441565b3360009081526034602090815260408083206001600160a01b038616845290915281205482811015610f1d5760405162461bcd60e51b815260206004820152602560248201527f45524332303a2064656372656173656420616c6c6f77616e63652062656c6f77604482015264207a65726f60d81b60648201526084016109a5565b610f2a3385858403611261565b5060019392505050565b60008111610f965760405162461bcd60e51b815260206004820152602960248201527f596f75206e65656420746f207374616b65206120706f73697469766520746f6b604482015268195b88185b5bdd5b9d60ba1b60648201526084016109a5565b610169546001600160a01b03166323b872dd336040516001600160e01b031960e084901b1681526001600160a01b03909116600482015230602482015260448101849052606401602060405180830381600087803b158015610ff757600080fd5b505af115801561100b573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061102f91906124e9565b61109e5760405162461bcd60e51b815260206004820152603a60248201527f7472616e7366657246726f6d206661696c65642c206d616b652073757265207960448201527937ba9030b8383937bb32b2103a37b5b2b7103a3930b739b332b960311b60648201526084016109a5565b6110ac303383600043611964565b506110b733826119ce565b610e6d33611597565b6110eb6040518060800160405280600081526020016000815260200160008152602001600081525090565b50306000908152606b602090815260408083206001600160a01b0394909416835292815290829020825160808101845281548152600182015492810192909252600281015492820192909252600390910154606082015290565b60006107c6338484611385565b600061115d30610e71565b905090565b60006111713060004385610cb8565b92915050565b61117f611a9b565b610c793082611b70565b600060026101375414156111af5760405162461bcd60e51b81526004016109a590612499565b6002610137556111be33611597565b905060016101375590565b6101045460405163bf40fac160e01b815260206004820152600a60248201526923a7a7a22227a62620a960b11b60448201526000916001600160a01b03169063bf40fac19060640160206040518083038186803b15801561122957600080fd5b505afa15801561123d573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061115d919061247c565b6001600160a01b0383166112c35760405162461bcd60e51b8152602060048201526024808201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646044820152637265737360e01b60648201526084016109a5565b6001600160a01b0382166113245760405162461bcd60e51b815260206004820152602260248201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604482015261737360f01b60648201526084016109a5565b6001600160a01b0383811660008181526034602090815260408083209487168084529482529182902085905590518481527f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b925910160405180910390a3505050565b611393308483600043611503565b506113a2308383600043611964565b506113ac83611597565b506113b682611597565b506113c2838383611b9d565b505050565b6001600160a01b0382166114275760405162461bcd60e51b815260206004820152602160248201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736044820152607360f81b60648201526084016109a5565b6001600160a01b0382166000908152603360205260409020548181101561149b5760405162461bcd60e51b815260206004820152602260248201527f45524332303a206275726e20616d6f756e7420657863656564732062616c616e604482015261636560f01b60648201526084016109a5565b6001600160a01b03831660009081526033602052604081208383039055603580548492906114ca9084906125ee565b90915550506040518281526000906001600160a01b038516906000805160206126a28339815191529060200160405180910390a3505050565b6000611510868484611d5b565b6001600160a01b038087166000908152606b602090815260408083209389168352929052205461154e90879087906115499088906125ee565b611dd6565b6001600160a01b0386166000908152606560205260409020546115729085906125ee565b6001600160a01b03871660009081526065602052604090205550600195945050505050565b6000806115a73084600043611eed565b90508015611171576101045460405163bf40fac160e01b815260206004820152600a6024820152692922a82aaa20aa24a7a760b11b60448201526001600160a01b039091169063bf40fac19060640160206040518083038186803b15801561160e57600080fd5b505afa158015611622573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611646919061247c565b6001600160a01b03166340c10f1984836040518363ffffffff1660e01b81526004016116739291906124d0565b602060405180830381600087803b15801561168d57600080fd5b505af11580156116a1573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906116c59190612605565b5060405181815233907f43848d0574703c28d68ae8958e0571521618f60c4bcacfb094cff2156eaae0f19060200160405180910390a292915050565b60008051602061265b833981519152546001600160a01b031690565b610c79611a9b565b600061172f611701565b905061173a84611fc3565b6000835111806117475750815b15611758576117568484612056565b505b7f4910fdfa16fed3260ed0e7147f7cc6da11a60208b5b9406d12a635614ffd9143805460ff1661186557805460ff191660011781556040516117d39086906117a4908590602401612354565b60408051601f198184030181529190526020810180516001600160e01b0316631b2ce7f360e11b179052612056565b50805460ff191681556117e4611701565b6001600160a01b0316826001600160a01b03161461185c5760405162461bcd60e51b815260206004820152602f60248201527f45524331393637557067726164653a207570677261646520627265616b73206660448201526e75727468657220757067726164657360881b60648201526084016109a5565b61186585612141565b5050505050565b6001600160a01b0383166000908152606660209081526040808320546069909252909120549083821080156118a15750834310155b6118ab57816118ad565b835b915060008343116118be57436118c0565b835b9050848110806118d05750838310155b156118db575061195c565b60006118e784836125ee565b6001600160a01b0388166000908152606a60205260408120549192509061190e90836125ad565b6001600160a01b03891660009081526065602052604090205490915061193f82676765c793fa10079d601b1b6125ad565b61194991906125cc565b6119539085612595565b93508294505050505b935093915050565b6000611971868484611d5b565b6001600160a01b038087166000908152606b60209081526040808320938916835292905220546119aa9087908790611549908890612595565b6001600160a01b038616600090815260656020526040902054611572908590612595565b6001600160a01b038216611a245760405162461bcd60e51b815260206004820152601f60248201527f45524332303a206d696e7420746f20746865207a65726f20616464726573730060448201526064016109a5565b8060356000828254611a369190612595565b90915550506001600160a01b03821660009081526033602052604081208054839290611a63908490612595565b90915550506040518181526001600160a01b038316906000906000805160206126a28339815191529060200160405180910390a35050565b6101025460408051632d77bef360e11b8152905133926001600160a01b031691635aef7de6916004808301926020929190829003018186803b158015611ae057600080fd5b505afa158015611af4573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190611b18919061247c565b6001600160a01b031614611b6e5760405162461bcd60e51b815260206004820181905260248201527f6f6e6c79206176617461722063616e2063616c6c2074686973206d6574686f6460448201526064016109a5565b565b611b7d6207e900826125cc565b6001600160a01b039092166000908152606a602052604090209190915550565b6001600160a01b038316611c015760405162461bcd60e51b815260206004820152602560248201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604482015264647265737360d81b60648201526084016109a5565b6001600160a01b038216611c635760405162461bcd60e51b815260206004820152602360248201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260448201526265737360e81b60648201526084016109a5565b6001600160a01b03831660009081526033602052604090205481811015611cdb5760405162461bcd60e51b815260206004820152602660248201527f45524332303a207472616e7366657220616d6f756e7420657863656564732062604482015265616c616e636560d01b60648201526084016109a5565b6001600160a01b03808516600090815260336020526040808220858503905591851681529081208054849290611d12908490612595565b92505081905550826001600160a01b0316846001600160a01b03166000805160206126a283398151915284604051611d4c91815260200190565b60405180910390a35b50505050565b6001600160a01b038316600090815260656020526040902054611d965750506001600160a01b03166000908152606960205260409020439055565b600080611da485858561186c565b6001600160a01b0390961660009081526066602090815260408083209890985560699052959095209490945550505050565b6001600160a01b038084166000908152606b60209081526040808320938616835292905220805415611ea55760018101546001600160a01b0385166000908152606660205260408120548354919291676765c793fa10079d601b1b91611e3b916125ad565b611e4591906125cc565b611e4f91906125ee565b9050808260020154611e619190612595565b60028301556001600160a01b038516600090815260686020526040902054611e8a908290612595565b6001600160a01b038616600090815260686020526040902055505b8181556001600160a01b038416600090815260666020526040902054676765c793fa10079d601b1b90611ed890846125ad565b611ee291906125cc565b600190910155505050565b6000611efa858484611d5b565b6001600160a01b038086166000908152606b6020908152604080832093881683529290522054611f2d9086908690611dd6565b6001600160a01b038086166000908152606b6020908152604080832093881683529290529081206002810180549083905560038201805492939192839290611f76908490612595565b90915550506001600160a01b038716600090815260676020526040902054611f9f908290612595565b6001600160a01b038816600090815260676020526040902055915050949350505050565b803b6120275760405162461bcd60e51b815260206004820152602d60248201527f455243313936373a206e657720696d706c656d656e746174696f6e206973206e60448201526c1bdd08184818dbdb9d1c9858dd609a1b60648201526084016109a5565b60008051602061265b83398151915280546001600160a01b0319166001600160a01b0392909216919091179055565b6060823b6120b55760405162461bcd60e51b815260206004820152602660248201527f416464726573733a2064656c65676174652063616c6c20746f206e6f6e2d636f6044820152651b9d1c9858dd60d21b60648201526084016109a5565b600080846001600160a01b0316846040516120d0919061261e565b600060405180830381855af49150503d806000811461210b576040519150601f19603f3d011682016040523d82523d6000602084013e612110565b606091505b5091509150612138828260405180606001604052806027815260200161267b60279139612181565b95945050505050565b61214a81611fc3565b6040516001600160a01b038216907fbc7cd75a20ee27fd9adebab32041f755214dbc6bffa90cc0225b39da2e5c2d3b90600090a250565b606083156121905750816109c1565b8251156121a05782518084602001fd5b8160405162461bcd60e51b81526004016109a591906121e6565b60005b838110156121d55781810151838201526020016121bd565b83811115611d555750506000910152565b60208152600082518060208401526122058160408501602087016121ba565b601f01601f19169190910160400192915050565b6001600160a01b0381168114610c7957600080fd5b6000806040838503121561224157600080fd5b823561224c81612219565b946020939093013593505050565b60006020828403121561226c57600080fd5b81356109c181612219565b60008060006060848603121561228c57600080fd5b833561229781612219565b925060208401356122a781612219565b929592945050506040919091013590565b6000602082840312156122ca57600080fd5b5035919050565b600080604083850312156122e457600080fd5b82356122ef81612219565b915060208301356122ff81612219565b809150509250929050565b6000806000806080858703121561232057600080fd5b843561232b81612219565b93506020850135925060408501359150606085013561234981612219565b939692955090935050565b6001600160a01b0391909116815260200190565b634e487b7160e01b600052604160045260246000fd5b6000806040838503121561239157600080fd5b823561239c81612219565b915060208301356001600160401b03808211156123b857600080fd5b818501915085601f8301126123cc57600080fd5b8135818111156123de576123de612368565b604051601f8201601f19908116603f0116810190838211818310171561240657612406612368565b8160405282815288602084870101111561241f57600080fd5b8260208601602083013760006020848301015280955050505050509250929050565b600181811c9082168061245557607f821691505b6020821081141561247657634e487b7160e01b600052602260045260246000fd5b50919050565b60006020828403121561248e57600080fd5b81516109c181612219565b6020808252601f908201527f5265656e7472616e637947756172643a207265656e7472616e742063616c6c00604082015260600190565b6001600160a01b03929092168252602082015260400190565b6000602082840312156124fb57600080fd5b815180151581146109c157600080fd5b6020808252602c9082015260008051602061263b83398151915260408201526b19195b1959d85d1958d85b1b60a21b606082015260800190565b6020808252602c9082015260008051602061263b83398151915260408201526b6163746976652070726f787960a01b606082015260800190565b634e487b7160e01b600052601160045260246000fd5b600082198211156125a8576125a861257f565b500190565b60008160001904831182151516156125c7576125c761257f565b500290565b6000826125e957634e487b7160e01b600052601260045260246000fd5b500490565b6000828210156126005761260061257f565b500390565b60006020828403121561261757600080fd5b5051919050565b600082516126308184602087016121ba565b919091019291505056fe46756e6374696f6e206d7573742062652063616c6c6564207468726f75676820360894a13ba1a3210667c828492db98dca3e2076cc3735a920a3ca505d382bbc416464726573733a206c6f772d6c6576656c2064656c65676174652063616c6c206661696c6564ddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3efa2646970667358221220dd36ed235a5821249088603d58d7d7165998695985429d53ffb30d213565231b64736f6c63430008080033