Feature Tip: Add private address tag to any address under My Name Tag !
Latest 2 internal transactions
Advanced mode:
| Parent Transaction Hash | Method | Block |
From
|
|
To
|
||
|---|---|---|---|---|---|---|---|
| - | 12125705 | 1792 days ago | Contract Creation | 0 ETH | |||
| - | 12125705 | 1792 days ago | Contract Creation | 0 ETH |
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
Core
Compiler Version
v0.6.6+commit.6c089d02
Contract Source Code (Solidity Standard Json-Input format)
pragma solidity ^0.6.0;
pragma experimental ABIEncoderV2;
import "@openzeppelin/contracts/proxy/Initializable.sol";
import "./Permissions.sol";
import "./ICore.sol";
import "../token/Fei.sol";
import "../dao/Tribe.sol";
/// @title Source of truth for Fei Protocol
/// @author Fei Protocol
/// @notice maintains roles, access control, fei, tribe, genesisGroup, and the TRIBE treasury
contract Core is ICore, Permissions, Initializable {
/// @notice the address of the FEI contract
IFei public override fei;
/// @notice the address of the TRIBE contract
IERC20 public override tribe;
/// @notice the address of the GenesisGroup contract
address public override genesisGroup;
/// @notice determines whether in genesis period or not
bool public override hasGenesisGroupCompleted;
function init() external override initializer {
_setupGovernor(msg.sender);
Fei _fei = new Fei(address(this));
_setFei(address(_fei));
Tribe _tribe = new Tribe(address(this), msg.sender);
_setTribe(address(_tribe));
}
/// @notice sets Fei address to a new address
/// @param token new fei address
function setFei(address token) external override onlyGovernor {
_setFei(token);
}
/// @notice sets Tribe address to a new address
/// @param token new tribe address
function setTribe(address token) external override onlyGovernor {
_setTribe(token);
}
/// @notice sets Genesis Group address
/// @param _genesisGroup new genesis group address
function setGenesisGroup(address _genesisGroup)
external
override
onlyGovernor
{
genesisGroup = _genesisGroup;
emit GenesisGroupUpdate(_genesisGroup);
}
/// @notice sends TRIBE tokens from treasury to an address
/// @param to the address to send TRIBE to
/// @param amount the amount of TRIBE to send
function allocateTribe(address to, uint256 amount)
external
override
onlyGovernor
{
IERC20 _tribe = tribe;
require(
_tribe.balanceOf(address(this)) >= amount,
"Core: Not enough Tribe"
);
_tribe.transfer(to, amount);
emit TribeAllocation(to, amount);
}
/// @notice marks the end of the genesis period
/// @dev can only be called once
function completeGenesisGroup() external override {
require(
!hasGenesisGroupCompleted,
"Core: Genesis Group already complete"
);
require(
msg.sender == genesisGroup,
"Core: Caller is not Genesis Group"
);
hasGenesisGroupCompleted = true;
// solhint-disable-next-line not-rely-on-time
emit GenesisPeriodComplete(block.timestamp);
}
function _setFei(address token) internal {
fei = IFei(token);
emit FeiUpdate(token);
}
function _setTribe(address token) internal {
tribe = IERC20(token);
emit TribeUpdate(token);
}
}pragma solidity ^0.6.0;
pragma experimental ABIEncoderV2;
import "@openzeppelin/contracts/access/AccessControl.sol";
import "./IPermissions.sol";
/// @title Access control module for Core
/// @author Fei Protocol
contract Permissions is IPermissions, AccessControl {
bytes32 public constant BURNER_ROLE = keccak256("BURNER_ROLE");
bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
bytes32 public constant PCV_CONTROLLER_ROLE = keccak256("PCV_CONTROLLER_ROLE");
bytes32 public constant GOVERN_ROLE = keccak256("GOVERN_ROLE");
bytes32 public constant GUARDIAN_ROLE = keccak256("GUARDIAN_ROLE");
constructor() public {
// Appointed as a governor so guardian can have indirect access to revoke ability
_setupGovernor(address(this));
_setRoleAdmin(MINTER_ROLE, GOVERN_ROLE);
_setRoleAdmin(BURNER_ROLE, GOVERN_ROLE);
_setRoleAdmin(PCV_CONTROLLER_ROLE, GOVERN_ROLE);
_setRoleAdmin(GOVERN_ROLE, GOVERN_ROLE);
_setRoleAdmin(GUARDIAN_ROLE, GOVERN_ROLE);
}
modifier onlyGovernor() {
require(
isGovernor(msg.sender),
"Permissions: Caller is not a governor"
);
_;
}
modifier onlyGuardian() {
require(isGuardian(msg.sender), "Permissions: Caller is not a guardian");
_;
}
/// @notice creates a new role to be maintained
/// @param role the new role id
/// @param adminRole the admin role id for `role`
/// @dev can also be used to update admin of existing role
function createRole(bytes32 role, bytes32 adminRole)
external
override
onlyGovernor
{
_setRoleAdmin(role, adminRole);
}
/// @notice grants minter role to address
/// @param minter new minter
function grantMinter(address minter) external override onlyGovernor {
grantRole(MINTER_ROLE, minter);
}
/// @notice grants burner role to address
/// @param burner new burner
function grantBurner(address burner) external override onlyGovernor {
grantRole(BURNER_ROLE, burner);
}
/// @notice grants controller role to address
/// @param pcvController new controller
function grantPCVController(address pcvController)
external
override
onlyGovernor
{
grantRole(PCV_CONTROLLER_ROLE, pcvController);
}
/// @notice grants governor role to address
/// @param governor new governor
function grantGovernor(address governor) external override onlyGovernor {
grantRole(GOVERN_ROLE, governor);
}
/// @notice grants guardian role to address
/// @param guardian new guardian
function grantGuardian(address guardian) external override onlyGovernor {
grantRole(GUARDIAN_ROLE, guardian);
}
/// @notice revokes minter role from address
/// @param minter ex minter
function revokeMinter(address minter) external override onlyGovernor {
revokeRole(MINTER_ROLE, minter);
}
/// @notice revokes burner role from address
/// @param burner ex burner
function revokeBurner(address burner) external override onlyGovernor {
revokeRole(BURNER_ROLE, burner);
}
/// @notice revokes pcvController role from address
/// @param pcvController ex pcvController
function revokePCVController(address pcvController)
external
override
onlyGovernor
{
revokeRole(PCV_CONTROLLER_ROLE, pcvController);
}
/// @notice revokes governor role from address
/// @param governor ex governor
function revokeGovernor(address governor) external override onlyGovernor {
revokeRole(GOVERN_ROLE, governor);
}
/// @notice revokes guardian role from address
/// @param guardian ex guardian
function revokeGuardian(address guardian) external override onlyGovernor {
revokeRole(GUARDIAN_ROLE, guardian);
}
/// @notice revokes a role from address
/// @param role the role to revoke
/// @param account the address to revoke the role from
function revokeOverride(bytes32 role, address account)
external
override
onlyGuardian
{
require(role != GOVERN_ROLE, "Permissions: Guardian cannot revoke governor");
// External call because this contract is appointed as a governor and has access to revoke
this.revokeRole(role, account);
}
/// @notice checks if address is a minter
/// @param _address address to check
/// @return true _address is a minter
function isMinter(address _address) external view override returns (bool) {
return hasRole(MINTER_ROLE, _address);
}
/// @notice checks if address is a burner
/// @param _address address to check
/// @return true _address is a burner
function isBurner(address _address) external view override returns (bool) {
return hasRole(BURNER_ROLE, _address);
}
/// @notice checks if address is a controller
/// @param _address address to check
/// @return true _address is a controller
function isPCVController(address _address)
external
view
override
returns (bool)
{
return hasRole(PCV_CONTROLLER_ROLE, _address);
}
/// @notice checks if address is a governor
/// @param _address address to check
/// @return true _address is a governor
// only virtual for testing mock override
function isGovernor(address _address)
public
view
virtual
override
returns (bool)
{
return hasRole(GOVERN_ROLE, _address);
}
/// @notice checks if address is a guardian
/// @param _address address to check
/// @return true _address is a guardian
function isGuardian(address _address) public view override returns (bool) {
return hasRole(GUARDIAN_ROLE, _address);
}
function _setupGovernor(address governor) internal {
_setupRole(GOVERN_ROLE, governor);
}
}pragma solidity ^0.6.0;
pragma experimental ABIEncoderV2;
/// @title Permissions interface
/// @author Fei Protocol
interface IPermissions {
// ----------- Governor only state changing api -----------
function createRole(bytes32 role, bytes32 adminRole) external;
function grantMinter(address minter) external;
function grantBurner(address burner) external;
function grantPCVController(address pcvController) external;
function grantGovernor(address governor) external;
function grantGuardian(address guardian) external;
function revokeMinter(address minter) external;
function revokeBurner(address burner) external;
function revokePCVController(address pcvController) external;
function revokeGovernor(address governor) external;
function revokeGuardian(address guardian) external;
// ----------- Revoker only state changing api -----------
function revokeOverride(bytes32 role, address account) external;
// ----------- Getters -----------
function isBurner(address _address) external view returns (bool);
function isMinter(address _address) external view returns (bool);
function isGovernor(address _address) external view returns (bool);
function isGuardian(address _address) external view returns (bool);
function isPCVController(address _address) external view returns (bool);
}pragma solidity ^0.6.0;
pragma experimental ABIEncoderV2;
import "./IPermissions.sol";
import "../token/IFei.sol";
/// @title Core Interface
/// @author Fei Protocol
interface ICore is IPermissions {
// ----------- Events -----------
event FeiUpdate(address indexed _fei);
event TribeUpdate(address indexed _tribe);
event GenesisGroupUpdate(address indexed _genesisGroup);
event TribeAllocation(address indexed _to, uint256 _amount);
event GenesisPeriodComplete(uint256 _timestamp);
// ----------- Governor only state changing api -----------
function init() external;
// ----------- Governor only state changing api -----------
function setFei(address token) external;
function setTribe(address token) external;
function setGenesisGroup(address _genesisGroup) external;
function allocateTribe(address to, uint256 amount) external;
// ----------- Genesis Group only state changing api -----------
function completeGenesisGroup() external;
// ----------- Getters -----------
function fei() external view returns (IFei);
function tribe() external view returns (IERC20);
function genesisGroup() external view returns (address);
function hasGenesisGroupCompleted() external view returns (bool);
}pragma solidity ^0.6.2;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
/// @title FEI stablecoin interface
/// @author Fei Protocol
interface IFei is IERC20 {
// ----------- Events -----------
event Minting(
address indexed _to,
address indexed _minter,
uint256 _amount
);
event Burning(
address indexed _to,
address indexed _burner,
uint256 _amount
);
event IncentiveContractUpdate(
address indexed _incentivized,
address indexed _incentiveContract
);
// ----------- State changing api -----------
function burn(uint256 amount) external;
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external;
// ----------- Burner only state changing api -----------
function burnFrom(address account, uint256 amount) external;
// ----------- Minter only state changing api -----------
function mint(address account, uint256 amount) external;
// ----------- Governor only state changing api -----------
function setIncentiveContract(address account, address incentive) external;
// ----------- Getters -----------
function incentiveContract(address account) external view returns (address);
}pragma solidity ^0.6.0;
pragma experimental ABIEncoderV2;
import "@openzeppelin/contracts/token/ERC20/ERC20Burnable.sol";
import "@openzeppelin/contracts/utils/Address.sol";
import "./IIncentive.sol";
import "./IFei.sol";
import "../refs/CoreRef.sol";
/// @title FEI stablecoin
/// @author Fei Protocol
contract Fei is IFei, ERC20Burnable, CoreRef {
/// @notice get associated incentive contract, 0 address if N/A
mapping(address => address) public override incentiveContract;
// solhint-disable-next-line var-name-mixedcase
bytes32 public DOMAIN_SEPARATOR;
// keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");
bytes32 public constant PERMIT_TYPEHASH =
0x6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9;
mapping(address => uint256) public nonces;
/// @notice Fei token constructor
/// @param core Fei Core address to reference
constructor(address core) public ERC20("Fei USD", "FEI") CoreRef(core) {
uint256 chainId;
// solhint-disable-next-line no-inline-assembly
assembly {
chainId := chainid()
}
DOMAIN_SEPARATOR = keccak256(
abi.encode(
keccak256(
"EIP712Domain(string name,string version,uint256 chainId,address verifyingContract)"
),
keccak256(bytes(name())),
keccak256(bytes("1")),
chainId,
address(this)
)
);
}
/// @param account the account to incentivize
/// @param incentive the associated incentive contract
function setIncentiveContract(address account, address incentive)
external
override
onlyGovernor
{
incentiveContract[account] = incentive;
emit IncentiveContractUpdate(account, incentive);
}
/// @notice mint FEI tokens
/// @param account the account to mint to
/// @param amount the amount to mint
function mint(address account, uint256 amount)
external
override
onlyMinter
whenNotPaused
{
_mint(account, amount);
emit Minting(account, msg.sender, amount);
}
/// @notice burn FEI tokens from caller
/// @param amount the amount to burn
function burn(uint256 amount) public override(IFei, ERC20Burnable) {
super.burn(amount);
emit Burning(msg.sender, msg.sender, amount);
}
/// @notice burn FEI tokens from specified account
/// @param account the account to burn from
/// @param amount the amount to burn
function burnFrom(address account, uint256 amount)
public
override(IFei, ERC20Burnable)
onlyBurner
whenNotPaused
{
_burn(account, amount);
emit Burning(account, msg.sender, amount);
}
function _transfer(
address sender,
address recipient,
uint256 amount
) internal override {
super._transfer(sender, recipient, amount);
_checkAndApplyIncentives(sender, recipient, amount);
}
function _checkAndApplyIncentives(
address sender,
address recipient,
uint256 amount
) internal {
// incentive on sender
address senderIncentive = incentiveContract[sender];
if (senderIncentive != address(0)) {
IIncentive(senderIncentive).incentivize(
sender,
recipient,
msg.sender,
amount
);
}
// incentive on recipient
address recipientIncentive = incentiveContract[recipient];
if (recipientIncentive != address(0)) {
IIncentive(recipientIncentive).incentivize(
sender,
recipient,
msg.sender,
amount
);
}
// incentive on operator
address operatorIncentive = incentiveContract[msg.sender];
if (
msg.sender != sender &&
msg.sender != recipient &&
operatorIncentive != address(0)
) {
IIncentive(operatorIncentive).incentivize(
sender,
recipient,
msg.sender,
amount
);
}
// all incentive, if active applies to every transfer
address allIncentive = incentiveContract[address(0)];
if (allIncentive != address(0)) {
IIncentive(allIncentive).incentivize(
sender,
recipient,
msg.sender,
amount
);
}
}
/// @notice permit spending of FEI
/// @param owner the FEI holder
/// @param spender the approved operator
/// @param value the amount approved
/// @param deadline the deadline after which the approval is no longer valid
function permit(
address owner,
address spender,
uint256 value,
uint256 deadline,
uint8 v,
bytes32 r,
bytes32 s
) external override {
// solhint-disable-next-line not-rely-on-time
require(deadline >= block.timestamp, "Fei: EXPIRED");
bytes32 digest =
keccak256(
abi.encodePacked(
"\x19\x01",
DOMAIN_SEPARATOR,
keccak256(
abi.encode(
PERMIT_TYPEHASH,
owner,
spender,
value,
nonces[owner]++,
deadline
)
)
)
);
address recoveredAddress = ecrecover(digest, v, r, s);
require(
recoveredAddress != address(0) && recoveredAddress == owner,
"Fei: INVALID_SIGNATURE"
);
_approve(owner, spender, value);
}
}pragma solidity ^0.6.2;
/// @title incentive contract interface
/// @author Fei Protocol
/// @notice Called by FEI token contract when transferring with an incentivized address
/// @dev should be appointed as a Minter or Burner as needed
interface IIncentive {
// ----------- Fei only state changing api -----------
/// @notice apply incentives on transfer
/// @param sender the sender address of the FEI
/// @param receiver the receiver address of the FEI
/// @param operator the operator (msg.sender) of the transfer
/// @param amount the amount of FEI transferred
function incentivize(
address sender,
address receiver,
address operator,
uint256 amount
) external;
}pragma solidity ^0.6.0;
pragma experimental ABIEncoderV2;
import "./ICoreRef.sol";
import "@openzeppelin/contracts/utils/Pausable.sol";
import "@openzeppelin/contracts/utils/Address.sol";
/// @title A Reference to Core
/// @author Fei Protocol
/// @notice defines some modifiers and utilities around interacting with Core
abstract contract CoreRef is ICoreRef, Pausable {
ICore private _core;
/// @notice CoreRef constructor
/// @param core Fei Core to reference
constructor(address core) public {
_core = ICore(core);
}
modifier ifMinterSelf() {
if (_core.isMinter(address(this))) {
_;
}
}
modifier ifBurnerSelf() {
if (_core.isBurner(address(this))) {
_;
}
}
modifier onlyMinter() {
require(_core.isMinter(msg.sender), "CoreRef: Caller is not a minter");
_;
}
modifier onlyBurner() {
require(_core.isBurner(msg.sender), "CoreRef: Caller is not a burner");
_;
}
modifier onlyPCVController() {
require(
_core.isPCVController(msg.sender),
"CoreRef: Caller is not a PCV controller"
);
_;
}
modifier onlyGovernor() {
require(
_core.isGovernor(msg.sender),
"CoreRef: Caller is not a governor"
);
_;
}
modifier onlyGuardianOrGovernor() {
require(
_core.isGovernor(msg.sender) ||
_core.isGuardian(msg.sender),
"CoreRef: Caller is not a guardian or governor"
);
_;
}
modifier onlyFei() {
require(msg.sender == address(fei()), "CoreRef: Caller is not FEI");
_;
}
modifier onlyGenesisGroup() {
require(
msg.sender == _core.genesisGroup(),
"CoreRef: Caller is not GenesisGroup"
);
_;
}
modifier postGenesis() {
require(
_core.hasGenesisGroupCompleted(),
"CoreRef: Still in Genesis Period"
);
_;
}
modifier nonContract() {
require(!Address.isContract(msg.sender), "CoreRef: Caller is a contract");
_;
}
/// @notice set new Core reference address
/// @param core the new core address
function setCore(address core) external override onlyGovernor {
_core = ICore(core);
emit CoreUpdate(core);
}
/// @notice set pausable methods to paused
function pause() public override onlyGuardianOrGovernor {
_pause();
}
/// @notice set pausable methods to unpaused
function unpause() public override onlyGuardianOrGovernor {
_unpause();
}
/// @notice address of the Core contract referenced
/// @return ICore implementation address
function core() public view override returns (ICore) {
return _core;
}
/// @notice address of the Fei contract referenced by Core
/// @return IFei implementation address
function fei() public view override returns (IFei) {
return _core.fei();
}
/// @notice address of the Tribe contract referenced by Core
/// @return IERC20 implementation address
function tribe() public view override returns (IERC20) {
return _core.tribe();
}
/// @notice fei balance of contract
/// @return fei amount held
function feiBalance() public view override returns (uint256) {
return fei().balanceOf(address(this));
}
/// @notice tribe balance of contract
/// @return tribe amount held
function tribeBalance() public view override returns (uint256) {
return tribe().balanceOf(address(this));
}
function _burnFeiHeld() internal {
fei().burn(feiBalance());
}
function _mintFei(uint256 amount) internal {
fei().mint(address(this), amount);
}
}pragma solidity ^0.6.0;
pragma experimental ABIEncoderV2;
import "../core/ICore.sol";
/// @title CoreRef interface
/// @author Fei Protocol
interface ICoreRef {
// ----------- Events -----------
event CoreUpdate(address indexed _core);
// ----------- Governor only state changing api -----------
function setCore(address core) external;
function pause() external;
function unpause() external;
// ----------- Getters -----------
function core() external view returns (ICore);
function fei() external view returns (IFei);
function tribe() external view returns (IERC20);
function feiBalance() external view returns (uint256);
function tribeBalance() external view returns (uint256);
}pragma solidity ^0.6.0;
pragma experimental ABIEncoderV2;
// Forked from Uniswap's UNI
// Reference: https://etherscan.io/address/0x1f9840a85d5af5bf1d1762f925bdaddc4201f984#code
contract Tribe {
/// @notice EIP-20 token name for this token
// solhint-disable-next-line const-name-snakecase
string public constant name = "Tribe";
/// @notice EIP-20 token symbol for this token
// solhint-disable-next-line const-name-snakecase
string public constant symbol = "TRIBE";
/// @notice EIP-20 token decimals for this token
// solhint-disable-next-line const-name-snakecase
uint8 public constant decimals = 18;
/// @notice Total number of tokens in circulation
// solhint-disable-next-line const-name-snakecase
uint public totalSupply = 1_000_000_000e18; // 1 billion Tribe
/// @notice Address which may mint new tokens
address public minter;
/// @notice Allowance amounts on behalf of others
mapping (address => mapping (address => uint96)) internal allowances;
/// @notice Official record of token balances for each account
mapping (address => uint96) internal balances;
/// @notice A record of each accounts delegate
mapping (address => address) public delegates;
/// @notice A checkpoint for marking number of votes from a given block
struct Checkpoint {
uint32 fromBlock;
uint96 votes;
}
/// @notice A record of votes checkpoints for each account, by index
mapping (address => mapping (uint32 => Checkpoint)) public checkpoints;
/// @notice The number of checkpoints for each account
mapping (address => uint32) public numCheckpoints;
/// @notice The EIP-712 typehash for the contract's domain
bytes32 public constant DOMAIN_TYPEHASH = keccak256("EIP712Domain(string name,uint256 chainId,address verifyingContract)");
/// @notice The EIP-712 typehash for the delegation struct used by the contract
bytes32 public constant DELEGATION_TYPEHASH = keccak256("Delegation(address delegatee,uint256 nonce,uint256 expiry)");
/// @notice The EIP-712 typehash for the permit struct used by the contract
bytes32 public constant PERMIT_TYPEHASH = keccak256("Permit(address owner,address spender,uint256 value,uint256 nonce,uint256 deadline)");
/// @notice A record of states for signing / validating signatures
mapping (address => uint) public nonces;
/// @notice An event thats emitted when the minter address is changed
event MinterChanged(address minter, address newMinter);
/// @notice An event thats emitted when an account changes its delegate
event DelegateChanged(address indexed delegator, address indexed fromDelegate, address indexed toDelegate);
/// @notice An event thats emitted when a delegate account's vote balance changes
event DelegateVotesChanged(address indexed delegate, uint previousBalance, uint newBalance);
/// @notice The standard EIP-20 transfer event
event Transfer(address indexed from, address indexed to, uint256 amount);
/// @notice The standard EIP-20 approval event
event Approval(address indexed owner, address indexed spender, uint256 amount);
/**
* @notice Construct a new Tribe token
* @param account The initial account to grant all the tokens
* @param minter_ The account with minting ability
*/
constructor(address account, address minter_) public {
balances[account] = uint96(totalSupply);
emit Transfer(address(0), account, totalSupply);
minter = minter_;
emit MinterChanged(address(0), minter);
}
/**
* @notice Change the minter address
* @param minter_ The address of the new minter
*/
function setMinter(address minter_) external {
require(msg.sender == minter, "Tribe: only the minter can change the minter address");
emit MinterChanged(minter, minter_);
minter = minter_;
}
/**
* @notice Mint new tokens
* @param dst The address of the destination account
* @param rawAmount The number of tokens to be minted
*/
function mint(address dst, uint rawAmount) external {
require(msg.sender == minter, "Tribe: only the minter can mint");
require(dst != address(0), "Tribe: cannot transfer to the zero address");
// mint the amount
uint96 amount = safe96(rawAmount, "Tribe: amount exceeds 96 bits");
uint96 safeSupply = safe96(totalSupply, "Tribe: totalSupply exceeds 96 bits");
totalSupply = add96(safeSupply, amount, "Tribe: totalSupply exceeds 96 bits");
// transfer the amount to the recipient
balances[dst] = add96(balances[dst], amount, "Tribe: transfer amount overflows");
emit Transfer(address(0), dst, amount);
// move delegates
_moveDelegates(address(0), delegates[dst], amount);
}
/**
* @notice Get the number of tokens `spender` is approved to spend on behalf of `account`
* @param account The address of the account holding the funds
* @param spender The address of the account spending the funds
* @return The number of tokens approved
*/
function allowance(address account, address spender) external view returns (uint) {
return allowances[account][spender];
}
/**
* @notice Approve `spender` to transfer up to `amount` from `src`
* @dev This will overwrite the approval amount for `spender`
* and is subject to issues noted [here](https://eips.ethereum.org/EIPS/eip-20#approve)
* @param spender The address of the account which may transfer tokens
* @param rawAmount The number of tokens that are approved (2^256-1 means infinite)
* @return Whether or not the approval succeeded
*/
function approve(address spender, uint rawAmount) external returns (bool) {
uint96 amount;
if (rawAmount == uint(-1)) {
amount = uint96(-1);
} else {
amount = safe96(rawAmount, "Tribe: amount exceeds 96 bits");
}
allowances[msg.sender][spender] = amount;
emit Approval(msg.sender, spender, amount);
return true;
}
/**
* @notice Triggers an approval from owner to spends
* @param owner The address to approve from
* @param spender The address to be approved
* @param rawAmount The number of tokens that are approved (2^256-1 means infinite)
* @param deadline The time at which to expire the signature
* @param v The recovery byte of the signature
* @param r Half of the ECDSA signature pair
* @param s Half of the ECDSA signature pair
*/
function permit(address owner, address spender, uint rawAmount, uint deadline, uint8 v, bytes32 r, bytes32 s) external {
uint96 amount;
if (rawAmount == uint(-1)) {
amount = uint96(-1);
} else {
amount = safe96(rawAmount, "Tribe: amount exceeds 96 bits");
}
bytes32 domainSeparator = keccak256(abi.encode(DOMAIN_TYPEHASH, keccak256(bytes(name)), getChainId(), address(this)));
bytes32 structHash = keccak256(abi.encode(PERMIT_TYPEHASH, owner, spender, rawAmount, nonces[owner]++, deadline));
bytes32 digest = keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash));
address signatory = ecrecover(digest, v, r, s);
require(signatory != address(0), "Tribe: invalid signature");
require(signatory == owner, "Tribe: unauthorized");
// solhint-disable-next-line not-rely-on-time
require(block.timestamp <= deadline, "Tribe: signature expired");
allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
/**
* @notice Get the number of tokens held by the `account`
* @param account The address of the account to get the balance of
* @return The number of tokens held
*/
function balanceOf(address account) external view returns (uint) {
return balances[account];
}
/**
* @notice Transfer `amount` tokens from `msg.sender` to `dst`
* @param dst The address of the destination account
* @param rawAmount The number of tokens to transfer
* @return Whether or not the transfer succeeded
*/
function transfer(address dst, uint rawAmount) external returns (bool) {
uint96 amount = safe96(rawAmount, "Tribe: amount exceeds 96 bits");
_transferTokens(msg.sender, dst, amount);
return true;
}
/**
* @notice Transfer `amount` tokens from `src` to `dst`
* @param src The address of the source account
* @param dst The address of the destination account
* @param rawAmount The number of tokens to transfer
* @return Whether or not the transfer succeeded
*/
function transferFrom(address src, address dst, uint rawAmount) external returns (bool) {
address spender = msg.sender;
uint96 spenderAllowance = allowances[src][spender];
uint96 amount = safe96(rawAmount, "Tribe: amount exceeds 96 bits");
if (spender != src && spenderAllowance != uint96(-1)) {
uint96 newAllowance = sub96(spenderAllowance, amount, "Tribe: transfer amount exceeds spender allowance");
allowances[src][spender] = newAllowance;
emit Approval(src, spender, newAllowance);
}
_transferTokens(src, dst, amount);
return true;
}
/**
* @notice Delegate votes from `msg.sender` to `delegatee`
* @param delegatee The address to delegate votes to
*/
function delegate(address delegatee) public {
return _delegate(msg.sender, delegatee);
}
/**
* @notice Delegates votes from signatory to `delegatee`
* @param delegatee The address to delegate votes to
* @param nonce The contract state required to match the signature
* @param expiry The time at which to expire the signature
* @param v The recovery byte of the signature
* @param r Half of the ECDSA signature pair
* @param s Half of the ECDSA signature pair
*/
function delegateBySig(address delegatee, uint nonce, uint expiry, uint8 v, bytes32 r, bytes32 s) public {
bytes32 domainSeparator = keccak256(abi.encode(DOMAIN_TYPEHASH, keccak256(bytes(name)), getChainId(), address(this)));
bytes32 structHash = keccak256(abi.encode(DELEGATION_TYPEHASH, delegatee, nonce, expiry));
bytes32 digest = keccak256(abi.encodePacked("\x19\x01", domainSeparator, structHash));
address signatory = ecrecover(digest, v, r, s);
require(signatory != address(0), "Tribe: invalid signature");
require(nonce == nonces[signatory]++, "Tribe: invalid nonce");
// solhint-disable-next-line not-rely-on-time
require(block.timestamp <= expiry, "Tribe: signature expired");
return _delegate(signatory, delegatee);
}
/**
* @notice Gets the current votes balance for `account`
* @param account The address to get votes balance
* @return The number of current votes for `account`
*/
function getCurrentVotes(address account) external view returns (uint96) {
uint32 nCheckpoints = numCheckpoints[account];
return nCheckpoints > 0 ? checkpoints[account][nCheckpoints - 1].votes : 0;
}
/**
* @notice Determine the prior number of votes for an account as of a block number
* @dev Block number must be a finalized block or else this function will revert to prevent misinformation.
* @param account The address of the account to check
* @param blockNumber The block number to get the vote balance at
* @return The number of votes the account had as of the given block
*/
function getPriorVotes(address account, uint blockNumber) public view returns (uint96) {
require(blockNumber < block.number, "Tribe: not yet determined");
uint32 nCheckpoints = numCheckpoints[account];
if (nCheckpoints == 0) {
return 0;
}
// First check most recent balance
if (checkpoints[account][nCheckpoints - 1].fromBlock <= blockNumber) {
return checkpoints[account][nCheckpoints - 1].votes;
}
// Next check implicit zero balance
if (checkpoints[account][0].fromBlock > blockNumber) {
return 0;
}
uint32 lower = 0;
uint32 upper = nCheckpoints - 1;
while (upper > lower) {
uint32 center = upper - (upper - lower) / 2; // ceil, avoiding overflow
Checkpoint memory cp = checkpoints[account][center];
if (cp.fromBlock == blockNumber) {
return cp.votes;
} else if (cp.fromBlock < blockNumber) {
lower = center;
} else {
upper = center - 1;
}
}
return checkpoints[account][lower].votes;
}
function _delegate(address delegator, address delegatee) internal {
address currentDelegate = delegates[delegator];
uint96 delegatorBalance = balances[delegator];
delegates[delegator] = delegatee;
emit DelegateChanged(delegator, currentDelegate, delegatee);
_moveDelegates(currentDelegate, delegatee, delegatorBalance);
}
function _transferTokens(address src, address dst, uint96 amount) internal {
require(src != address(0), "Tribe: cannot transfer from the zero address");
require(dst != address(0), "Tribe: cannot transfer to the zero address");
balances[src] = sub96(balances[src], amount, "Tribe: transfer amount exceeds balance");
balances[dst] = add96(balances[dst], amount, "Tribe: transfer amount overflows");
emit Transfer(src, dst, amount);
_moveDelegates(delegates[src], delegates[dst], amount);
}
function _moveDelegates(address srcRep, address dstRep, uint96 amount) internal {
if (srcRep != dstRep && amount > 0) {
if (srcRep != address(0)) {
uint32 srcRepNum = numCheckpoints[srcRep];
uint96 srcRepOld = srcRepNum > 0 ? checkpoints[srcRep][srcRepNum - 1].votes : 0;
uint96 srcRepNew = sub96(srcRepOld, amount, "Tribe: vote amount underflows");
_writeCheckpoint(srcRep, srcRepNum, srcRepOld, srcRepNew);
}
if (dstRep != address(0)) {
uint32 dstRepNum = numCheckpoints[dstRep];
uint96 dstRepOld = dstRepNum > 0 ? checkpoints[dstRep][dstRepNum - 1].votes : 0;
uint96 dstRepNew = add96(dstRepOld, amount, "Tribe: vote amount overflows");
_writeCheckpoint(dstRep, dstRepNum, dstRepOld, dstRepNew);
}
}
}
function _writeCheckpoint(address delegatee, uint32 nCheckpoints, uint96 oldVotes, uint96 newVotes) internal {
uint32 blockNumber = safe32(block.number, "Tribe: block number exceeds 32 bits");
if (nCheckpoints > 0 && checkpoints[delegatee][nCheckpoints - 1].fromBlock == blockNumber) {
checkpoints[delegatee][nCheckpoints - 1].votes = newVotes;
} else {
checkpoints[delegatee][nCheckpoints] = Checkpoint(blockNumber, newVotes);
numCheckpoints[delegatee] = nCheckpoints + 1;
}
emit DelegateVotesChanged(delegatee, oldVotes, newVotes);
}
function safe32(uint n, string memory errorMessage) internal pure returns (uint32) {
require(n < 2**32, errorMessage);
return uint32(n);
}
function safe96(uint n, string memory errorMessage) internal pure returns (uint96) {
require(n < 2**96, errorMessage);
return uint96(n);
}
function add96(uint96 a, uint96 b, string memory errorMessage) internal pure returns (uint96) {
uint96 c = a + b;
require(c >= a, errorMessage);
return c;
}
function sub96(uint96 a, uint96 b, string memory errorMessage) internal pure returns (uint96) {
require(b <= a, errorMessage);
return a - b;
}
function getChainId() internal pure returns (uint) {
uint256 chainId;
// solhint-disable-next-line no-inline-assembly
assembly { chainId := chainid() }
return chainId;
}
}// SPDX-License-Identifier: MIT
// solhint-disable-next-line compiler-version
pragma solidity >=0.4.24 <0.8.0;
import "../utils/Address.sol";
/**
* @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 {UpgradeableProxy-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 || _isConstructor() || !_initialized, "Initializable: contract is already initialized");
bool isTopLevelCall = !_initializing;
if (isTopLevelCall) {
_initializing = true;
_initialized = true;
}
_;
if (isTopLevelCall) {
_initializing = false;
}
}
/// @dev Returns true if and only if the function is running in the constructor
function _isConstructor() private view returns (bool) {
return !Address.isContract(address(this));
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.6.2 <0.8.0;
/**
* @dev Collection of functions related to the address type
*/
library Address {
/**
* @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;
// solhint-disable-next-line no-inline-assembly
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");
// solhint-disable-next-line avoid-low-level-calls, avoid-call-value
(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");
// solhint-disable-next-line avoid-low-level-calls
(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");
// solhint-disable-next-line avoid-low-level-calls
(bool success, bytes memory returndata) = target.staticcall(data);
return _verifyCallResult(success, returndata, errorMessage);
}
/**
* @dev Same as {xref-Address-functionCall-address-bytes-}[`functionCall`],
* but performing a delegate call.
*
* _Available since v3.4._
*/
function functionDelegateCall(address target, bytes memory data) internal returns (bytes memory) {
return functionDelegateCall(target, data, "Address: low-level delegate call failed");
}
/**
* @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, string memory errorMessage) internal returns (bytes memory) {
require(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 _verifyCallResult(success, returndata, errorMessage);
}
function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private 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
// solhint-disable-next-line no-inline-assembly
assembly {
let returndata_size := mload(returndata)
revert(add(32, returndata), returndata_size)
}
} else {
revert(errorMessage);
}
}
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.8.0;
import "../utils/EnumerableSet.sol";
import "../utils/Address.sol";
import "../utils/Context.sol";
/**
* @dev Contract module that allows children to implement role-based access
* control mechanisms.
*
* Roles are referred to by their `bytes32` identifier. These should be exposed
* in the external API and be unique. The best way to achieve this is by
* using `public constant` hash digests:
*
* ```
* bytes32 public constant MY_ROLE = keccak256("MY_ROLE");
* ```
*
* Roles can be used to represent a set of permissions. To restrict access to a
* function call, use {hasRole}:
*
* ```
* function foo() public {
* require(hasRole(MY_ROLE, msg.sender));
* ...
* }
* ```
*
* Roles can be granted and revoked dynamically via the {grantRole} and
* {revokeRole} functions. Each role has an associated admin role, and only
* accounts that have a role's admin role can call {grantRole} and {revokeRole}.
*
* By default, the admin role for all roles is `DEFAULT_ADMIN_ROLE`, which means
* that only accounts with this role will be able to grant or revoke other
* roles. More complex role relationships can be created by using
* {_setRoleAdmin}.
*
* WARNING: The `DEFAULT_ADMIN_ROLE` is also its own admin: it has permission to
* grant and revoke this role. Extra precautions should be taken to secure
* accounts that have been granted it.
*/
abstract contract AccessControl is Context {
using EnumerableSet for EnumerableSet.AddressSet;
using Address for address;
struct RoleData {
EnumerableSet.AddressSet members;
bytes32 adminRole;
}
mapping (bytes32 => RoleData) private _roles;
bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;
/**
* @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
*
* `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
* {RoleAdminChanged} not being emitted signaling this.
*
* _Available since v3.1._
*/
event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);
/**
* @dev Emitted when `account` is granted `role`.
*
* `sender` is the account that originated the contract call, an admin role
* bearer except when using {_setupRole}.
*/
event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Emitted when `account` is revoked `role`.
*
* `sender` is the account that originated the contract call:
* - if using `revokeRole`, it is the admin role bearer
* - if using `renounceRole`, it is the role bearer (i.e. `account`)
*/
event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) public view returns (bool) {
return _roles[role].members.contains(account);
}
/**
* @dev Returns the number of accounts that have `role`. Can be used
* together with {getRoleMember} to enumerate all bearers of a role.
*/
function getRoleMemberCount(bytes32 role) public view returns (uint256) {
return _roles[role].members.length();
}
/**
* @dev Returns one of the accounts that have `role`. `index` must be a
* value between 0 and {getRoleMemberCount}, non-inclusive.
*
* Role bearers are not sorted in any particular way, and their ordering may
* change at any point.
*
* WARNING: When using {getRoleMember} and {getRoleMemberCount}, make sure
* you perform all queries on the same block. See the following
* https://forum.openzeppelin.com/t/iterating-over-elements-on-enumerableset-in-openzeppelin-contracts/2296[forum post]
* for more information.
*/
function getRoleMember(bytes32 role, uint256 index) public view returns (address) {
return _roles[role].members.at(index);
}
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) public view returns (bytes32) {
return _roles[role].adminRole;
}
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function grantRole(bytes32 role, address account) public virtual {
require(hasRole(_roles[role].adminRole, _msgSender()), "AccessControl: sender must be an admin to grant");
_grantRole(role, account);
}
/**
* @dev Revokes `role` from `account`.
*
* If `account` had been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function revokeRole(bytes32 role, address account) public virtual {
require(hasRole(_roles[role].adminRole, _msgSender()), "AccessControl: sender must be an admin to revoke");
_revokeRole(role, account);
}
/**
* @dev Revokes `role` from the calling account.
*
* Roles are often managed via {grantRole} and {revokeRole}: this function's
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* If the calling account had been granted `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `account`.
*/
function renounceRole(bytes32 role, address account) public virtual {
require(account == _msgSender(), "AccessControl: can only renounce roles for self");
_revokeRole(role, account);
}
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event. Note that unlike {grantRole}, this function doesn't perform any
* checks on the calling account.
*
* [WARNING]
* ====
* This function should only be called from the constructor when setting
* up the initial roles for the system.
*
* Using this function in any other way is effectively circumventing the admin
* system imposed by {AccessControl}.
* ====
*/
function _setupRole(bytes32 role, address account) internal virtual {
_grantRole(role, account);
}
/**
* @dev Sets `adminRole` as ``role``'s admin role.
*
* Emits a {RoleAdminChanged} event.
*/
function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
emit RoleAdminChanged(role, _roles[role].adminRole, adminRole);
_roles[role].adminRole = adminRole;
}
function _grantRole(bytes32 role, address account) private {
if (_roles[role].members.add(account)) {
emit RoleGranted(role, account, _msgSender());
}
}
function _revokeRole(bytes32 role, address account) private {
if (_roles[role].members.remove(account)) {
emit RoleRevoked(role, account, _msgSender());
}
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.8.0;
/**
* @dev Library for managing
* https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
* types.
*
* Sets have the following properties:
*
* - Elements are added, removed, and checked for existence in constant time
* (O(1)).
* - Elements are enumerated in O(n). No guarantees are made on the ordering.
*
* ```
* contract Example {
* // Add the library methods
* using EnumerableSet for EnumerableSet.AddressSet;
*
* // Declare a set state variable
* EnumerableSet.AddressSet private mySet;
* }
* ```
*
* As of v3.3.0, sets of type `bytes32` (`Bytes32Set`), `address` (`AddressSet`)
* and `uint256` (`UintSet`) are supported.
*/
library EnumerableSet {
// To implement this library for multiple types with as little code
// repetition as possible, we write it in terms of a generic Set type with
// bytes32 values.
// The Set implementation uses private functions, and user-facing
// implementations (such as AddressSet) are just wrappers around the
// underlying Set.
// This means that we can only create new EnumerableSets for types that fit
// in bytes32.
struct Set {
// Storage of set values
bytes32[] _values;
// Position of the value in the `values` array, plus 1 because index 0
// means a value is not in the set.
mapping (bytes32 => uint256) _indexes;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function _add(Set storage set, bytes32 value) private returns (bool) {
if (!_contains(set, value)) {
set._values.push(value);
// The value is stored at length-1, but we add 1 to all indexes
// and use 0 as a sentinel value
set._indexes[value] = set._values.length;
return true;
} else {
return false;
}
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function _remove(Set storage set, bytes32 value) private returns (bool) {
// We read and store the value's index to prevent multiple reads from the same storage slot
uint256 valueIndex = set._indexes[value];
if (valueIndex != 0) { // Equivalent to contains(set, value)
// To delete an element from the _values array in O(1), we swap the element to delete with the last one in
// the array, and then remove the last element (sometimes called as 'swap and pop').
// This modifies the order of the array, as noted in {at}.
uint256 toDeleteIndex = valueIndex - 1;
uint256 lastIndex = set._values.length - 1;
// When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs
// so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement.
bytes32 lastvalue = set._values[lastIndex];
// Move the last value to the index where the value to delete is
set._values[toDeleteIndex] = lastvalue;
// Update the index for the moved value
set._indexes[lastvalue] = toDeleteIndex + 1; // All indexes are 1-based
// Delete the slot where the moved value was stored
set._values.pop();
// Delete the index for the deleted slot
delete set._indexes[value];
return true;
} else {
return false;
}
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function _contains(Set storage set, bytes32 value) private view returns (bool) {
return set._indexes[value] != 0;
}
/**
* @dev Returns the number of values on the set. O(1).
*/
function _length(Set storage set) private view returns (uint256) {
return set._values.length;
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function _at(Set storage set, uint256 index) private view returns (bytes32) {
require(set._values.length > index, "EnumerableSet: index out of bounds");
return set._values[index];
}
// Bytes32Set
struct Bytes32Set {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _add(set._inner, value);
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(Bytes32Set storage set, bytes32 value) internal returns (bool) {
return _remove(set._inner, value);
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(Bytes32Set storage set, bytes32 value) internal view returns (bool) {
return _contains(set._inner, value);
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(Bytes32Set storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
return _at(set._inner, index);
}
// AddressSet
struct AddressSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(AddressSet storage set, address value) internal returns (bool) {
return _add(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(AddressSet storage set, address value) internal returns (bool) {
return _remove(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(AddressSet storage set, address value) internal view returns (bool) {
return _contains(set._inner, bytes32(uint256(uint160(value))));
}
/**
* @dev Returns the number of values in the set. O(1).
*/
function length(AddressSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(AddressSet storage set, uint256 index) internal view returns (address) {
return address(uint160(uint256(_at(set._inner, index))));
}
// UintSet
struct UintSet {
Set _inner;
}
/**
* @dev Add a value to a set. O(1).
*
* Returns true if the value was added to the set, that is if it was not
* already present.
*/
function add(UintSet storage set, uint256 value) internal returns (bool) {
return _add(set._inner, bytes32(value));
}
/**
* @dev Removes a value from a set. O(1).
*
* Returns true if the value was removed from the set, that is if it was
* present.
*/
function remove(UintSet storage set, uint256 value) internal returns (bool) {
return _remove(set._inner, bytes32(value));
}
/**
* @dev Returns true if the value is in the set. O(1).
*/
function contains(UintSet storage set, uint256 value) internal view returns (bool) {
return _contains(set._inner, bytes32(value));
}
/**
* @dev Returns the number of values on the set. O(1).
*/
function length(UintSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(UintSet storage set, uint256 index) internal view returns (uint256) {
return uint256(_at(set._inner, index));
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.8.0;
/*
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with GSN meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address payable) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes memory) {
this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691
return msg.data;
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @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);
}// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.8.0;
import "../../utils/Context.sol";
import "./ERC20.sol";
/**
* @dev Extension of {ERC20} that allows token holders to destroy both their own
* tokens and those that they have an allowance for, in a way that can be
* recognized off-chain (via event analysis).
*/
abstract contract ERC20Burnable is Context, ERC20 {
using SafeMath for uint256;
/**
* @dev Destroys `amount` tokens from the caller.
*
* See {ERC20-_burn}.
*/
function burn(uint256 amount) public virtual {
_burn(_msgSender(), amount);
}
/**
* @dev Destroys `amount` tokens from `account`, deducting from the caller's
* allowance.
*
* See {ERC20-_burn} and {ERC20-allowance}.
*
* Requirements:
*
* - the caller must have allowance for ``accounts``'s tokens of at least
* `amount`.
*/
function burnFrom(address account, uint256 amount) public virtual {
uint256 decreasedAllowance = allowance(account, _msgSender()).sub(amount, "ERC20: burn amount exceeds allowance");
_approve(account, _msgSender(), decreasedAllowance);
_burn(account, amount);
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.8.0;
import "../../utils/Context.sol";
import "./IERC20.sol";
import "../../math/SafeMath.sol";
/**
* @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 guidelines: functions revert instead
* of 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 ERC20 is Context, IERC20 {
using SafeMath for uint256;
mapping (address => uint256) private _balances;
mapping (address => mapping (address => uint256)) private _allowances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
uint8 private _decimals;
/**
* @dev Sets the values for {name} and {symbol}, initializes {decimals} with
* a default value of 18.
*
* To select a different value for {decimals}, use {_setupDecimals}.
*
* All three of these values are immutable: they can only be set once during
* construction.
*/
constructor (string memory name_, string memory symbol_) public {
_name = name_;
_symbol = symbol_;
_decimals = 18;
}
/**
* @dev Returns the name of the token.
*/
function name() public view virtual returns (string memory) {
return _name;
}
/**
* @dev Returns the symbol of the token, usually a shorter version of the
* name.
*/
function symbol() public view virtual 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 {_setupDecimals} is
* called.
*
* 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 returns (uint8) {
return _decimals;
}
/**
* @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);
_approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance"));
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].add(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) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero"));
return true;
}
/**
* @dev Moves tokens `amount` from `sender` to `recipient`.
*
* This is 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);
_balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance");
_balances[recipient] = _balances[recipient].add(amount);
emit Transfer(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:
*
* - `to` 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 = _totalSupply.add(amount);
_balances[account] = _balances[account].add(amount);
emit Transfer(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);
_balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance");
_totalSupply = _totalSupply.sub(amount);
emit Transfer(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 Sets {decimals} to a value other than the default one of 18.
*
* WARNING: This function should only be called from the constructor. Most
* applications that interact with token contracts will not expect
* {decimals} to ever change, and may work incorrectly if it does.
*/
function _setupDecimals(uint8 decimals_) internal virtual {
_decimals = decimals_;
}
/**
* @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 to 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 { }
}// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.8.0;
/**
* @dev Wrappers over Solidity's arithmetic operations with added overflow
* checks.
*
* Arithmetic operations in Solidity wrap on overflow. This can easily result
* in bugs, because programmers usually assume that an overflow raises an
* error, which is the standard behavior in high level programming languages.
* `SafeMath` restores this intuition by reverting the transaction when an
* operation overflows.
*
* Using this library instead of the unchecked operations eliminates an entire
* class of bugs, so it's recommended to use it always.
*/
library SafeMath {
/**
* @dev Returns the addition of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function tryAdd(uint256 a, uint256 b) internal pure returns (bool, uint256) {
uint256 c = a + b;
if (c < a) return (false, 0);
return (true, c);
}
/**
* @dev Returns the substraction of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function trySub(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b > a) return (false, 0);
return (true, a - b);
}
/**
* @dev Returns the multiplication of two unsigned integers, with an overflow flag.
*
* _Available since v3.4._
*/
function tryMul(uint256 a, uint256 b) internal pure returns (bool, uint256) {
// Gas optimization: this is cheaper than requiring 'a' not being zero, but the
// benefit is lost if 'b' is also tested.
// See: https://github.com/OpenZeppelin/openzeppelin-contracts/pull/522
if (a == 0) return (true, 0);
uint256 c = a * b;
if (c / a != b) return (false, 0);
return (true, c);
}
/**
* @dev Returns the division of two unsigned integers, with a division by zero flag.
*
* _Available since v3.4._
*/
function tryDiv(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b == 0) return (false, 0);
return (true, a / b);
}
/**
* @dev Returns the remainder of dividing two unsigned integers, with a division by zero flag.
*
* _Available since v3.4._
*/
function tryMod(uint256 a, uint256 b) internal pure returns (bool, uint256) {
if (b == 0) return (false, 0);
return (true, a % b);
}
/**
* @dev Returns the addition of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `+` operator.
*
* Requirements:
*
* - Addition cannot overflow.
*/
function add(uint256 a, uint256 b) internal pure returns (uint256) {
uint256 c = a + b;
require(c >= a, "SafeMath: addition overflow");
return c;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting on
* overflow (when the result is negative).
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b) internal pure returns (uint256) {
require(b <= a, "SafeMath: subtraction overflow");
return a - b;
}
/**
* @dev Returns the multiplication of two unsigned integers, reverting on
* overflow.
*
* Counterpart to Solidity's `*` operator.
*
* Requirements:
*
* - Multiplication cannot overflow.
*/
function mul(uint256 a, uint256 b) internal pure returns (uint256) {
if (a == 0) return 0;
uint256 c = a * b;
require(c / a == b, "SafeMath: multiplication overflow");
return c;
}
/**
* @dev Returns the integer division of two unsigned integers, reverting on
* division by zero. The result is rounded towards zero.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b) internal pure returns (uint256) {
require(b > 0, "SafeMath: division by zero");
return a / b;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* reverting when dividing by zero.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b) internal pure returns (uint256) {
require(b > 0, "SafeMath: modulo by zero");
return a % b;
}
/**
* @dev Returns the subtraction of two unsigned integers, reverting with custom message on
* overflow (when the result is negative).
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {trySub}.
*
* Counterpart to Solidity's `-` operator.
*
* Requirements:
*
* - Subtraction cannot overflow.
*/
function sub(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b <= a, errorMessage);
return a - b;
}
/**
* @dev Returns the integer division of two unsigned integers, reverting with custom message on
* division by zero. The result is rounded towards zero.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {tryDiv}.
*
* Counterpart to Solidity's `/` operator. Note: this function uses a
* `revert` opcode (which leaves remaining gas untouched) while Solidity
* uses an invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function div(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
return a / b;
}
/**
* @dev Returns the remainder of dividing two unsigned integers. (unsigned integer modulo),
* reverting with custom message when dividing by zero.
*
* CAUTION: This function is deprecated because it requires allocating memory for the error
* message unnecessarily. For custom revert reasons use {tryMod}.
*
* Counterpart to Solidity's `%` operator. This function uses a `revert`
* opcode (which leaves remaining gas untouched) while Solidity uses an
* invalid opcode to revert (consuming all remaining gas).
*
* Requirements:
*
* - The divisor cannot be zero.
*/
function mod(uint256 a, uint256 b, string memory errorMessage) internal pure returns (uint256) {
require(b > 0, errorMessage);
return a % b;
}
}// SPDX-License-Identifier: MIT
pragma solidity >=0.6.0 <0.8.0;
import "./Context.sol";
/**
* @dev Contract module which allows children to implement an emergency stop
* mechanism that can be triggered by an authorized account.
*
* This module is used through inheritance. It will make available the
* modifiers `whenNotPaused` and `whenPaused`, which can be applied to
* the functions of your contract. Note that they will not be pausable by
* simply including this module, only once the modifiers are put in place.
*/
abstract contract Pausable is Context {
/**
* @dev Emitted when the pause is triggered by `account`.
*/
event Paused(address account);
/**
* @dev Emitted when the pause is lifted by `account`.
*/
event Unpaused(address account);
bool private _paused;
/**
* @dev Initializes the contract in unpaused state.
*/
constructor () internal {
_paused = false;
}
/**
* @dev Returns true if the contract is paused, and false otherwise.
*/
function paused() public view virtual returns (bool) {
return _paused;
}
/**
* @dev Modifier to make a function callable only when the contract is not paused.
*
* Requirements:
*
* - The contract must not be paused.
*/
modifier whenNotPaused() {
require(!paused(), "Pausable: paused");
_;
}
/**
* @dev Modifier to make a function callable only when the contract is paused.
*
* Requirements:
*
* - The contract must be paused.
*/
modifier whenPaused() {
require(paused(), "Pausable: not paused");
_;
}
/**
* @dev Triggers stopped state.
*
* Requirements:
*
* - The contract must not be paused.
*/
function _pause() internal virtual whenNotPaused {
_paused = true;
emit Paused(_msgSender());
}
/**
* @dev Returns to normal state.
*
* Requirements:
*
* - The contract must be paused.
*/
function _unpause() internal virtual whenPaused {
_paused = false;
emit Unpaused(_msgSender());
}
}{
"metadata": {
"useLiteralContent": true
},
"optimizer": {
"enabled": true,
"runs": 200
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"abi"
]
}
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_fei","type":"address"}],"name":"FeiUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_genesisGroup","type":"address"}],"name":"GenesisGroupUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"_timestamp","type":"uint256"}],"name":"GenesisPeriodComplete","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"previousAdminRole","type":"bytes32"},{"indexed":true,"internalType":"bytes32","name":"newAdminRole","type":"bytes32"}],"name":"RoleAdminChanged","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleGranted","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"role","type":"bytes32"},{"indexed":true,"internalType":"address","name":"account","type":"address"},{"indexed":true,"internalType":"address","name":"sender","type":"address"}],"name":"RoleRevoked","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_to","type":"address"},{"indexed":false,"internalType":"uint256","name":"_amount","type":"uint256"}],"name":"TribeAllocation","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"_tribe","type":"address"}],"name":"TribeUpdate","type":"event"},{"inputs":[],"name":"BURNER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"DEFAULT_ADMIN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GOVERN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"GUARDIAN_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"MINTER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"PCV_CONTROLLER_ROLE","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"to","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"allocateTribe","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"completeGenesisGroup","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"bytes32","name":"adminRole","type":"bytes32"}],"name":"createRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"fei","outputs":[{"internalType":"contract IFei","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"genesisGroup","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleAdmin","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"uint256","name":"index","type":"uint256"}],"name":"getRoleMember","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"}],"name":"getRoleMemberCount","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"burner","type":"address"}],"name":"grantBurner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"governor","type":"address"}],"name":"grantGovernor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"guardian","type":"address"}],"name":"grantGuardian","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"minter","type":"address"}],"name":"grantMinter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"pcvController","type":"address"}],"name":"grantPCVController","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"grantRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"hasGenesisGroupCompleted","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"hasRole","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"init","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"isBurner","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"isGovernor","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"isGuardian","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"isMinter","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"isPCVController","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"renounceRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"burner","type":"address"}],"name":"revokeBurner","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"governor","type":"address"}],"name":"revokeGovernor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"guardian","type":"address"}],"name":"revokeGuardian","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"minter","type":"address"}],"name":"revokeMinter","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeOverride","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"pcvController","type":"address"}],"name":"revokePCVController","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"role","type":"bytes32"},{"internalType":"address","name":"account","type":"address"}],"name":"revokeRole","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"setFei","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_genesisGroup","type":"address"}],"name":"setGenesisGroup","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"token","type":"address"}],"name":"setTribe","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"tribe","outputs":[{"internalType":"contract IERC20","name":"","type":"address"}],"stateMutability":"view","type":"function"}]Contract Creation Code
608060405262000018306001600160e01b03620000a616565b620000586040516200002a90620002ce565b60405180910390206040516200004090620002b7565b6040519081900390206001600160e01b03620000d416565b6200006a6040516200002a9062000287565b6200007c6040516200002a906200025e565b6200008e6040516200002a90620002b7565b620000a06040516200002a906200029e565b620002e5565b620000d1604051620000b890620002b7565b604051908190039020826001600160e01b036200012616565b50565b600082815260208190526040808220600201549051839285917fbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff9190a460009182526020829052604090912060020155565b6200013b82826001600160e01b036200013f16565b5050565b6000828152602081815260409091206200016491839062001228620001c1821b17901c565b156200013b576200017d6001600160e01b03620001ea16565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b6000620001e1836001600160a01b0384166001600160e01b03620001ee16565b90505b92915050565b3390565b60006200020583836001600160e01b036200024616565b6200023d57508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155620001e4565b506000620001e4565b60009081526001919091016020526040902054151590565b7f5043565f434f4e54524f4c4c45525f524f4c4500000000000000000000000000815260130190565b6a4255524e45525f524f4c4560a81b8152600b0190565b6c475541524449414e5f524f4c4560981b8152600d0190565b6a474f5645524e5f524f4c4560a81b8152600b0190565b6a4d494e5445525f524f4c4560a81b8152600b0190565b615d0880620002f56000396000f3fe60806040523480156200001157600080fd5b5060043610620002805760003560e01c80639010d07c1162000159578063c1ef303a11620000c9578063e0a200461162000087578063e0a200461462000560578063e1c7392a146200056a578063e43581b81462000574578063e6eb982f146200058b578063eacdd9e814620005a25762000280565b8063c1ef303a14620004fa578063ca15c8731462000511578063cfbd48851462000528578063d5391393146200053f578063d547741f14620005495762000280565b8063a217fddf1162000117578063a217fddf14620004a1578063aa271e1a14620004ab578063af648c3d14620004c2578063b86677fe14620004d9578063b9022dc014620004e35762000280565b80639010d07c146200044857806391d14854146200045f57806394b1d2c014620004765780639711ac34146200048d5780639a9ba4da14620004975762000280565b806336568abe11620001f55780635f06d76111620001b35780635f06d76114620003d3578063611cf19b14620003ea5780636186943e146200040157806384bb0a6b14620004185780638dd9227614620004315762000280565b806336568abe146200036d57806338b7f4461462000384578063395c62e8146200038e5780634334614a14620003a55780634c9f938414620003bc5762000280565b8063248a9ca31162000243578063248a9ca3146200030557806324ea54f4146200032b578063261707fa1462000335578063282c51f3146200034c5780632f2ff15d14620003565762000280565b8063080bf57c14620002855780630900cc33146200029e5780630c68ba2114620002b557806310511f9614620002e4578063201175c214620002fb575b600080fd5b6200029c6200029636600462001496565b620005b9565b005b6200029c620002af36600462001410565b62000683565b620002cc620002c636600462001410565b620006d1565b604051620002db9190620015d1565b60405180910390f35b6200029c620002f536600462001410565b620006fa565b6200029c62000745565b6200031c620003163660046200147d565b620007ee565b604051620002db9190620015dc565b6200031c62000803565b6200029c6200034636600462001410565b6200081c565b6200031c62000858565b6200029c6200036736600462001496565b62000866565b6200029c6200037e36600462001496565b620008b6565b6200031c620008ff565b6200029c6200039f36600462001410565b6200090d565b620002cc620003b636600462001410565b62000949565b6200029c620003cd366004620014d2565b6200095d565b6200029c620003e436600462001410565b62000993565b6200029c620003fb36600462001410565b620009c8565b620002cc6200041236600462001410565b62000a3c565b6200042262000a50565b604051620002db91906200158a565b6200029c6200044236600462001410565b62000a5f565b6200042262000459366004620014d2565b62000a9b565b620002cc6200047036600462001496565b62000ac2565b6200029c6200048736600462001410565b62000ae2565b620002cc62000b1e565b6200042262000b2e565b6200031c62000b43565b620002cc620004bc36600462001410565b62000b48565b6200029c620004d336600462001410565b62000b5c565b6200042262000b98565b6200029c620004f436600462001410565b62000ba7565b6200029c6200050b36600462001410565b62000bdc565b6200031c620005223660046200147d565b62000c18565b6200029c6200053936600462001410565b62000c31565b6200031c62000c6d565b6200029c6200055a36600462001496565b62000c7b565b6200031c62000cbb565b6200029c62000cc9565b620002cc6200058536600462001410565b62000df2565b6200029c6200059c36600462001410565b62000e06565b6200029c620005b33660046200142e565b62000e42565b620005c433620006d1565b620005ec5760405162461bcd60e51b8152600401620005e39062001825565b60405180910390fd5b604051620005fa906200155c565b6040518091039020821415620006245760405162461bcd60e51b8152600401620005e3906200186a565b60405163d547741f60e01b8152309063d547741f906200064b9085908590600401620015e5565b600060405180830381600087803b1580156200066657600080fd5b505af11580156200067b573d6000803e3d6000fd5b505050505050565b6200068e3362000df2565b620006ad5760405162461bcd60e51b8152600401620005e3906200163e565b620006ce604051620006bf906200152c565b60405180910390208262000c7b565b50565b6000620006f4604051620006e59062001543565b60405180910390208362000ac2565b92915050565b620007053362000df2565b620007245760405162461bcd60e51b8152600401620005e3906200163e565b620006ce60405162000736906200152c565b60405180910390208262000866565b600354600160a01b900460ff1615620007725760405162461bcd60e51b8152600401620005e39062001743565b6003546001600160a01b031633146200079f5760405162461bcd60e51b8152600401620005e39062001702565b6003805460ff60a01b1916600160a01b1790556040517f55728014a7cf4447d0a7e11503cf9ab1ca633624fa3150f8fe149b56e3c026fb90620007e4904290620015dc565b60405180910390a1565b60009081526020819052604090206002015490565b604051620008119062001543565b604051809103902081565b620008273362000df2565b620008465760405162461bcd60e51b8152600401620005e3906200163e565b620006ce604051620007369062001573565b60405162000811906200152c565b60008281526020819052604090206002015462000887906200047062000fe6565b620008a65760405162461bcd60e51b8152600401620005e39062001683565b620008b2828262000fea565b5050565b620008c062000fe6565b6001600160a01b0316816001600160a01b031614620008f35760405162461bcd60e51b8152600401620005e390620018b6565b620008b282826200105e565b60405162000811906200155c565b620009183362000df2565b620009375760405162461bcd60e51b8152600401620005e3906200163e565b620006ce60405162000736906200155c565b6000620006f4604051620006e5906200152c565b620009683362000df2565b620009875760405162461bcd60e51b8152600401620005e3906200163e565b620008b28282620010d2565b6200099e3362000df2565b620009bd5760405162461bcd60e51b8152600401620005e3906200163e565b620006ce8162001124565b620009d33362000df2565b620009f25760405162461bcd60e51b8152600401620005e3906200163e565b600380546001600160a01b0319166001600160a01b0383169081179091556040517f815cf7ef55cab2e0662e0739c044d60e9a897f882091d48baa1b0b30d28f8a3090600090a250565b6000620006f4604051620006e5906200150d565b6003546001600160a01b031681565b62000a6a3362000df2565b62000a895760405162461bcd60e51b8152600401620005e3906200163e565b620006ce604051620006bf906200150d565b600082815260208190526040812062000abb908363ffffffff6200117816565b9392505050565b600082815260208190526040812062000abb908363ffffffff6200118616565b62000aed3362000df2565b62000b0c5760405162461bcd60e51b8152600401620005e3906200163e565b620006ce604051620007369062001543565b600354600160a01b900460ff1681565b6001546201000090046001600160a01b031681565b600081565b6000620006f4604051620006e59062001573565b62000b673362000df2565b62000b865760405162461bcd60e51b8152600401620005e3906200163e565b620006ce604051620006bf9062001543565b6002546001600160a01b031681565b62000bb23362000df2565b62000bd15760405162461bcd60e51b8152600401620005e3906200163e565b620006ce816200119d565b62000be73362000df2565b62000c065760405162461bcd60e51b8152600401620005e3906200163e565b620006ce60405162000736906200150d565b6000818152602081905260408120620006f490620011e7565b62000c3c3362000df2565b62000c5b5760405162461bcd60e51b8152600401620005e3906200163e565b620006ce604051620006bf9062001573565b604051620008119062001573565b60008281526020819052604090206002015462000c9c906200047062000fe6565b620008f35760405162461bcd60e51b8152600401620005e39062001787565b60405162000811906200150d565b600154610100900460ff168062000ce5575062000ce5620011f4565b8062000cf4575060015460ff16155b62000d135760405162461bcd60e51b8152600401620005e390620017d7565b600154610100900460ff1615801562000d3e576001805460ff1961ff00199091166101001716811790555b62000d493362001207565b60003060405162000d5a90620013dc565b62000d6691906200158a565b604051809103906000f08015801562000d83573d6000803e3d6000fd5b50905062000d918162001124565b6000303360405162000da390620013ea565b62000db09291906200159e565b604051809103906000f08015801562000dcd573d6000803e3d6000fd5b50905062000ddb816200119d565b50508015620006ce576001805461ff001916905550565b6000620006f4604051620006e5906200155c565b62000e113362000df2565b62000e305760405162461bcd60e51b8152600401620005e3906200163e565b620006ce604051620006bf906200155c565b62000e4d3362000df2565b62000e6c5760405162461bcd60e51b8152600401620005e3906200163e565b6002546040516370a0823160e01b81526001600160a01b0390911690829082906370a082319062000ea29030906004016200158a565b60206040518083038186803b15801562000ebb57600080fd5b505afa15801562000ed0573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000ef69190620014f4565b101562000f175760405162461bcd60e51b8152600401620005e390620016d2565b60405163a9059cbb60e01b81526001600160a01b0382169063a9059cbb9062000f479086908690600401620015b8565b602060405180830381600087803b15801562000f6257600080fd5b505af115801562000f77573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000f9d91906200145b565b50826001600160a01b03167ffd90a2bc2c0c3cf07693529b256c4173a944fe9f55c1984c09a10a1ad28c11648360405162000fd99190620015dc565b60405180910390a2505050565b3390565b60008281526020819052604090206200100a908263ffffffff6200122816565b15620008b2576200101a62000fe6565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b60008281526020819052604090206200107e908263ffffffff6200123f16565b15620008b2576200108e62000fe6565b6001600160a01b0316816001600160a01b0316837ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a45050565b600082815260208190526040808220600201549051839285917fbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff9190a460009182526020829052604090912060020155565b6001805462010000600160b01b031916620100006001600160a01b038416908102919091179091556040517fb382b2a2d84e1d7542e0d58950e00d33ddc7a4b379a265768bf3e8640dde4ef190600090a250565b600062000abb838362001256565b600062000abb836001600160a01b0384166200129f565b600280546001600160a01b0319166001600160a01b0383169081179091556040517f9675664499c8d4f09c5268d1696ba833416ed56d870558fa7a722bb8aff5d90f90600090a250565b6000620006f482620012b7565b60006200120130620012bb565b15905090565b620006ce60405162001219906200155c565b604051809103902082620008a6565b600062000abb836001600160a01b038416620012c1565b600062000abb836001600160a01b03841662001310565b815460009082106200127c5760405162461bcd60e51b8152600401620005e390620015fc565b8260000182815481106200128c57fe5b9060005260206000200154905092915050565b60009081526001919091016020526040902054151590565b5490565b3b151590565b6000620012cf83836200129f565b6200130757508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155620006f4565b506000620006f4565b60008181526001830160205260408120548015620013d157835460001980830191908101906000908790839081106200134557fe5b90600052602060002001549050808760000184815481106200136357fe5b6000918252602080832090910192909255828152600189810190925260409020908401905586548790806200139457fe5b60019003818190600052602060002001600090559055866001016000878152602001908152602001600020600090556001945050505050620006f4565b6000915050620006f4565b6122c4806200190683390190565b6121098062003bca83390190565b80356001600160a01b0381168114620006f457600080fd5b60006020828403121562001422578081fd5b62000abb8383620013f8565b6000806040838503121562001441578081fd5b6200144d8484620013f8565b946020939093013593505050565b6000602082840312156200146d578081fd5b8151801515811462000abb578182fd5b6000602082840312156200148f578081fd5b5035919050565b60008060408385031215620014a9578182fd5b8235915060208301356001600160a01b0381168114620014c7578182fd5b809150509250929050565b60008060408385031215620014e5578182fd5b50508035926020909101359150565b60006020828403121562001506578081fd5b5051919050565b725043565f434f4e54524f4c4c45525f524f4c4560681b815260130190565b6a4255524e45525f524f4c4560a81b8152600b0190565b6c475541524449414e5f524f4c4560981b8152600d0190565b6a474f5645524e5f524f4c4560a81b8152600b0190565b6a4d494e5445525f524f4c4560a81b8152600b0190565b6001600160a01b0391909116815260200190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b03929092168252602082015260400190565b901515815260200190565b90815260200190565b9182526001600160a01b0316602082015260400190565b60208082526022908201527f456e756d657261626c655365743a20696e646578206f7574206f6620626f756e604082015261647360f01b606082015260800190565b60208082526025908201527f5065726d697373696f6e733a2043616c6c6572206973206e6f74206120676f7660408201526432b93737b960d91b606082015260800190565b6020808252602f908201527f416363657373436f6e74726f6c3a2073656e646572206d75737420626520616e60408201526e0818591b5a5b881d1bc819dc985b9d608a1b606082015260800190565b602080825260169082015275436f72653a204e6f7420656e6f75676820547269626560501b604082015260600190565b60208082526021908201527f436f72653a2043616c6c6572206973206e6f742047656e657369732047726f756040820152600760fc1b606082015260800190565b60208082526024908201527f436f72653a2047656e657369732047726f757020616c726561647920636f6d706040820152636c65746560e01b606082015260800190565b60208082526030908201527f416363657373436f6e74726f6c3a2073656e646572206d75737420626520616e60408201526f2061646d696e20746f207265766f6b6560801b606082015260800190565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b60208082526025908201527f5065726d697373696f6e733a2043616c6c6572206973206e6f74206120677561604082015264393234b0b760d91b606082015260800190565b6020808252602c908201527f5065726d697373696f6e733a20477561726469616e2063616e6e6f742072657660408201526b37b5b29033b7bb32b93737b960a11b606082015260800190565b6020808252602f908201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560408201526e103937b632b9903337b91039b2b63360891b60608201526080019056fe60806040523480156200001157600080fd5b50604051620022c4380380620022c48339810160408190526200003491620002aa565b604080518082018252600781526611995a481554d160ca1b6020808301918252835180850190945260038085526246454960e81b91850191909152825185949262000080929162000208565b5080516200009690600490602084019062000208565b5050600580546001600160a01b039093166201000002610100600160b01b031960ff199094166012179390931692909217909155506040514690620000db90620002da565b604051908190039020620000f76001600160e01b036200016d16565b805160209182012060408051808201825260018152603160f81b90840152516200014993927fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc691869130910162000344565b60405160208183030381529060405280519060200120600781905550505062000370565b60038054604080516020601f6002600019610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015620001fd5780601f10620001d157610100808354040283529160200191620001fd565b820191906000526020600020905b815481529060010190602001808311620001df57829003601f168201915b505050505090505b90565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200024b57805160ff19168380011785556200027b565b828001600101855582156200027b579182015b828111156200027b5782518255916020019190600101906200025e565b50620002899291506200028d565b5090565b6200020591905b8082111562000289576000815560010162000294565b600060208284031215620002bc578081fd5b81516001600160a01b0381168114620002d3578182fd5b9392505050565b7f454950373132446f6d61696e28737472696e67206e616d652c737472696e672081527f76657273696f6e2c75696e7432353620636861696e49642c6164647265737320602082015271766572696679696e67436f6e74726163742960701b604082015260520190565b9485526020850193909352604084019190915260608301526001600160a01b0316608082015260a00190565b611f4480620003806000396000f3fe608060405234801561001057600080fd5b50600436106101cf5760003560e01c806379cc679011610104578063a9059cbb116100a2578063bc701e7511610071578063bc701e751461036c578063d505accf1461037f578063dd62ed3e14610392578063f2f4eb26146103a5576101cf565b8063a9059cbb14610336578063b490589714610349578063b6232c9914610351578063b86677fe14610364576101cf565b80638456cb59116100de5780638456cb59146102fe57806395d89b41146103065780639a9ba4da1461030e578063a457c2d714610323576101cf565b806379cc6790146102c55780637ecebe00146102d857806380009630146102eb576101cf565b8063395093511161017157806342966c681161014b57806342966c681461028f5780635c975abb146102a25780636b6dff0a146102aa57806370a08231146102b2576101cf565b8063395093511461025f5780633f4ba83a1461027257806340c10f191461027c576101cf565b806323b872dd116101ad57806323b872dd1461022757806330adf81f1461023a578063313ce567146102425780633644e51514610257576101cf565b806306fdde03146101d4578063095ea7b3146101f257806318160ddd14610212575b600080fd5b6101dc6103ad565b6040516101e99190611a65565b60405180910390f35b61020561020036600461190f565b610443565b6040516101e991906119ff565b61021a610460565b6040516101e99190611a0a565b61020561023536600461185a565b610466565b61021a6104f3565b61024a610517565b6040516101e99190611e56565b61021a610520565b61020561026d36600461190f565b610526565b61027a61057a565b005b61027a61028a36600461190f565b6106b9565b61027a61029d366004611976565b6107d8565b610205610820565b61021a61082e565b61021a6102c0366004611806565b6108b8565b61027a6102d336600461190f565b6108d3565b61021a6102e6366004611806565b6109e6565b61027a6102f9366004611806565b6109f8565b61027a610aed565b6101dc610c21565b610316610c82565b6040516101e991906119c1565b61020561033136600461190f565b610d0a565b61020561034436600461190f565b610d78565b61021a610d8c565b61027a61035f366004611822565b610d96565b610316610e8e565b61031661037a366004611806565b610ede565b61027a61038d36600461189a565b610ef9565b61021a6103a0366004611822565b611068565b610316611093565b60038054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156104395780601f1061040e57610100808354040283529160200191610439565b820191906000526020600020905b81548152906001019060200180831161041c57829003601f168201915b5050505050905090565b60006104576104506110a8565b84846110ac565b50600192915050565b60025490565b6000610473848484611160565b6104e98461047f6110a8565b6104e485604051806060016040528060288152602001611ec2602891396001600160a01b038a166000908152600160205260408120906104bd6110a8565b6001600160a01b03168152602081019190915260400160002054919063ffffffff61117b16565b6110ac565b5060019392505050565b7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b60055460ff1690565b60075481565b60006104576105336110a8565b846104e485600160006105446110a8565b6001600160a01b03908116825260208083019390935260409182016000908120918c16815292529020549063ffffffff6111a716565b600554604051631c86b03760e31b8152620100009091046001600160a01b03169063e43581b8906105af9033906004016119c1565b60206040518083038186803b1580156105c757600080fd5b505afa1580156105db573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ff919061193a565b8061068a5750600554604051630c68ba2160e01b8152620100009091046001600160a01b031690630c68ba219061063a9033906004016119c1565b60206040518083038186803b15801561065257600080fd5b505afa158015610666573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061068a919061193a565b6106af5760405162461bcd60e51b81526004016106a690611ba2565b60405180910390fd5b6106b76111d3565b565b6005546040516355138f0d60e11b8152620100009091046001600160a01b03169063aa271e1a906106ee9033906004016119c1565b60206040518083038186803b15801561070657600080fd5b505afa15801561071a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061073e919061193a565b61075a5760405162461bcd60e51b81526004016106a690611b29565b610762610820565b1561077f5760405162461bcd60e51b81526004016106a690611cba565b6107898282611242565b336001600160a01b0316826001600160a01b03167fb1233017d63154bc561d57c16f7b6a55e2e1acd7fcac94045a9f35fb31a850ca836040516107cc9190611a0a565b60405180910390a35050565b6107e181611302565b604051339081907f227fb4b3aae8331f21af5167739c291fefe3afd3c2e08cea44f499e564f486ef90610815908590611a0a565b60405180910390a350565b600554610100900460ff1690565b6000610838610e8e565b6001600160a01b03166370a08231306040518263ffffffff1660e01b815260040161086391906119c1565b60206040518083038186803b15801561087b57600080fd5b505afa15801561088f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108b3919061198e565b905090565b6001600160a01b031660009081526020819052604090205490565b60055460405163219a30a560e11b8152620100009091046001600160a01b031690634334614a906109089033906004016119c1565b60206040518083038186803b15801561092057600080fd5b505afa158015610934573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610958919061193a565b6109745760405162461bcd60e51b81526004016106a690611c26565b61097c610820565b156109995760405162461bcd60e51b81526004016106a690611cba565b6109a38282611316565b336001600160a01b0316826001600160a01b03167f227fb4b3aae8331f21af5167739c291fefe3afd3c2e08cea44f499e564f486ef836040516107cc9190611a0a565b60086020526000908152604090205481565b600554604051631c86b03760e31b8152620100009091046001600160a01b03169063e43581b890610a2d9033906004016119c1565b60206040518083038186803b158015610a4557600080fd5b505afa158015610a59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a7d919061193a565b610a995760405162461bcd60e51b81526004016106a690611dde565b6005805462010000600160b01b031916620100006001600160a01b038416908102919091179091556040517fad9400e618eb1344fde53db22397a1b82c765527ecbba3a5c86bcac15090828b90600090a250565b600554604051631c86b03760e31b8152620100009091046001600160a01b03169063e43581b890610b229033906004016119c1565b60206040518083038186803b158015610b3a57600080fd5b505afa158015610b4e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b72919061193a565b80610bfd5750600554604051630c68ba2160e01b8152620100009091046001600160a01b031690630c68ba2190610bad9033906004016119c1565b60206040518083038186803b158015610bc557600080fd5b505afa158015610bd9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bfd919061193a565b610c195760405162461bcd60e51b81526004016106a690611ba2565b6106b76113f8565b60048054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156104395780601f1061040e57610100808354040283529160200191610439565b6000600560029054906101000a90046001600160a01b03166001600160a01b0316639a9ba4da6040518163ffffffff1660e01b815260040160206040518083038186803b158015610cd257600080fd5b505afa158015610ce6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108b3919061195a565b6000610457610d176110a8565b846104e485604051806060016040528060258152602001611eea6025913960016000610d416110a8565b6001600160a01b03908116825260208083019390935260409182016000908120918d1681529252902054919063ffffffff61117b16565b6000610457610d856110a8565b8484611160565b6000610838610c82565b600554604051631c86b03760e31b8152620100009091046001600160a01b03169063e43581b890610dcb9033906004016119c1565b60206040518083038186803b158015610de357600080fd5b505afa158015610df7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e1b919061193a565b610e375760405162461bcd60e51b81526004016106a690611dde565b6001600160a01b0382811660008181526006602052604080822080546001600160a01b0319169486169485179055517f88bb9e877881758e827c849b8a0e38421bd5ff916f4ef79ed65aec74cc04a5da9190a35050565b6000600560029054906101000a90046001600160a01b03166001600160a01b031663b86677fe6040518163ffffffff1660e01b815260040160206040518083038186803b158015610cd257600080fd5b6006602052600090815260409020546001600160a01b031681565b42841015610f195760405162461bcd60e51b81526004016106a690611c5d565b6007546001600160a01b03881660009081526008602090815260408083208054600181019091559051929392610f7a927f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9928d928d928d92918d9101611a13565b60405160208183030381529060405280519060200120604051602001610fa19291906119a6565b604051602081830303815290604052805190602001209050600060018286868660405160008152602001604052604051610fde9493929190611a47565b6020604051602081039080840390855afa158015611000573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116158015906110365750886001600160a01b0316816001600160a01b0316145b6110525760405162461bcd60e51b81526004016106a690611ce4565b61105d8989896110ac565b505050505050505050565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6005546201000090046001600160a01b031690565b3390565b6001600160a01b0383166110d25760405162461bcd60e51b81526004016106a690611d9a565b6001600160a01b0382166110f85760405162461bcd60e51b81526004016106a690611b60565b6001600160a01b0380841660008181526001602090815260408083209487168084529490915290819020849055517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590611153908590611a0a565b60405180910390a3505050565b61116b838383611455565b611176838383611576565b505050565b6000818484111561119f5760405162461bcd60e51b81526004016106a69190611a65565b505050900390565b6000828201838110156111cc5760405162461bcd60e51b81526004016106a690611bef565b9392505050565b6111db610820565b6111f75760405162461bcd60e51b81526004016106a690611afb565b6005805461ff00191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa61122b6110a8565b60405161123891906119c1565b60405180910390a1565b6001600160a01b0382166112685760405162461bcd60e51b81526004016106a690611e1f565b61127460008383611176565b600254611287908263ffffffff6111a716565b6002556001600160a01b0382166000908152602081905260409020546112b3908263ffffffff6111a716565b6001600160a01b0383166000818152602081905260408082209390935591519091907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906107cc908590611a0a565b61131361130d6110a8565b82611316565b50565b6001600160a01b03821661133c5760405162461bcd60e51b81526004016106a690611d14565b61134882600083611176565b61138b81604051806060016040528060228152602001611e7a602291396001600160a01b038516600090815260208190526040902054919063ffffffff61117b16565b6001600160a01b0383166000908152602081905260409020556002546113b7908263ffffffff6117de16565b6002556040516000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906107cc908590611a0a565b611400610820565b1561141d5760405162461bcd60e51b81526004016106a690611cba565b6005805461ff0019166101001790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25861122b6110a8565b6001600160a01b03831661147b5760405162461bcd60e51b81526004016106a690611d55565b6001600160a01b0382166114a15760405162461bcd60e51b81526004016106a690611ab8565b6114ac838383611176565b6114ef81604051806060016040528060268152602001611e9c602691396001600160a01b038616600090815260208190526040902054919063ffffffff61117b16565b6001600160a01b038085166000908152602081905260408082209390935590841681522054611524908263ffffffff6111a716565b6001600160a01b0380841660008181526020819052604090819020939093559151908516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90611153908590611a0a565b6001600160a01b038084166000908152600660205260409020541680156115fc57604051636e22230d60e01b81526001600160a01b03821690636e22230d906115c99087908790339088906004016119d5565b600060405180830381600087803b1580156115e357600080fd5b505af11580156115f7573d6000803e3d6000fd5b505050505b6001600160a01b0380841660009081526006602052604090205416801561168257604051636e22230d60e01b81526001600160a01b03821690636e22230d9061164f9088908890339089906004016119d5565b600060405180830381600087803b15801561166957600080fd5b505af115801561167d573d6000803e3d6000fd5b505050505b336000818152600660205260409020546001600160a01b0390811691908716148015906116b85750336001600160a01b03861614155b80156116cc57506001600160a01b03811615155b1561173657604051636e22230d60e01b81526001600160a01b03821690636e22230d90611703908990899033908a906004016119d5565b600060405180830381600087803b15801561171d57600080fd5b505af1158015611731573d6000803e3d6000fd5b505050505b6000805260066020527f54cdd369e4e8a8515e52ca72ec816c2101831ad1f18bf44102ed171459c9b4f8546001600160a01b031680156117d557604051636e22230d60e01b81526001600160a01b03821690636e22230d906117a2908a908a9033908b906004016119d5565b600060405180830381600087803b1580156117bc57600080fd5b505af11580156117d0573d6000803e3d6000fd5b505050505b50505050505050565b6000828211156118005760405162461bcd60e51b81526004016106a690611c83565b50900390565b600060208284031215611817578081fd5b81356111cc81611e64565b60008060408385031215611834578081fd5b823561183f81611e64565b9150602083013561184f81611e64565b809150509250929050565b60008060006060848603121561186e578081fd5b833561187981611e64565b9250602084013561188981611e64565b929592945050506040919091013590565b600080600080600080600060e0888a0312156118b4578283fd5b87356118bf81611e64565b965060208801356118cf81611e64565b95506040880135945060608801359350608088013560ff811681146118f2578384fd5b9699959850939692959460a0840135945060c09093013592915050565b60008060408385031215611921578182fd5b823561192c81611e64565b946020939093013593505050565b60006020828403121561194b578081fd5b815180151581146111cc578182fd5b60006020828403121561196b578081fd5b81516111cc81611e64565b600060208284031215611987578081fd5b5035919050565b60006020828403121561199f578081fd5b5051919050565b61190160f01b81526002810192909252602282015260420190565b6001600160a01b0391909116815260200190565b6001600160a01b039485168152928416602084015292166040820152606081019190915260800190565b901515815260200190565b90815260200190565b9586526001600160a01b0394851660208701529290931660408501526060840152608083019190915260a082015260c00190565b93845260ff9290921660208401526040830152606082015260800190565b6000602080835283518082850152825b81811015611a9157858101830151858201604001528201611a75565b81811115611aa25783604083870101525b50601f01601f1916929092016040019392505050565b60208082526023908201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260408201526265737360e81b606082015260800190565b60208082526014908201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b604082015260600190565b6020808252601f908201527f436f72655265663a2043616c6c6572206973206e6f742061206d696e74657200604082015260600190565b60208082526022908201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604082015261737360f01b606082015260800190565b6020808252602d908201527f436f72655265663a2043616c6c6572206973206e6f742061206775617264696160408201526c371037b91033b7bb32b93737b960991b606082015260800190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b6020808252601f908201527f436f72655265663a2043616c6c6572206973206e6f742061206275726e657200604082015260600190565b6020808252600c908201526b11995a4e881156141254915160a21b604082015260600190565b6020808252601e908201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604082015260600190565b60208082526010908201526f14185d5cd8589b194e881c185d5cd95960821b604082015260600190565b6020808252601690820152754665693a20494e56414c49445f5349474e415455524560501b604082015260600190565b60208082526021908201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736040820152607360f81b606082015260800190565b60208082526025908201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604082015264647265737360d81b606082015260800190565b60208082526024908201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646040820152637265737360e01b606082015260800190565b60208082526021908201527f436f72655265663a2043616c6c6572206973206e6f74206120676f7665726e6f6040820152603960f91b606082015260800190565b6020808252601f908201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604082015260600190565b60ff91909116815260200190565b6001600160a01b038116811461131357600080fdfe45524332303a206275726e20616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa264697066735822122050e890c3b2545b3935ee59eb10f843e1ae9421c4c123c2534bea07e27e8ff0f164736f6c6343000606003360806040526b033b2e3c9fd0803ce80000006000553480156200002157600080fd5b506040516200210938038062002109833981016040819052620000449162000121565b600080546001600160a01b0384168083526003602052604080842080546001600160601b0319166001600160601b0390941693909317909255825491519092917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91620000b2919062000179565b60405180910390a3600180546001600160a01b0319166001600160a01b0383811691909117918290556040517f3b0007eb941cf645526cbb3a4fdaecda9d28ce4843167d9263b536a1f1edc0f69262000111926000929116906200015f565b60405180910390a150506200019b565b6000806040838503121562000134578182fd5b8251620001418162000182565b6020840151909250620001548162000182565b809150509250929050565b6001600160a01b0392831681529116602082015260400190565b90815260200190565b6001600160a01b03811681146200019857600080fd5b50565b611f5e80620001ab6000396000f3fe608060405234801561001057600080fd5b50600436106101585760003560e01c806370a08231116100c3578063c3cda5201161007c578063c3cda520146102cc578063d505accf146102df578063dd62ed3e146102f2578063e7a324dc14610305578063f1127ed81461030d578063fca3b5aa1461032e57610158565b806370a0823114610258578063782d6fe11461026b5780637ecebe001461028b57806395d89b411461029e578063a9059cbb146102a6578063b4b5ea57146102b957610158565b806330adf81f1161011557806330adf81f146101e0578063313ce567146101e857806340c10f19146101fd578063587cde1e146102125780635c19a95c146102255780636fcfff451461023857610158565b806306fdde031461015d578063075461721461017b578063095ea7b31461019057806318160ddd146101b057806320606b70146101c557806323b872dd146101cd575b600080fd5b610165610341565b6040516101729190611b78565b60405180910390f35b610183610362565b6040516101729190611a9c565b6101a361019e3660046118ab565b610371565b6040516101729190611aca565b6101b861043b565b6040516101729190611ad5565b6101b8610441565b6101a36101db3660046117ff565b610458565b6101b86105a7565b6101f06105b3565b6040516101729190611e1c565b61021061020b3660046118ab565b6105b8565b005b6101836102203660046117b0565b610794565b6102106102333660046117b0565b6107af565b61024b6102463660046117b0565b6107bc565b6040516101729190611dec565b6101b86102663660046117b0565b6107d4565b61027e6102793660046118ab565b6107f8565b6040516101729190611e2a565b6101b86102993660046117b0565b610a06565b610165610a18565b6101a36102b43660046118ab565b610a39565b61027e6102c73660046117b0565b610a80565b6102106102da3660046118d5565b610af1565b6102106102ed36600461183f565b610cd8565b6101b86103003660046117cb565b610fcc565b6101b8611000565b61032061031b36600461192e565b61100c565b604051610172929190611dfd565b61021061033c3660046117b0565b611041565b60405180604001604052806005815260200164547269626560d81b81525081565b6001546001600160a01b031681565b60008060001983141561038757506000196103b7565b6103b4836040518060400160405280601d8152602001600080516020611f098339815191528152506110d4565b90505b3360008181526002602090815260408083206001600160a01b03891680855292529182902080546001600160601b0319166001600160601b03861617905590519091907f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590610427908590611e2a565b60405180910390a360019150505b92915050565b60005481565b60405161044d906119f2565b604051809103902081565b6001600160a01b038316600090815260026020908152604080832033808552908352818420548251808401909352601d8352600080516020611f0983398151915293830193909352916001600160601b03169083906104b89086906110d4565b9050866001600160a01b0316836001600160a01b0316141580156104e557506001600160601b0382811614155b1561058f57600061050f8383604051806060016040528060308152602001611eb360309139611103565b6001600160a01b038981166000818152600260209081526040808320948a16808452949091529081902080546001600160601b0319166001600160601b0386161790555192935090917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590610585908590611e2a565b60405180910390a3505b61059a878783611142565b5060019695505050505050565b60405161044d90611988565b601281565b6001546001600160a01b031633146105eb5760405162461bcd60e51b81526004016105e290611bcb565b60405180910390fd5b6001600160a01b0382166106115760405162461bcd60e51b81526004016105e290611c02565b6000610640826040518060400160405280601d8152602001600080516020611f098339815191528152506110d4565b90506000610668600054604051806060016040528060228152602001611e91602291396110d4565b905061068d8183604051806060016040528060228152602001611e9160229139611305565b6001600160601b0390811660009081556001600160a01b0386168152600360209081526040918290205482518084019093528183527f54726962653a207472616e7366657220616d6f756e74206f766572666c6f7773918301919091526106f79216908490611305565b6001600160a01b03851660008181526003602052604080822080546001600160601b0319166001600160601b03959095169490941790935591519091907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90610761908690611e2a565b60405180910390a36001600160a01b0380851660009081526004602052604081205461078e921684611341565b50505050565b6004602052600090815260409020546001600160a01b031681565b6107b9338261150d565b50565b60066020526000908152604090205463ffffffff1681565b6001600160a01b03166000908152600360205260409020546001600160601b031690565b60004382106108195760405162461bcd60e51b81526004016105e290611db5565b6001600160a01b03831660009081526006602052604090205463ffffffff1680610847576000915050610435565b6001600160a01b038416600090815260056020908152604080832063ffffffff6000198601811685529252909120541683106108c3576001600160a01b03841660009081526005602090815260408083206000199490940163ffffffff1683529290522054600160201b90046001600160601b03169050610435565b6001600160a01b038416600090815260056020908152604080832083805290915290205463ffffffff168310156108fe576000915050610435565b600060001982015b8163ffffffff168163ffffffff1611156109c157600282820363ffffffff16048103610930611771565b506001600160a01b038716600090815260056020908152604080832063ffffffff858116855290835292819020815180830190925254928316808252600160201b9093046001600160601b0316918101919091529087141561099c576020015194506104359350505050565b805163ffffffff168711156109b3578193506109ba565b6001820392505b5050610906565b506001600160a01b038516600090815260056020908152604080832063ffffffff909416835292905220546001600160601b03600160201b9091041691505092915050565b60076020526000908152604090205481565b60405180604001604052806005815260200164545249424560d81b81525081565b600080610a69836040518060400160405280601d8152602001600080516020611f098339815191528152506110d4565b9050610a76338583611142565b5060019392505050565b6001600160a01b03811660009081526006602052604081205463ffffffff1680610aab576000610aea565b6001600160a01b0383166000908152600560209081526040808320600019850163ffffffff168452909152902054600160201b90046001600160601b03165b9392505050565b6000604051610aff906119f2565b604080519182900382208282019091526005825264547269626560d81b6020909201919091527febed0dee75115424b4c6084a9ab165e0c99bcf5a44403d7510e1ad1caeaea506610b4e611591565b30604051602001610b629493929190611b36565b6040516020818303038152906040528051906020012090506000604051610b8890611a4d565b604051908190038120610ba3918a908a908a90602001611b12565b60405160208183030381529060405280519060200120905060008282604051602001610bd092919061196d565b604051602081830303815290604052805190602001209050600060018288888860405160008152602001604052604051610c0d9493929190611b5a565b6020604051602081039080840390855afa158015610c2f573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116610c625760405162461bcd60e51b81526004016105e290611cfc565b6001600160a01b03811660009081526007602052604090208054600181019091558914610ca15760405162461bcd60e51b81526004016105e290611d33565b87421115610cc15760405162461bcd60e51b81526004016105e290611c4c565b610ccb818b61150d565b505050505b505050505050565b6000600019861415610ced5750600019610d1d565b610d1a866040518060400160405280601d8152602001600080516020611f098339815191528152506110d4565b90505b6000604051610d2b906119f2565b604080519182900382208282019091526005825264547269626560d81b6020909201919091527febed0dee75115424b4c6084a9ab165e0c99bcf5a44403d7510e1ad1caeaea506610d7a611591565b30604051602001610d8e9493929190611b36565b6040516020818303038152906040528051906020012090506000604051610db490611988565b604080519182900382206001600160a01b038d16600090815260076020908152929020805460018101909155610df69391928e928e928e9290918e9101611ade565b60405160208183030381529060405280519060200120905060008282604051602001610e2392919061196d565b604051602081830303815290604052805190602001209050600060018289898960405160008152602001604052604051610e609493929190611b5a565b6020604051602081039080840390855afa158015610e82573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116610eb55760405162461bcd60e51b81526004016105e290611cfc565b8b6001600160a01b0316816001600160a01b031614610ee65760405162461bcd60e51b81526004016105e290611ccf565b88421115610f065760405162461bcd60e51b81526004016105e290611c4c565b84600260008e6001600160a01b03166001600160a01b0316815260200190815260200160002060008d6001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a8154816001600160601b0302191690836001600160601b031602179055508a6001600160a01b03168c6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92587604051610fb69190611e2a565b60405180910390a3505050505050505050505050565b6001600160a01b0391821660009081526002602090815260408083209390941682529190915220546001600160601b031690565b60405161044d90611a4d565b600560209081526000928352604080842090915290825290205463ffffffff811690600160201b90046001600160601b031682565b6001546001600160a01b0316331461106b5760405162461bcd60e51b81526004016105e290611d61565b6001546040517f3b0007eb941cf645526cbb3a4fdaecda9d28ce4843167d9263b536a1f1edc0f6916110aa916001600160a01b03909116908490611ab0565b60405180910390a1600180546001600160a01b0319166001600160a01b0392909216919091179055565b600081600160601b84106110fb5760405162461bcd60e51b81526004016105e29190611b78565b509192915050565b6000836001600160601b0316836001600160601b03161115829061113a5760405162461bcd60e51b81526004016105e29190611b78565b505050900390565b6001600160a01b0383166111685760405162461bcd60e51b81526004016105e290611c83565b6001600160a01b03821661118e5760405162461bcd60e51b81526004016105e290611c02565b6001600160a01b0383166000908152600360209081526040918290205482516060810190935260268084526111d9936001600160601b039092169285929190611ee390830139611103565b6001600160a01b03848116600090815260036020908152604080832080546001600160601b0319166001600160601b039687161790559286168252908290205482518084019093528183527f54726962653a207472616e7366657220616d6f756e74206f766572666c6f7773918301919091526112599216908390611305565b6001600160a01b038381166000818152600360205260409081902080546001600160601b0319166001600160601b0395909516949094179093559151908516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906112c6908590611e2a565b60405180910390a36001600160a01b0380841660009081526004602052604080822054858416835291205461130092918216911683611341565b505050565b6000838301826001600160601b0380871690831610156113385760405162461bcd60e51b81526004016105e29190611b78565b50949350505050565b816001600160a01b0316836001600160a01b03161415801561136c57506000816001600160601b0316115b15611300576001600160a01b03831615611441576001600160a01b03831660009081526006602052604081205463ffffffff1690816113ac5760006113eb565b6001600160a01b0385166000908152600560209081526040808320600019860163ffffffff168452909152902054600160201b90046001600160601b03165b9050600061142f82856040518060400160405280601d81526020017f54726962653a20766f746520616d6f756e7420756e646572666c6f7773000000815250611103565b905061143d86848484611595565b5050505b6001600160a01b03821615611300576001600160a01b03821660009081526006602052604081205463ffffffff16908161147c5760006114bb565b6001600160a01b0384166000908152600560209081526040808320600019860163ffffffff168452909152902054600160201b90046001600160601b03165b905060006114ff82856040518060400160405280601c81526020017f54726962653a20766f746520616d6f756e74206f766572666c6f777300000000815250611305565b9050610cd085848484611595565b6001600160a01b03808316600081815260046020818152604080842080546003845282862054949093528787166001600160a01b031984168117909155905191909516946001600160601b039092169391928592917f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f9190a461078e828483611341565b4690565b60006115b943604051806060016040528060238152602001611e6e6023913961174a565b905060008463ffffffff1611801561160257506001600160a01b038516600090815260056020908152604080832063ffffffff6000198901811685529252909120548282169116145b15611661576001600160a01b0385166000908152600560209081526040808320600019880163ffffffff168452909152902080546fffffffffffffffffffffffff000000001916600160201b6001600160601b03851602179055611700565b60408051808201825263ffffffff80841682526001600160601b0380861660208085019182526001600160a01b038b166000818152600583528781208c871682528352878120965187549451909516600160201b026fffffffffffffffffffffffff000000001995871663ffffffff19958616179590951694909417909555938252600690935292909220805460018801909316929091169190911790555b846001600160a01b03167fdec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a724848460405161173b929190611e3e565b60405180910390a25050505050565b600081600160201b84106110fb5760405162461bcd60e51b81526004016105e29190611b78565b604080518082019091526000808252602082015290565b80356001600160a01b038116811461043557600080fd5b803560ff8116811461043557600080fd5b6000602082840312156117c1578081fd5b610aea8383611788565b600080604083850312156117dd578081fd5b6117e78484611788565b91506117f68460208501611788565b90509250929050565b600080600060608486031215611813578081fd5b833561181e81611e58565b9250602084013561182e81611e58565b929592945050506040919091013590565b600080600080600080600060e0888a031215611859578283fd5b6118638989611788565b96506118728960208a01611788565b9550604088013594506060880135935061188f8960808a0161179f565b925060a0880135915060c0880135905092959891949750929550565b600080604083850312156118bd578182fd5b6118c78484611788565b946020939093013593505050565b60008060008060008060c087890312156118ed578182fd5b6118f78888611788565b95506020870135945060408701359350611914886060890161179f565b92506080870135915060a087013590509295509295509295565b60008060408385031215611940578182fd5b61194a8484611788565b9150602083013563ffffffff81168114611962578182fd5b809150509250929050565b61190160f01b81526002810192909252602282015260420190565b7f5065726d69742861646472657373206f776e65722c616464726573732073706581527f6e6465722c75696e743235362076616c75652c75696e74323536206e6f6e63656020820152712c75696e7432353620646561646c696e652960701b604082015260520190565b7f454950373132446f6d61696e28737472696e67206e616d652c75696e7432353681527f20636861696e49642c6164647265737320766572696679696e67436f6e74726160208201526263742960e81b604082015260430190565b7f44656c65676174696f6e28616464726573732064656c6567617465652c75696e81527f74323536206e6f6e63652c75696e7432353620657870697279290000000000006020820152603a0190565b6001600160a01b0391909116815260200190565b6001600160a01b0392831681529116602082015260400190565b901515815260200190565b90815260200190565b9586526001600160a01b0394851660208701529290931660408501526060840152608083019190915260a082015260c00190565b9384526001600160a01b039290921660208401526040830152606082015260800190565b938452602084019290925260408301526001600160a01b0316606082015260800190565b93845260ff9290921660208401526040830152606082015260800190565b6000602080835283518082850152825b81811015611ba457858101830151858201604001528201611b88565b81811115611bb55783604083870101525b50601f01601f1916929092016040019392505050565b6020808252601f908201527f54726962653a206f6e6c7920746865206d696e7465722063616e206d696e7400604082015260600190565b6020808252602a908201527f54726962653a2063616e6e6f74207472616e7366657220746f20746865207a65604082015269726f206164647265737360b01b606082015260800190565b60208082526018908201527f54726962653a207369676e617475726520657870697265640000000000000000604082015260600190565b6020808252602c908201527f54726962653a2063616e6e6f74207472616e736665722066726f6d207468652060408201526b7a65726f206164647265737360a01b606082015260800190565b602080825260139082015272151c9a58994e881d5b985d5d1a1bdc9a5e9959606a1b604082015260600190565b60208082526018908201527f54726962653a20696e76616c6964207369676e61747572650000000000000000604082015260600190565b60208082526014908201527354726962653a20696e76616c6964206e6f6e636560601b604082015260600190565b60208082526034908201527f54726962653a206f6e6c7920746865206d696e7465722063616e206368616e676040820152736520746865206d696e746572206164647265737360601b606082015260800190565b60208082526019908201527f54726962653a206e6f74207965742064657465726d696e656400000000000000604082015260600190565b63ffffffff91909116815260200190565b63ffffffff9290921682526001600160601b0316602082015260400190565b60ff91909116815260200190565b6001600160601b0391909116815260200190565b6001600160601b0392831681529116602082015260400190565b6001600160a01b03811681146107b957600080fdfe54726962653a20626c6f636b206e756d6265722065786365656473203332206269747354726962653a20746f74616c537570706c792065786365656473203936206269747354726962653a207472616e7366657220616d6f756e742065786365656473207370656e64657220616c6c6f77616e636554726962653a207472616e7366657220616d6f756e7420657863656564732062616c616e636554726962653a20616d6f756e7420657863656564732039362062697473000000a26469706673582212204b5ab84c8ee5befcd5fba2745834ef385b0d07beb1f852bc25562eb10a137ac064736f6c63430006060033a2646970667358221220062ff29caa9fb83e030acb922feb057204cd2a5c38816a82f996dd0f7178683c64736f6c63430006060033
Deployed Bytecode
0x60806040523480156200001157600080fd5b5060043610620002805760003560e01c80639010d07c1162000159578063c1ef303a11620000c9578063e0a200461162000087578063e0a200461462000560578063e1c7392a146200056a578063e43581b81462000574578063e6eb982f146200058b578063eacdd9e814620005a25762000280565b8063c1ef303a14620004fa578063ca15c8731462000511578063cfbd48851462000528578063d5391393146200053f578063d547741f14620005495762000280565b8063a217fddf1162000117578063a217fddf14620004a1578063aa271e1a14620004ab578063af648c3d14620004c2578063b86677fe14620004d9578063b9022dc014620004e35762000280565b80639010d07c146200044857806391d14854146200045f57806394b1d2c014620004765780639711ac34146200048d5780639a9ba4da14620004975762000280565b806336568abe11620001f55780635f06d76111620001b35780635f06d76114620003d3578063611cf19b14620003ea5780636186943e146200040157806384bb0a6b14620004185780638dd9227614620004315762000280565b806336568abe146200036d57806338b7f4461462000384578063395c62e8146200038e5780634334614a14620003a55780634c9f938414620003bc5762000280565b8063248a9ca31162000243578063248a9ca3146200030557806324ea54f4146200032b578063261707fa1462000335578063282c51f3146200034c5780632f2ff15d14620003565762000280565b8063080bf57c14620002855780630900cc33146200029e5780630c68ba2114620002b557806310511f9614620002e4578063201175c214620002fb575b600080fd5b6200029c6200029636600462001496565b620005b9565b005b6200029c620002af36600462001410565b62000683565b620002cc620002c636600462001410565b620006d1565b604051620002db9190620015d1565b60405180910390f35b6200029c620002f536600462001410565b620006fa565b6200029c62000745565b6200031c620003163660046200147d565b620007ee565b604051620002db9190620015dc565b6200031c62000803565b6200029c6200034636600462001410565b6200081c565b6200031c62000858565b6200029c6200036736600462001496565b62000866565b6200029c6200037e36600462001496565b620008b6565b6200031c620008ff565b6200029c6200039f36600462001410565b6200090d565b620002cc620003b636600462001410565b62000949565b6200029c620003cd366004620014d2565b6200095d565b6200029c620003e436600462001410565b62000993565b6200029c620003fb36600462001410565b620009c8565b620002cc6200041236600462001410565b62000a3c565b6200042262000a50565b604051620002db91906200158a565b6200029c6200044236600462001410565b62000a5f565b6200042262000459366004620014d2565b62000a9b565b620002cc6200047036600462001496565b62000ac2565b6200029c6200048736600462001410565b62000ae2565b620002cc62000b1e565b6200042262000b2e565b6200031c62000b43565b620002cc620004bc36600462001410565b62000b48565b6200029c620004d336600462001410565b62000b5c565b6200042262000b98565b6200029c620004f436600462001410565b62000ba7565b6200029c6200050b36600462001410565b62000bdc565b6200031c620005223660046200147d565b62000c18565b6200029c6200053936600462001410565b62000c31565b6200031c62000c6d565b6200029c6200055a36600462001496565b62000c7b565b6200031c62000cbb565b6200029c62000cc9565b620002cc6200058536600462001410565b62000df2565b6200029c6200059c36600462001410565b62000e06565b6200029c620005b33660046200142e565b62000e42565b620005c433620006d1565b620005ec5760405162461bcd60e51b8152600401620005e39062001825565b60405180910390fd5b604051620005fa906200155c565b6040518091039020821415620006245760405162461bcd60e51b8152600401620005e3906200186a565b60405163d547741f60e01b8152309063d547741f906200064b9085908590600401620015e5565b600060405180830381600087803b1580156200066657600080fd5b505af11580156200067b573d6000803e3d6000fd5b505050505050565b6200068e3362000df2565b620006ad5760405162461bcd60e51b8152600401620005e3906200163e565b620006ce604051620006bf906200152c565b60405180910390208262000c7b565b50565b6000620006f4604051620006e59062001543565b60405180910390208362000ac2565b92915050565b620007053362000df2565b620007245760405162461bcd60e51b8152600401620005e3906200163e565b620006ce60405162000736906200152c565b60405180910390208262000866565b600354600160a01b900460ff1615620007725760405162461bcd60e51b8152600401620005e39062001743565b6003546001600160a01b031633146200079f5760405162461bcd60e51b8152600401620005e39062001702565b6003805460ff60a01b1916600160a01b1790556040517f55728014a7cf4447d0a7e11503cf9ab1ca633624fa3150f8fe149b56e3c026fb90620007e4904290620015dc565b60405180910390a1565b60009081526020819052604090206002015490565b604051620008119062001543565b604051809103902081565b620008273362000df2565b620008465760405162461bcd60e51b8152600401620005e3906200163e565b620006ce604051620007369062001573565b60405162000811906200152c565b60008281526020819052604090206002015462000887906200047062000fe6565b620008a65760405162461bcd60e51b8152600401620005e39062001683565b620008b2828262000fea565b5050565b620008c062000fe6565b6001600160a01b0316816001600160a01b031614620008f35760405162461bcd60e51b8152600401620005e390620018b6565b620008b282826200105e565b60405162000811906200155c565b620009183362000df2565b620009375760405162461bcd60e51b8152600401620005e3906200163e565b620006ce60405162000736906200155c565b6000620006f4604051620006e5906200152c565b620009683362000df2565b620009875760405162461bcd60e51b8152600401620005e3906200163e565b620008b28282620010d2565b6200099e3362000df2565b620009bd5760405162461bcd60e51b8152600401620005e3906200163e565b620006ce8162001124565b620009d33362000df2565b620009f25760405162461bcd60e51b8152600401620005e3906200163e565b600380546001600160a01b0319166001600160a01b0383169081179091556040517f815cf7ef55cab2e0662e0739c044d60e9a897f882091d48baa1b0b30d28f8a3090600090a250565b6000620006f4604051620006e5906200150d565b6003546001600160a01b031681565b62000a6a3362000df2565b62000a895760405162461bcd60e51b8152600401620005e3906200163e565b620006ce604051620006bf906200150d565b600082815260208190526040812062000abb908363ffffffff6200117816565b9392505050565b600082815260208190526040812062000abb908363ffffffff6200118616565b62000aed3362000df2565b62000b0c5760405162461bcd60e51b8152600401620005e3906200163e565b620006ce604051620007369062001543565b600354600160a01b900460ff1681565b6001546201000090046001600160a01b031681565b600081565b6000620006f4604051620006e59062001573565b62000b673362000df2565b62000b865760405162461bcd60e51b8152600401620005e3906200163e565b620006ce604051620006bf9062001543565b6002546001600160a01b031681565b62000bb23362000df2565b62000bd15760405162461bcd60e51b8152600401620005e3906200163e565b620006ce816200119d565b62000be73362000df2565b62000c065760405162461bcd60e51b8152600401620005e3906200163e565b620006ce60405162000736906200150d565b6000818152602081905260408120620006f490620011e7565b62000c3c3362000df2565b62000c5b5760405162461bcd60e51b8152600401620005e3906200163e565b620006ce604051620006bf9062001573565b604051620008119062001573565b60008281526020819052604090206002015462000c9c906200047062000fe6565b620008f35760405162461bcd60e51b8152600401620005e39062001787565b60405162000811906200150d565b600154610100900460ff168062000ce5575062000ce5620011f4565b8062000cf4575060015460ff16155b62000d135760405162461bcd60e51b8152600401620005e390620017d7565b600154610100900460ff1615801562000d3e576001805460ff1961ff00199091166101001716811790555b62000d493362001207565b60003060405162000d5a90620013dc565b62000d6691906200158a565b604051809103906000f08015801562000d83573d6000803e3d6000fd5b50905062000d918162001124565b6000303360405162000da390620013ea565b62000db09291906200159e565b604051809103906000f08015801562000dcd573d6000803e3d6000fd5b50905062000ddb816200119d565b50508015620006ce576001805461ff001916905550565b6000620006f4604051620006e5906200155c565b62000e113362000df2565b62000e305760405162461bcd60e51b8152600401620005e3906200163e565b620006ce604051620006bf906200155c565b62000e4d3362000df2565b62000e6c5760405162461bcd60e51b8152600401620005e3906200163e565b6002546040516370a0823160e01b81526001600160a01b0390911690829082906370a082319062000ea29030906004016200158a565b60206040518083038186803b15801562000ebb57600080fd5b505afa15801562000ed0573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000ef69190620014f4565b101562000f175760405162461bcd60e51b8152600401620005e390620016d2565b60405163a9059cbb60e01b81526001600160a01b0382169063a9059cbb9062000f479086908690600401620015b8565b602060405180830381600087803b15801562000f6257600080fd5b505af115801562000f77573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019062000f9d91906200145b565b50826001600160a01b03167ffd90a2bc2c0c3cf07693529b256c4173a944fe9f55c1984c09a10a1ad28c11648360405162000fd99190620015dc565b60405180910390a2505050565b3390565b60008281526020819052604090206200100a908263ffffffff6200122816565b15620008b2576200101a62000fe6565b6001600160a01b0316816001600160a01b0316837f2f8788117e7eff1d82e926ec794901d17c78024a50270940304540a733656f0d60405160405180910390a45050565b60008281526020819052604090206200107e908263ffffffff6200123f16565b15620008b2576200108e62000fe6565b6001600160a01b0316816001600160a01b0316837ff6391f5c32d9c69d2a47ea670b442974b53935d1edc7fd64eb21e047a839171b60405160405180910390a45050565b600082815260208190526040808220600201549051839285917fbd79b86ffe0ab8e8776151514217cd7cacd52c909f66475c3af44e129f0b00ff9190a460009182526020829052604090912060020155565b6001805462010000600160b01b031916620100006001600160a01b038416908102919091179091556040517fb382b2a2d84e1d7542e0d58950e00d33ddc7a4b379a265768bf3e8640dde4ef190600090a250565b600062000abb838362001256565b600062000abb836001600160a01b0384166200129f565b600280546001600160a01b0319166001600160a01b0383169081179091556040517f9675664499c8d4f09c5268d1696ba833416ed56d870558fa7a722bb8aff5d90f90600090a250565b6000620006f482620012b7565b60006200120130620012bb565b15905090565b620006ce60405162001219906200155c565b604051809103902082620008a6565b600062000abb836001600160a01b038416620012c1565b600062000abb836001600160a01b03841662001310565b815460009082106200127c5760405162461bcd60e51b8152600401620005e390620015fc565b8260000182815481106200128c57fe5b9060005260206000200154905092915050565b60009081526001919091016020526040902054151590565b5490565b3b151590565b6000620012cf83836200129f565b6200130757508154600181810184556000848152602080822090930184905584548482528286019093526040902091909155620006f4565b506000620006f4565b60008181526001830160205260408120548015620013d157835460001980830191908101906000908790839081106200134557fe5b90600052602060002001549050808760000184815481106200136357fe5b6000918252602080832090910192909255828152600189810190925260409020908401905586548790806200139457fe5b60019003818190600052602060002001600090559055866001016000878152602001908152602001600020600090556001945050505050620006f4565b6000915050620006f4565b6122c4806200190683390190565b6121098062003bca83390190565b80356001600160a01b0381168114620006f457600080fd5b60006020828403121562001422578081fd5b62000abb8383620013f8565b6000806040838503121562001441578081fd5b6200144d8484620013f8565b946020939093013593505050565b6000602082840312156200146d578081fd5b8151801515811462000abb578182fd5b6000602082840312156200148f578081fd5b5035919050565b60008060408385031215620014a9578182fd5b8235915060208301356001600160a01b0381168114620014c7578182fd5b809150509250929050565b60008060408385031215620014e5578182fd5b50508035926020909101359150565b60006020828403121562001506578081fd5b5051919050565b725043565f434f4e54524f4c4c45525f524f4c4560681b815260130190565b6a4255524e45525f524f4c4560a81b8152600b0190565b6c475541524449414e5f524f4c4560981b8152600d0190565b6a474f5645524e5f524f4c4560a81b8152600b0190565b6a4d494e5445525f524f4c4560a81b8152600b0190565b6001600160a01b0391909116815260200190565b6001600160a01b0392831681529116602082015260400190565b6001600160a01b03929092168252602082015260400190565b901515815260200190565b90815260200190565b9182526001600160a01b0316602082015260400190565b60208082526022908201527f456e756d657261626c655365743a20696e646578206f7574206f6620626f756e604082015261647360f01b606082015260800190565b60208082526025908201527f5065726d697373696f6e733a2043616c6c6572206973206e6f74206120676f7660408201526432b93737b960d91b606082015260800190565b6020808252602f908201527f416363657373436f6e74726f6c3a2073656e646572206d75737420626520616e60408201526e0818591b5a5b881d1bc819dc985b9d608a1b606082015260800190565b602080825260169082015275436f72653a204e6f7420656e6f75676820547269626560501b604082015260600190565b60208082526021908201527f436f72653a2043616c6c6572206973206e6f742047656e657369732047726f756040820152600760fc1b606082015260800190565b60208082526024908201527f436f72653a2047656e657369732047726f757020616c726561647920636f6d706040820152636c65746560e01b606082015260800190565b60208082526030908201527f416363657373436f6e74726f6c3a2073656e646572206d75737420626520616e60408201526f2061646d696e20746f207265766f6b6560801b606082015260800190565b6020808252602e908201527f496e697469616c697a61626c653a20636f6e747261637420697320616c72656160408201526d191e481a5b9a5d1a585b1a5e995960921b606082015260800190565b60208082526025908201527f5065726d697373696f6e733a2043616c6c6572206973206e6f74206120677561604082015264393234b0b760d91b606082015260800190565b6020808252602c908201527f5065726d697373696f6e733a20477561726469616e2063616e6e6f742072657660408201526b37b5b29033b7bb32b93737b960a11b606082015260800190565b6020808252602f908201527f416363657373436f6e74726f6c3a2063616e206f6e6c792072656e6f756e636560408201526e103937b632b9903337b91039b2b63360891b60608201526080019056fe60806040523480156200001157600080fd5b50604051620022c4380380620022c48339810160408190526200003491620002aa565b604080518082018252600781526611995a481554d160ca1b6020808301918252835180850190945260038085526246454960e81b91850191909152825185949262000080929162000208565b5080516200009690600490602084019062000208565b5050600580546001600160a01b039093166201000002610100600160b01b031960ff199094166012179390931692909217909155506040514690620000db90620002da565b604051908190039020620000f76001600160e01b036200016d16565b805160209182012060408051808201825260018152603160f81b90840152516200014993927fc89efdaa54c0f20c7adf612882df0950f5a951637e0307cdcb4c672f298b8bc691869130910162000344565b60405160208183030381529060405280519060200120600781905550505062000370565b60038054604080516020601f6002600019610100600188161502019095169490940493840181900481028201810190925282815260609390929091830182828015620001fd5780601f10620001d157610100808354040283529160200191620001fd565b820191906000526020600020905b815481529060010190602001808311620001df57829003601f168201915b505050505090505b90565b828054600181600116156101000203166002900490600052602060002090601f016020900481019282601f106200024b57805160ff19168380011785556200027b565b828001600101855582156200027b579182015b828111156200027b5782518255916020019190600101906200025e565b50620002899291506200028d565b5090565b6200020591905b8082111562000289576000815560010162000294565b600060208284031215620002bc578081fd5b81516001600160a01b0381168114620002d3578182fd5b9392505050565b7f454950373132446f6d61696e28737472696e67206e616d652c737472696e672081527f76657273696f6e2c75696e7432353620636861696e49642c6164647265737320602082015271766572696679696e67436f6e74726163742960701b604082015260520190565b9485526020850193909352604084019190915260608301526001600160a01b0316608082015260a00190565b611f4480620003806000396000f3fe608060405234801561001057600080fd5b50600436106101cf5760003560e01c806379cc679011610104578063a9059cbb116100a2578063bc701e7511610071578063bc701e751461036c578063d505accf1461037f578063dd62ed3e14610392578063f2f4eb26146103a5576101cf565b8063a9059cbb14610336578063b490589714610349578063b6232c9914610351578063b86677fe14610364576101cf565b80638456cb59116100de5780638456cb59146102fe57806395d89b41146103065780639a9ba4da1461030e578063a457c2d714610323576101cf565b806379cc6790146102c55780637ecebe00146102d857806380009630146102eb576101cf565b8063395093511161017157806342966c681161014b57806342966c681461028f5780635c975abb146102a25780636b6dff0a146102aa57806370a08231146102b2576101cf565b8063395093511461025f5780633f4ba83a1461027257806340c10f191461027c576101cf565b806323b872dd116101ad57806323b872dd1461022757806330adf81f1461023a578063313ce567146102425780633644e51514610257576101cf565b806306fdde03146101d4578063095ea7b3146101f257806318160ddd14610212575b600080fd5b6101dc6103ad565b6040516101e99190611a65565b60405180910390f35b61020561020036600461190f565b610443565b6040516101e991906119ff565b61021a610460565b6040516101e99190611a0a565b61020561023536600461185a565b610466565b61021a6104f3565b61024a610517565b6040516101e99190611e56565b61021a610520565b61020561026d36600461190f565b610526565b61027a61057a565b005b61027a61028a36600461190f565b6106b9565b61027a61029d366004611976565b6107d8565b610205610820565b61021a61082e565b61021a6102c0366004611806565b6108b8565b61027a6102d336600461190f565b6108d3565b61021a6102e6366004611806565b6109e6565b61027a6102f9366004611806565b6109f8565b61027a610aed565b6101dc610c21565b610316610c82565b6040516101e991906119c1565b61020561033136600461190f565b610d0a565b61020561034436600461190f565b610d78565b61021a610d8c565b61027a61035f366004611822565b610d96565b610316610e8e565b61031661037a366004611806565b610ede565b61027a61038d36600461189a565b610ef9565b61021a6103a0366004611822565b611068565b610316611093565b60038054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156104395780601f1061040e57610100808354040283529160200191610439565b820191906000526020600020905b81548152906001019060200180831161041c57829003601f168201915b5050505050905090565b60006104576104506110a8565b84846110ac565b50600192915050565b60025490565b6000610473848484611160565b6104e98461047f6110a8565b6104e485604051806060016040528060288152602001611ec2602891396001600160a01b038a166000908152600160205260408120906104bd6110a8565b6001600160a01b03168152602081019190915260400160002054919063ffffffff61117b16565b6110ac565b5060019392505050565b7f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c981565b60055460ff1690565b60075481565b60006104576105336110a8565b846104e485600160006105446110a8565b6001600160a01b03908116825260208083019390935260409182016000908120918c16815292529020549063ffffffff6111a716565b600554604051631c86b03760e31b8152620100009091046001600160a01b03169063e43581b8906105af9033906004016119c1565b60206040518083038186803b1580156105c757600080fd5b505afa1580156105db573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906105ff919061193a565b8061068a5750600554604051630c68ba2160e01b8152620100009091046001600160a01b031690630c68ba219061063a9033906004016119c1565b60206040518083038186803b15801561065257600080fd5b505afa158015610666573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061068a919061193a565b6106af5760405162461bcd60e51b81526004016106a690611ba2565b60405180910390fd5b6106b76111d3565b565b6005546040516355138f0d60e11b8152620100009091046001600160a01b03169063aa271e1a906106ee9033906004016119c1565b60206040518083038186803b15801561070657600080fd5b505afa15801561071a573d6000803e3d6000fd5b505050506040513d601f19601f8201168201806040525081019061073e919061193a565b61075a5760405162461bcd60e51b81526004016106a690611b29565b610762610820565b1561077f5760405162461bcd60e51b81526004016106a690611cba565b6107898282611242565b336001600160a01b0316826001600160a01b03167fb1233017d63154bc561d57c16f7b6a55e2e1acd7fcac94045a9f35fb31a850ca836040516107cc9190611a0a565b60405180910390a35050565b6107e181611302565b604051339081907f227fb4b3aae8331f21af5167739c291fefe3afd3c2e08cea44f499e564f486ef90610815908590611a0a565b60405180910390a350565b600554610100900460ff1690565b6000610838610e8e565b6001600160a01b03166370a08231306040518263ffffffff1660e01b815260040161086391906119c1565b60206040518083038186803b15801561087b57600080fd5b505afa15801561088f573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108b3919061198e565b905090565b6001600160a01b031660009081526020819052604090205490565b60055460405163219a30a560e11b8152620100009091046001600160a01b031690634334614a906109089033906004016119c1565b60206040518083038186803b15801561092057600080fd5b505afa158015610934573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610958919061193a565b6109745760405162461bcd60e51b81526004016106a690611c26565b61097c610820565b156109995760405162461bcd60e51b81526004016106a690611cba565b6109a38282611316565b336001600160a01b0316826001600160a01b03167f227fb4b3aae8331f21af5167739c291fefe3afd3c2e08cea44f499e564f486ef836040516107cc9190611a0a565b60086020526000908152604090205481565b600554604051631c86b03760e31b8152620100009091046001600160a01b03169063e43581b890610a2d9033906004016119c1565b60206040518083038186803b158015610a4557600080fd5b505afa158015610a59573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610a7d919061193a565b610a995760405162461bcd60e51b81526004016106a690611dde565b6005805462010000600160b01b031916620100006001600160a01b038416908102919091179091556040517fad9400e618eb1344fde53db22397a1b82c765527ecbba3a5c86bcac15090828b90600090a250565b600554604051631c86b03760e31b8152620100009091046001600160a01b03169063e43581b890610b229033906004016119c1565b60206040518083038186803b158015610b3a57600080fd5b505afa158015610b4e573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610b72919061193a565b80610bfd5750600554604051630c68ba2160e01b8152620100009091046001600160a01b031690630c68ba2190610bad9033906004016119c1565b60206040518083038186803b158015610bc557600080fd5b505afa158015610bd9573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610bfd919061193a565b610c195760405162461bcd60e51b81526004016106a690611ba2565b6106b76113f8565b60048054604080516020601f60026000196101006001881615020190951694909404938401819004810282018101909252828152606093909290918301828280156104395780601f1061040e57610100808354040283529160200191610439565b6000600560029054906101000a90046001600160a01b03166001600160a01b0316639a9ba4da6040518163ffffffff1660e01b815260040160206040518083038186803b158015610cd257600080fd5b505afa158015610ce6573d6000803e3d6000fd5b505050506040513d601f19601f820116820180604052508101906108b3919061195a565b6000610457610d176110a8565b846104e485604051806060016040528060258152602001611eea6025913960016000610d416110a8565b6001600160a01b03908116825260208083019390935260409182016000908120918d1681529252902054919063ffffffff61117b16565b6000610457610d856110a8565b8484611160565b6000610838610c82565b600554604051631c86b03760e31b8152620100009091046001600160a01b03169063e43581b890610dcb9033906004016119c1565b60206040518083038186803b158015610de357600080fd5b505afa158015610df7573d6000803e3d6000fd5b505050506040513d601f19601f82011682018060405250810190610e1b919061193a565b610e375760405162461bcd60e51b81526004016106a690611dde565b6001600160a01b0382811660008181526006602052604080822080546001600160a01b0319169486169485179055517f88bb9e877881758e827c849b8a0e38421bd5ff916f4ef79ed65aec74cc04a5da9190a35050565b6000600560029054906101000a90046001600160a01b03166001600160a01b031663b86677fe6040518163ffffffff1660e01b815260040160206040518083038186803b158015610cd257600080fd5b6006602052600090815260409020546001600160a01b031681565b42841015610f195760405162461bcd60e51b81526004016106a690611c5d565b6007546001600160a01b03881660009081526008602090815260408083208054600181019091559051929392610f7a927f6e71edae12b1b97f4d1f60370fef10105fa2faae0126114a169c64845d6126c9928d928d928d92918d9101611a13565b60405160208183030381529060405280519060200120604051602001610fa19291906119a6565b604051602081830303815290604052805190602001209050600060018286868660405160008152602001604052604051610fde9493929190611a47565b6020604051602081039080840390855afa158015611000573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116158015906110365750886001600160a01b0316816001600160a01b0316145b6110525760405162461bcd60e51b81526004016106a690611ce4565b61105d8989896110ac565b505050505050505050565b6001600160a01b03918216600090815260016020908152604080832093909416825291909152205490565b6005546201000090046001600160a01b031690565b3390565b6001600160a01b0383166110d25760405162461bcd60e51b81526004016106a690611d9a565b6001600160a01b0382166110f85760405162461bcd60e51b81526004016106a690611b60565b6001600160a01b0380841660008181526001602090815260408083209487168084529490915290819020849055517f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590611153908590611a0a565b60405180910390a3505050565b61116b838383611455565b611176838383611576565b505050565b6000818484111561119f5760405162461bcd60e51b81526004016106a69190611a65565b505050900390565b6000828201838110156111cc5760405162461bcd60e51b81526004016106a690611bef565b9392505050565b6111db610820565b6111f75760405162461bcd60e51b81526004016106a690611afb565b6005805461ff00191690557f5db9ee0a495bf2e6ff9c91a7834c1ba4fdd244a5e8aa4e537bd38aeae4b073aa61122b6110a8565b60405161123891906119c1565b60405180910390a1565b6001600160a01b0382166112685760405162461bcd60e51b81526004016106a690611e1f565b61127460008383611176565b600254611287908263ffffffff6111a716565b6002556001600160a01b0382166000908152602081905260409020546112b3908263ffffffff6111a716565b6001600160a01b0383166000818152602081905260408082209390935591519091907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906107cc908590611a0a565b61131361130d6110a8565b82611316565b50565b6001600160a01b03821661133c5760405162461bcd60e51b81526004016106a690611d14565b61134882600083611176565b61138b81604051806060016040528060228152602001611e7a602291396001600160a01b038516600090815260208190526040902054919063ffffffff61117b16565b6001600160a01b0383166000908152602081905260409020556002546113b7908263ffffffff6117de16565b6002556040516000906001600160a01b038416907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906107cc908590611a0a565b611400610820565b1561141d5760405162461bcd60e51b81526004016106a690611cba565b6005805461ff0019166101001790557f62e78cea01bee320cd4e420270b5ea74000d11b0c9f74754ebdbfc544b05a25861122b6110a8565b6001600160a01b03831661147b5760405162461bcd60e51b81526004016106a690611d55565b6001600160a01b0382166114a15760405162461bcd60e51b81526004016106a690611ab8565b6114ac838383611176565b6114ef81604051806060016040528060268152602001611e9c602691396001600160a01b038616600090815260208190526040902054919063ffffffff61117b16565b6001600160a01b038085166000908152602081905260408082209390935590841681522054611524908263ffffffff6111a716565b6001600160a01b0380841660008181526020819052604090819020939093559151908516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90611153908590611a0a565b6001600160a01b038084166000908152600660205260409020541680156115fc57604051636e22230d60e01b81526001600160a01b03821690636e22230d906115c99087908790339088906004016119d5565b600060405180830381600087803b1580156115e357600080fd5b505af11580156115f7573d6000803e3d6000fd5b505050505b6001600160a01b0380841660009081526006602052604090205416801561168257604051636e22230d60e01b81526001600160a01b03821690636e22230d9061164f9088908890339089906004016119d5565b600060405180830381600087803b15801561166957600080fd5b505af115801561167d573d6000803e3d6000fd5b505050505b336000818152600660205260409020546001600160a01b0390811691908716148015906116b85750336001600160a01b03861614155b80156116cc57506001600160a01b03811615155b1561173657604051636e22230d60e01b81526001600160a01b03821690636e22230d90611703908990899033908a906004016119d5565b600060405180830381600087803b15801561171d57600080fd5b505af1158015611731573d6000803e3d6000fd5b505050505b6000805260066020527f54cdd369e4e8a8515e52ca72ec816c2101831ad1f18bf44102ed171459c9b4f8546001600160a01b031680156117d557604051636e22230d60e01b81526001600160a01b03821690636e22230d906117a2908a908a9033908b906004016119d5565b600060405180830381600087803b1580156117bc57600080fd5b505af11580156117d0573d6000803e3d6000fd5b505050505b50505050505050565b6000828211156118005760405162461bcd60e51b81526004016106a690611c83565b50900390565b600060208284031215611817578081fd5b81356111cc81611e64565b60008060408385031215611834578081fd5b823561183f81611e64565b9150602083013561184f81611e64565b809150509250929050565b60008060006060848603121561186e578081fd5b833561187981611e64565b9250602084013561188981611e64565b929592945050506040919091013590565b600080600080600080600060e0888a0312156118b4578283fd5b87356118bf81611e64565b965060208801356118cf81611e64565b95506040880135945060608801359350608088013560ff811681146118f2578384fd5b9699959850939692959460a0840135945060c09093013592915050565b60008060408385031215611921578182fd5b823561192c81611e64565b946020939093013593505050565b60006020828403121561194b578081fd5b815180151581146111cc578182fd5b60006020828403121561196b578081fd5b81516111cc81611e64565b600060208284031215611987578081fd5b5035919050565b60006020828403121561199f578081fd5b5051919050565b61190160f01b81526002810192909252602282015260420190565b6001600160a01b0391909116815260200190565b6001600160a01b039485168152928416602084015292166040820152606081019190915260800190565b901515815260200190565b90815260200190565b9586526001600160a01b0394851660208701529290931660408501526060840152608083019190915260a082015260c00190565b93845260ff9290921660208401526040830152606082015260800190565b6000602080835283518082850152825b81811015611a9157858101830151858201604001528201611a75565b81811115611aa25783604083870101525b50601f01601f1916929092016040019392505050565b60208082526023908201527f45524332303a207472616e7366657220746f20746865207a65726f206164647260408201526265737360e81b606082015260800190565b60208082526014908201527314185d5cd8589b194e881b9bdd081c185d5cd95960621b604082015260600190565b6020808252601f908201527f436f72655265663a2043616c6c6572206973206e6f742061206d696e74657200604082015260600190565b60208082526022908201527f45524332303a20617070726f766520746f20746865207a65726f206164647265604082015261737360f01b606082015260800190565b6020808252602d908201527f436f72655265663a2043616c6c6572206973206e6f742061206775617264696160408201526c371037b91033b7bb32b93737b960991b606082015260800190565b6020808252601b908201527f536166654d6174683a206164646974696f6e206f766572666c6f770000000000604082015260600190565b6020808252601f908201527f436f72655265663a2043616c6c6572206973206e6f742061206275726e657200604082015260600190565b6020808252600c908201526b11995a4e881156141254915160a21b604082015260600190565b6020808252601e908201527f536166654d6174683a207375627472616374696f6e206f766572666c6f770000604082015260600190565b60208082526010908201526f14185d5cd8589b194e881c185d5cd95960821b604082015260600190565b6020808252601690820152754665693a20494e56414c49445f5349474e415455524560501b604082015260600190565b60208082526021908201527f45524332303a206275726e2066726f6d20746865207a65726f206164647265736040820152607360f81b606082015260800190565b60208082526025908201527f45524332303a207472616e736665722066726f6d20746865207a65726f206164604082015264647265737360d81b606082015260800190565b60208082526024908201527f45524332303a20617070726f76652066726f6d20746865207a65726f206164646040820152637265737360e01b606082015260800190565b60208082526021908201527f436f72655265663a2043616c6c6572206973206e6f74206120676f7665726e6f6040820152603960f91b606082015260800190565b6020808252601f908201527f45524332303a206d696e7420746f20746865207a65726f206164647265737300604082015260600190565b60ff91909116815260200190565b6001600160a01b038116811461131357600080fdfe45524332303a206275726e20616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e7420657863656564732062616c616e636545524332303a207472616e7366657220616d6f756e74206578636565647320616c6c6f77616e636545524332303a2064656372656173656420616c6c6f77616e63652062656c6f77207a65726fa264697066735822122050e890c3b2545b3935ee59eb10f843e1ae9421c4c123c2534bea07e27e8ff0f164736f6c6343000606003360806040526b033b2e3c9fd0803ce80000006000553480156200002157600080fd5b506040516200210938038062002109833981016040819052620000449162000121565b600080546001600160a01b0384168083526003602052604080842080546001600160601b0319166001600160601b0390941693909317909255825491519092917fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef91620000b2919062000179565b60405180910390a3600180546001600160a01b0319166001600160a01b0383811691909117918290556040517f3b0007eb941cf645526cbb3a4fdaecda9d28ce4843167d9263b536a1f1edc0f69262000111926000929116906200015f565b60405180910390a150506200019b565b6000806040838503121562000134578182fd5b8251620001418162000182565b6020840151909250620001548162000182565b809150509250929050565b6001600160a01b0392831681529116602082015260400190565b90815260200190565b6001600160a01b03811681146200019857600080fd5b50565b611f5e80620001ab6000396000f3fe608060405234801561001057600080fd5b50600436106101585760003560e01c806370a08231116100c3578063c3cda5201161007c578063c3cda520146102cc578063d505accf146102df578063dd62ed3e146102f2578063e7a324dc14610305578063f1127ed81461030d578063fca3b5aa1461032e57610158565b806370a0823114610258578063782d6fe11461026b5780637ecebe001461028b57806395d89b411461029e578063a9059cbb146102a6578063b4b5ea57146102b957610158565b806330adf81f1161011557806330adf81f146101e0578063313ce567146101e857806340c10f19146101fd578063587cde1e146102125780635c19a95c146102255780636fcfff451461023857610158565b806306fdde031461015d578063075461721461017b578063095ea7b31461019057806318160ddd146101b057806320606b70146101c557806323b872dd146101cd575b600080fd5b610165610341565b6040516101729190611b78565b60405180910390f35b610183610362565b6040516101729190611a9c565b6101a361019e3660046118ab565b610371565b6040516101729190611aca565b6101b861043b565b6040516101729190611ad5565b6101b8610441565b6101a36101db3660046117ff565b610458565b6101b86105a7565b6101f06105b3565b6040516101729190611e1c565b61021061020b3660046118ab565b6105b8565b005b6101836102203660046117b0565b610794565b6102106102333660046117b0565b6107af565b61024b6102463660046117b0565b6107bc565b6040516101729190611dec565b6101b86102663660046117b0565b6107d4565b61027e6102793660046118ab565b6107f8565b6040516101729190611e2a565b6101b86102993660046117b0565b610a06565b610165610a18565b6101a36102b43660046118ab565b610a39565b61027e6102c73660046117b0565b610a80565b6102106102da3660046118d5565b610af1565b6102106102ed36600461183f565b610cd8565b6101b86103003660046117cb565b610fcc565b6101b8611000565b61032061031b36600461192e565b61100c565b604051610172929190611dfd565b61021061033c3660046117b0565b611041565b60405180604001604052806005815260200164547269626560d81b81525081565b6001546001600160a01b031681565b60008060001983141561038757506000196103b7565b6103b4836040518060400160405280601d8152602001600080516020611f098339815191528152506110d4565b90505b3360008181526002602090815260408083206001600160a01b03891680855292529182902080546001600160601b0319166001600160601b03861617905590519091907f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590610427908590611e2a565b60405180910390a360019150505b92915050565b60005481565b60405161044d906119f2565b604051809103902081565b6001600160a01b038316600090815260026020908152604080832033808552908352818420548251808401909352601d8352600080516020611f0983398151915293830193909352916001600160601b03169083906104b89086906110d4565b9050866001600160a01b0316836001600160a01b0316141580156104e557506001600160601b0382811614155b1561058f57600061050f8383604051806060016040528060308152602001611eb360309139611103565b6001600160a01b038981166000818152600260209081526040808320948a16808452949091529081902080546001600160601b0319166001600160601b0386161790555192935090917f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92590610585908590611e2a565b60405180910390a3505b61059a878783611142565b5060019695505050505050565b60405161044d90611988565b601281565b6001546001600160a01b031633146105eb5760405162461bcd60e51b81526004016105e290611bcb565b60405180910390fd5b6001600160a01b0382166106115760405162461bcd60e51b81526004016105e290611c02565b6000610640826040518060400160405280601d8152602001600080516020611f098339815191528152506110d4565b90506000610668600054604051806060016040528060228152602001611e91602291396110d4565b905061068d8183604051806060016040528060228152602001611e9160229139611305565b6001600160601b0390811660009081556001600160a01b0386168152600360209081526040918290205482518084019093528183527f54726962653a207472616e7366657220616d6f756e74206f766572666c6f7773918301919091526106f79216908490611305565b6001600160a01b03851660008181526003602052604080822080546001600160601b0319166001600160601b03959095169490941790935591519091907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef90610761908690611e2a565b60405180910390a36001600160a01b0380851660009081526004602052604081205461078e921684611341565b50505050565b6004602052600090815260409020546001600160a01b031681565b6107b9338261150d565b50565b60066020526000908152604090205463ffffffff1681565b6001600160a01b03166000908152600360205260409020546001600160601b031690565b60004382106108195760405162461bcd60e51b81526004016105e290611db5565b6001600160a01b03831660009081526006602052604090205463ffffffff1680610847576000915050610435565b6001600160a01b038416600090815260056020908152604080832063ffffffff6000198601811685529252909120541683106108c3576001600160a01b03841660009081526005602090815260408083206000199490940163ffffffff1683529290522054600160201b90046001600160601b03169050610435565b6001600160a01b038416600090815260056020908152604080832083805290915290205463ffffffff168310156108fe576000915050610435565b600060001982015b8163ffffffff168163ffffffff1611156109c157600282820363ffffffff16048103610930611771565b506001600160a01b038716600090815260056020908152604080832063ffffffff858116855290835292819020815180830190925254928316808252600160201b9093046001600160601b0316918101919091529087141561099c576020015194506104359350505050565b805163ffffffff168711156109b3578193506109ba565b6001820392505b5050610906565b506001600160a01b038516600090815260056020908152604080832063ffffffff909416835292905220546001600160601b03600160201b9091041691505092915050565b60076020526000908152604090205481565b60405180604001604052806005815260200164545249424560d81b81525081565b600080610a69836040518060400160405280601d8152602001600080516020611f098339815191528152506110d4565b9050610a76338583611142565b5060019392505050565b6001600160a01b03811660009081526006602052604081205463ffffffff1680610aab576000610aea565b6001600160a01b0383166000908152600560209081526040808320600019850163ffffffff168452909152902054600160201b90046001600160601b03165b9392505050565b6000604051610aff906119f2565b604080519182900382208282019091526005825264547269626560d81b6020909201919091527febed0dee75115424b4c6084a9ab165e0c99bcf5a44403d7510e1ad1caeaea506610b4e611591565b30604051602001610b629493929190611b36565b6040516020818303038152906040528051906020012090506000604051610b8890611a4d565b604051908190038120610ba3918a908a908a90602001611b12565b60405160208183030381529060405280519060200120905060008282604051602001610bd092919061196d565b604051602081830303815290604052805190602001209050600060018288888860405160008152602001604052604051610c0d9493929190611b5a565b6020604051602081039080840390855afa158015610c2f573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116610c625760405162461bcd60e51b81526004016105e290611cfc565b6001600160a01b03811660009081526007602052604090208054600181019091558914610ca15760405162461bcd60e51b81526004016105e290611d33565b87421115610cc15760405162461bcd60e51b81526004016105e290611c4c565b610ccb818b61150d565b505050505b505050505050565b6000600019861415610ced5750600019610d1d565b610d1a866040518060400160405280601d8152602001600080516020611f098339815191528152506110d4565b90505b6000604051610d2b906119f2565b604080519182900382208282019091526005825264547269626560d81b6020909201919091527febed0dee75115424b4c6084a9ab165e0c99bcf5a44403d7510e1ad1caeaea506610d7a611591565b30604051602001610d8e9493929190611b36565b6040516020818303038152906040528051906020012090506000604051610db490611988565b604080519182900382206001600160a01b038d16600090815260076020908152929020805460018101909155610df69391928e928e928e9290918e9101611ade565b60405160208183030381529060405280519060200120905060008282604051602001610e2392919061196d565b604051602081830303815290604052805190602001209050600060018289898960405160008152602001604052604051610e609493929190611b5a565b6020604051602081039080840390855afa158015610e82573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b038116610eb55760405162461bcd60e51b81526004016105e290611cfc565b8b6001600160a01b0316816001600160a01b031614610ee65760405162461bcd60e51b81526004016105e290611ccf565b88421115610f065760405162461bcd60e51b81526004016105e290611c4c565b84600260008e6001600160a01b03166001600160a01b0316815260200190815260200160002060008d6001600160a01b03166001600160a01b0316815260200190815260200160002060006101000a8154816001600160601b0302191690836001600160601b031602179055508a6001600160a01b03168c6001600160a01b03167f8c5be1e5ebec7d5bd14f71427d1e84f3dd0314c0f7b2291e5b200ac8c7c3b92587604051610fb69190611e2a565b60405180910390a3505050505050505050505050565b6001600160a01b0391821660009081526002602090815260408083209390941682529190915220546001600160601b031690565b60405161044d90611a4d565b600560209081526000928352604080842090915290825290205463ffffffff811690600160201b90046001600160601b031682565b6001546001600160a01b0316331461106b5760405162461bcd60e51b81526004016105e290611d61565b6001546040517f3b0007eb941cf645526cbb3a4fdaecda9d28ce4843167d9263b536a1f1edc0f6916110aa916001600160a01b03909116908490611ab0565b60405180910390a1600180546001600160a01b0319166001600160a01b0392909216919091179055565b600081600160601b84106110fb5760405162461bcd60e51b81526004016105e29190611b78565b509192915050565b6000836001600160601b0316836001600160601b03161115829061113a5760405162461bcd60e51b81526004016105e29190611b78565b505050900390565b6001600160a01b0383166111685760405162461bcd60e51b81526004016105e290611c83565b6001600160a01b03821661118e5760405162461bcd60e51b81526004016105e290611c02565b6001600160a01b0383166000908152600360209081526040918290205482516060810190935260268084526111d9936001600160601b039092169285929190611ee390830139611103565b6001600160a01b03848116600090815260036020908152604080832080546001600160601b0319166001600160601b039687161790559286168252908290205482518084019093528183527f54726962653a207472616e7366657220616d6f756e74206f766572666c6f7773918301919091526112599216908390611305565b6001600160a01b038381166000818152600360205260409081902080546001600160601b0319166001600160601b0395909516949094179093559151908516907fddf252ad1be2c89b69c2b068fc378daa952ba7f163c4a11628f55a4df523b3ef906112c6908590611e2a565b60405180910390a36001600160a01b0380841660009081526004602052604080822054858416835291205461130092918216911683611341565b505050565b6000838301826001600160601b0380871690831610156113385760405162461bcd60e51b81526004016105e29190611b78565b50949350505050565b816001600160a01b0316836001600160a01b03161415801561136c57506000816001600160601b0316115b15611300576001600160a01b03831615611441576001600160a01b03831660009081526006602052604081205463ffffffff1690816113ac5760006113eb565b6001600160a01b0385166000908152600560209081526040808320600019860163ffffffff168452909152902054600160201b90046001600160601b03165b9050600061142f82856040518060400160405280601d81526020017f54726962653a20766f746520616d6f756e7420756e646572666c6f7773000000815250611103565b905061143d86848484611595565b5050505b6001600160a01b03821615611300576001600160a01b03821660009081526006602052604081205463ffffffff16908161147c5760006114bb565b6001600160a01b0384166000908152600560209081526040808320600019860163ffffffff168452909152902054600160201b90046001600160601b03165b905060006114ff82856040518060400160405280601c81526020017f54726962653a20766f746520616d6f756e74206f766572666c6f777300000000815250611305565b9050610cd085848484611595565b6001600160a01b03808316600081815260046020818152604080842080546003845282862054949093528787166001600160a01b031984168117909155905191909516946001600160601b039092169391928592917f3134e8a2e6d97e929a7e54011ea5485d7d196dd5f0ba4d4ef95803e8e3fc257f9190a461078e828483611341565b4690565b60006115b943604051806060016040528060238152602001611e6e6023913961174a565b905060008463ffffffff1611801561160257506001600160a01b038516600090815260056020908152604080832063ffffffff6000198901811685529252909120548282169116145b15611661576001600160a01b0385166000908152600560209081526040808320600019880163ffffffff168452909152902080546fffffffffffffffffffffffff000000001916600160201b6001600160601b03851602179055611700565b60408051808201825263ffffffff80841682526001600160601b0380861660208085019182526001600160a01b038b166000818152600583528781208c871682528352878120965187549451909516600160201b026fffffffffffffffffffffffff000000001995871663ffffffff19958616179590951694909417909555938252600690935292909220805460018801909316929091169190911790555b846001600160a01b03167fdec2bacdd2f05b59de34da9b523dff8be42e5e38e818c82fdb0bae774387a724848460405161173b929190611e3e565b60405180910390a25050505050565b600081600160201b84106110fb5760405162461bcd60e51b81526004016105e29190611b78565b604080518082019091526000808252602082015290565b80356001600160a01b038116811461043557600080fd5b803560ff8116811461043557600080fd5b6000602082840312156117c1578081fd5b610aea8383611788565b600080604083850312156117dd578081fd5b6117e78484611788565b91506117f68460208501611788565b90509250929050565b600080600060608486031215611813578081fd5b833561181e81611e58565b9250602084013561182e81611e58565b929592945050506040919091013590565b600080600080600080600060e0888a031215611859578283fd5b6118638989611788565b96506118728960208a01611788565b9550604088013594506060880135935061188f8960808a0161179f565b925060a0880135915060c0880135905092959891949750929550565b600080604083850312156118bd578182fd5b6118c78484611788565b946020939093013593505050565b60008060008060008060c087890312156118ed578182fd5b6118f78888611788565b95506020870135945060408701359350611914886060890161179f565b92506080870135915060a087013590509295509295509295565b60008060408385031215611940578182fd5b61194a8484611788565b9150602083013563ffffffff81168114611962578182fd5b809150509250929050565b61190160f01b81526002810192909252602282015260420190565b7f5065726d69742861646472657373206f776e65722c616464726573732073706581527f6e6465722c75696e743235362076616c75652c75696e74323536206e6f6e63656020820152712c75696e7432353620646561646c696e652960701b604082015260520190565b7f454950373132446f6d61696e28737472696e67206e616d652c75696e7432353681527f20636861696e49642c6164647265737320766572696679696e67436f6e74726160208201526263742960e81b604082015260430190565b7f44656c65676174696f6e28616464726573732064656c6567617465652c75696e81527f74323536206e6f6e63652c75696e7432353620657870697279290000000000006020820152603a0190565b6001600160a01b0391909116815260200190565b6001600160a01b0392831681529116602082015260400190565b901515815260200190565b90815260200190565b9586526001600160a01b0394851660208701529290931660408501526060840152608083019190915260a082015260c00190565b9384526001600160a01b039290921660208401526040830152606082015260800190565b938452602084019290925260408301526001600160a01b0316606082015260800190565b93845260ff9290921660208401526040830152606082015260800190565b6000602080835283518082850152825b81811015611ba457858101830151858201604001528201611b88565b81811115611bb55783604083870101525b50601f01601f1916929092016040019392505050565b6020808252601f908201527f54726962653a206f6e6c7920746865206d696e7465722063616e206d696e7400604082015260600190565b6020808252602a908201527f54726962653a2063616e6e6f74207472616e7366657220746f20746865207a65604082015269726f206164647265737360b01b606082015260800190565b60208082526018908201527f54726962653a207369676e617475726520657870697265640000000000000000604082015260600190565b6020808252602c908201527f54726962653a2063616e6e6f74207472616e736665722066726f6d207468652060408201526b7a65726f206164647265737360a01b606082015260800190565b602080825260139082015272151c9a58994e881d5b985d5d1a1bdc9a5e9959606a1b604082015260600190565b60208082526018908201527f54726962653a20696e76616c6964207369676e61747572650000000000000000604082015260600190565b60208082526014908201527354726962653a20696e76616c6964206e6f6e636560601b604082015260600190565b60208082526034908201527f54726962653a206f6e6c7920746865206d696e7465722063616e206368616e676040820152736520746865206d696e746572206164647265737360601b606082015260800190565b60208082526019908201527f54726962653a206e6f74207965742064657465726d696e656400000000000000604082015260600190565b63ffffffff91909116815260200190565b63ffffffff9290921682526001600160601b0316602082015260400190565b60ff91909116815260200190565b6001600160601b0391909116815260200190565b6001600160601b0392831681529116602082015260400190565b6001600160a01b03811681146107b957600080fdfe54726962653a20626c6f636b206e756d6265722065786365656473203332206269747354726962653a20746f74616c537570706c792065786365656473203936206269747354726962653a207472616e7366657220616d6f756e742065786365656473207370656e64657220616c6c6f77616e636554726962653a207472616e7366657220616d6f756e7420657863656564732062616c616e636554726962653a20616d6f756e7420657863656564732039362062697473000000a26469706673582212204b5ab84c8ee5befcd5fba2745834ef385b0d07beb1f852bc25562eb10a137ac064736f6c63430006060033a2646970667358221220062ff29caa9fb83e030acb922feb057204cd2a5c38816a82f996dd0f7178683c64736f6c63430006060033
Deployed Bytecode Sourcemap
385:2677:0:-:0;;;;5:9:-1;2:2;;;27:1;24;17:12;2:2;385:2677:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;12:1:-1;9;2:12;4081:347:3;;;;;;;;;:::i;:::-;;3100:117;;;;;;;;;:::i;5781:130::-;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;1996:115;;;;;;;;;:::i;2387:441:0:-;;;:::i;4282:112:10:-;;;;;;;;;:::i;:::-;;;;;;;;561:66:3;;;:::i;1796:115::-;;;;;;;;;:::i;273:62::-;;;:::i;4644:223:10:-;;;;;;;;;:::i;5818:205::-;;;;;;;;;:::i;493:62:3:-;;;:::i;2474:121::-;;;;;;;;;:::i;4827:128::-;;;;;;;;;:::i;1552:159::-;;;;;;;;;:::i;1186:93:0:-;;;;;;;;;:::i;1577:200::-;;;;;;;;;:::i;5098:179:3:-;;;;;;;;;:::i;668:36:0:-;;;:::i;:::-;;;;;;;;3325:174:3;;;;;;;;;:::i;3965:136:10:-;;;;;;;;;:::i;2950:137::-;;;;;;;;;:::i;2686:123:3:-;;;;;;;;;:::i;770:45:0:-;;;:::i;491:24::-;;;:::i;1727:49:10:-;;;:::i;4564:128:3:-;;;;;;;;;:::i;3808:125::-;;;;;;;;;:::i;576:28:0:-;;;:::i;1376:97::-;;;;;;;;;:::i;2211:172:3:-;;;;;;;;;:::i;3255:125:10:-;;;;;;;;;:::i;2896:117:3:-;;;;;;;;;:::i;341:62::-;;;:::i;5101:226:10:-;;;;;;;;;:::i;409:78:3:-;;;:::i;822:271:0:-;;;:::i;5462:180:3:-;;;;;;;;;:::i;3592:123::-;;;;;;;;;:::i;1943:349:0:-;;;;;;;;;:::i;4081:347:3:-;1259:22;1270:10;1259;:22::i;:::-;1251:72;;;;-1:-1:-1;;;1251:72:3;;;;;;;;;;;;;;;;;531:24:::1;;;;;;;;;;;;;;4213:4;:19;;4205:76;;;;-1:-1:-1::0;;;4205:76:3::1;;;;;;;;;4391:30;::::0;-1:-1:-1;;;4391:30:3;;:4:::1;::::0;:15:::1;::::0;:30:::1;::::0;4407:4;;4413:7;;4391:30:::1;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24::::0;17:12:::1;2:2;4391:30:3;;;;8:9:-1;5:2;;;45:16;42:1;39::::0;24:38:::1;77:16;74:1;67:27;5:2;4391:30:3;;;;4081:347:::0;;:::o;3100:117::-;1108:22;1119:10;1108;:22::i;:::-;1087:106;;;;-1:-1:-1;;;1087:106:3;;;;;;;;;3179:31:::1;311:24;;;;;;;;;;;;;;3203:6;3179:10;:31::i;:::-;3100:117:::0;:::o;5781:130::-;5849:4;5872:32;601:26;;;;;;;;;;;;;;5895:8;5872:7;:32::i;:::-;5865:39;5781:130;-1:-1:-1;;5781:130:3:o;1996:115::-;1108:22;1119:10;1108;:22::i;:::-;1087:106;;;;-1:-1:-1;;;1087:106:3;;;;;;;;;2074:30:::1;311:24;;;;;;;;;;;;;;2097:6;2074:9;:30::i;2387:441:0:-:0;2469:24;;-1:-1:-1;;;2469:24:0;;;;2468:25;2447:108;;;;-1:-1:-1;;;2447:108:0;;;;;;;;;2600:12;;-1:-1:-1;;;;;2600:12:0;2586:10;:26;2565:106;;;;-1:-1:-1;;;2565:106:0;;;;;;;;;2682:24;:31;;-1:-1:-1;;;;2682:31:0;-1:-1:-1;;;2682:31:0;;;2783:38;;;;;;2805:15;;2783:38;;;;;;;;;;2387:441::o;4282:112:10:-;4339:7;4365:12;;;;;;;;;;:22;;;;4282:112::o;561:66:3:-;601:26;;;;;;;;;;;;;;561:66;:::o;1796:115::-;1108:22;1119:10;1108;:22::i;:::-;1087:106;;;;-1:-1:-1;;;1087:106:3;;;;;;;;;1874:30:::1;379:24;;;;;;273:62:::0;311:24;;;;;;4644:223:10;4735:6;:12;;;;;;;;;;:22;;;4727:45;;4759:12;:10;:12::i;4727:45::-;4719:105;;;;-1:-1:-1;;;4719:105:10;;;;;;;;;4835:25;4846:4;4852:7;4835:10;:25::i;:::-;4644:223;;:::o;5818:205::-;5915:12;:10;:12::i;:::-;-1:-1:-1;;;;;5904:23:10;:7;-1:-1:-1;;;;;5904:23:10;;5896:83;;;;-1:-1:-1;;;5896:83:10;;;;;;;;;5990:26;6002:4;6008:7;5990:11;:26::i;493:62:3:-;531:24;;;;;;2474:121;1108:22;1119:10;1108;:22::i;:::-;1087:106;;;;-1:-1:-1;;;1087:106:3;;;;;;;;;2556:32:::1;531:24;;;;;;4827:128:::0;4895:4;4918:30;311:24;;;;;;1552:159;1108:22;1119:10;1108;:22::i;:::-;1087:106;;;;-1:-1:-1;;;1087:106:3;;;;;;;;;1674:30:::1;1688:4;1694:9;1674:13;:30::i;1186:93:0:-:0;1108:22:3;1119:10;1108;:22::i;:::-;1087:106;;;;-1:-1:-1;;;1087:106:3;;;;;;;;;1258:14:0::1;1266:5;1258:7;:14::i;1577:200::-:0;1108:22:3;1119:10;1108;:22::i;:::-;1087:106;;;;-1:-1:-1;;;1087:106:3;;;;;;;;;1694:12:0::1;:28:::0;;-1:-1:-1;;;;;;1694:28:0::1;-1:-1:-1::0;;;;;1694:28:0;::::1;::::0;;::::1;::::0;;;1737:33:::1;::::0;::::1;::::0;-1:-1:-1;;1737:33:0::1;1577:200:::0;:::o;5098:179:3:-;5205:4;5232:38;455:32;;;;;;668:36:0;;;-1:-1:-1;;;;;668:36:0;;:::o;3325:174:3:-;1108:22;1119:10;1108;:22::i;:::-;1087:106;;;;-1:-1:-1;;;1087:106:3;;;;;;;;;3446:46:::1;455:32;;;;;;3965:136:10::0;4038:7;4064:12;;;;;;;;;;:30;;4088:5;4064:30;:23;:30;:::i;:::-;4057:37;3965:136;-1:-1:-1;;;3965:136:10:o;2950:137::-;3019:4;3042:12;;;;;;;;;;:38;;3072:7;3042:38;:29;:38;:::i;2686:123:3:-;1108:22;1119:10;1108;:22::i;:::-;1087:106;;;;-1:-1:-1;;;1087:106:3;;;;;;;;;2768:34:::1;601:26;;;;;;770:45:0::0;;;-1:-1:-1;;;770:45:0;;;;;:::o;491:24::-;;;;;;-1:-1:-1;;;;;491:24:0;;:::o;1727:49:10:-;1772:4;1727:49;:::o;4564:128:3:-;4632:4;4655:30;379:24;;;;;;3808:125;1108:22;1119:10;1108;:22::i;:::-;1087:106;;;;-1:-1:-1;;;1087:106:3;;;;;;;;;3891:35:::1;601:26;;;;;;576:28:0::0;;;-1:-1:-1;;;;;576:28:0;;:::o;1376:97::-;1108:22:3;1119:10;1108;:22::i;:::-;1087:106;;;;-1:-1:-1;;;1087:106:3;;;;;;;;;1450:16:0::1;1460:5;1450:9;:16::i;2211:172:3:-:0;1108:22;1119:10;1108;:22::i;:::-;1087:106;;;;-1:-1:-1;;;1087:106:3;;;;;;;;;2331:45:::1;455:32;;;;;;3255:125:10::0;3318:7;3344:12;;;;;;;;;;:29;;:27;:29::i;2896:117:3:-;1108:22;1119:10;1108;:22::i;:::-;1087:106;;;;-1:-1:-1;;;1087:106:3;;;;;;;;;2975:31:::1;379:24;;;;;;341:62:::0;379:24;;;;;;5101:226:10;5193:6;:12;;;;;;;;;;:22;;;5185:45;;5217:12;:10;:12::i;5185:45::-;5177:106;;;;-1:-1:-1;;;5177:106:10;;;;;;;;409:78:3;455:32;;;;;;822:271:0;1501:13:12;;;;;;;;:33;;;1518:16;:14;:16::i;:::-;1501:50;;;-1:-1:-1;1539:12:12;;;;1538:13;1501:50;1493:109;;;;-1:-1:-1;;;1493:109:12;;;;;;;;;1636:13;;;;;;;1635:14;1659:98;;;;1709:4;1693:20;;-1:-1:-1;;;;1693:20:12;;;;;1727:19;;;;;1659:98;878:26:0::1;893:10;878:14;:26::i;:::-;923:8;950:4;934:22;;;;;:::i;:::-;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;45:16;42:1;39::::0;24:38:::1;77:16;74:1;67:27;5:2;934:22:0;923:33;;966:22;982:4;966:7;:22::i;:::-;999:12;1032:4;1039:10;1014:36;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;8:9:-1;5:2;;;45:16;42:1;39::::0;24:38:::1;77:16;74:1;67:27;5:2;1014:36:0;999:51;;1060:26;1078:6;1060:9;:26::i;:::-;1767:1:12;;1783:14:::0;1779:66;;;1813:13;:21;;-1:-1:-1;;1813:21:12;;;822:271:0;:::o;5462:180:3:-;5578:4;5605:30;531:24;;;;;;3592:123;1108:22;1119:10;1108;:22::i;:::-;1087:106;;;;-1:-1:-1;;;1087:106:3;;;;;;;;;3675:33:::1;531:24;;;;;;1943:349:0::0;1108:22:3;1119:10;1108;:22::i;:::-;1087:106;;;;-1:-1:-1;;;1087:106:3;;;;;;;;;2079:5:0::1;::::0;2115:31:::1;::::0;-1:-1:-1;;;2115:31:0;;-1:-1:-1;;;;;2079:5:0;;::::1;::::0;2150:6;;2079:5;;2115:16:::1;::::0;:31:::1;::::0;2140:4:::1;::::0;2115:31:::1;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24::::0;17:12:::1;2:2;2115:31:0;;;;8:9:-1;5:2;;;45:16;42:1;39::::0;24:38:::1;77:16;74:1;67:27;5:2;2115:31:0;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;2115:31:0;;;;;;;;;:41;;2094:110;;;;-1:-1:-1::0;;;2094:110:0::1;;;;;;;;;2215:27;::::0;-1:-1:-1;;;2215:27:0;;-1:-1:-1;;;;;2215:15:0;::::1;::::0;::::1;::::0;:27:::1;::::0;2231:2;;2235:6;;2215:27:::1;;;;;;;;;;;;;;;;;5:9:-1;2:2;;;27:1;24::::0;17:12:::1;2:2;2215:27:0;;;;8:9:-1;5:2;;;45:16;42:1;39::::0;24:38:::1;77:16;74:1;67:27;5:2;2215:27:0;;;;;;;101:4:-1;97:9;90:4;84;80:15;76:31;69:5;65:43;126:6;120:4;113:20;0:138;2215:27:0;;;;;;;;;;2274:2;-1:-1:-1::0;;;;;2258:27:0::1;;2278:6;2258:27;;;;;;;;;;;;;;;1203:1:3;1943:349:0::0;;:::o;598:104:17:-;685:10;598:104;:::o;7025:184:10:-;7098:6;:12;;;;;;;;;;:33;;7123:7;7098:33;:24;:33;:::i;:::-;7094:109;;;7179:12;:10;:12::i;:::-;-1:-1:-1;;;;;7152:40:10;7170:7;-1:-1:-1;;;;;7152:40:10;7164:4;7152:40;;;;;;;;;;7025:184;;:::o;7215:188::-;7289:6;:12;;;;;;;;;;:36;;7317:7;7289:36;:27;:36;:::i;:::-;7285:112;;;7373:12;:10;:12::i;:::-;-1:-1:-1;;;;;7346:40:10;7364:7;-1:-1:-1;;;;;7346:40:10;7358:4;7346:40;;;;;;;;;;7215:188;;:::o;6823:196::-;6934:6;:12;;;;;;;;;;;:22;;;6911:57;;6958:9;;6941:4;;6911:57;;6934:6;6911:57;6978:6;:12;;;;;;;;;;;:22;;:34;6823:196::o;2834:106:0:-;2885:3;:17;;-1:-1:-1;;;;;;2885:17:0;;-1:-1:-1;;;;;2885:17:0;;;;;;;;;;;;2917:16;;;;-1:-1:-1;;2917:16:0;2834:106;:::o;7677:156:18:-;7751:7;7801:22;7805:3;7817:5;7801:3;:22::i;6984:165::-;7064:4;7087:55;7097:3;-1:-1:-1;;;;;7117:23:18;;7087:9;:55::i;2946:114:0:-;2999:5;:21;;-1:-1:-1;;;;;;2999:21:0;-1:-1:-1;;;;;2999:21:0;;;;;;;;3035:18;;;;-1:-1:-1;;3035:18:0;2946:114;:::o;7230:115:18:-;7293:7;7319:19;7327:3;7319:7;:19::i;1941:112:12:-;1989:4;2013:33;2040:4;2013:18;:33::i;:::-;2012:34;2005:41;;1941:112;:::o;5917:101:3:-;5978:33;531:24;;;;;;;;;;;;;;6002:8;5978:10;:33::i;6429:150:18:-;6499:4;6522:50;6527:3;-1:-1:-1;;;;;6547:23:18;;6522:4;:50::i;6747:156::-;6820:4;6843:53;6851:3;-1:-1:-1;;;;;6871:23:18;;6843:7;:53::i;4452:201::-;4546:18;;4519:7;;4546:26;-1:-1:-1;4538:73:18;;;;-1:-1:-1;;;4538:73:18;;;;;;;;;4628:3;:11;;4640:5;4628:18;;;;;;;;;;;;;;;;4621:25;;4452:201;;;;:::o;3805:127::-;3878:4;3901:19;;;:12;;;;;:19;;;;;;:24;;;3805:127::o;4013:107::-;4095:18;;4013:107::o;726:413:16:-;1086:20;1124:8;;;726:413::o;1640:404:18:-;1703:4;1724:21;1734:3;1739:5;1724:9;:21::i;:::-;1719:319;;-1:-1:-1;27:10;;39:1;23:18;;;45:23;;1761:11:18;:23;;;;;;;;;;;;;1941:18;;1919:19;;;:12;;;:19;;;;;;:40;;;;1973:11;;1719:319;-1:-1:-1;2022:5:18;2015:12;;2212:1512;2278:4;2415:19;;;:12;;;:19;;;;;;2449:15;;2445:1273;;2878:18;;-1:-1:-1;;2830:14:18;;;;2878:22;;;;2806:21;;2878:3;;:22;;3160;;;;;;;;;;;;;;3140:42;;3303:9;3274:3;:11;;3286:13;3274:26;;;;;;;;;;;;;;;;;;;:38;;;;3378:23;;;3420:1;3378:12;;;:23;;;;;;3404:17;;;3378:43;;3527:17;;3378:3;;3527:17;;;;;;;;;;;;;;;;;;;;;;3619:3;:12;;:19;3632:5;3619:19;;;;;;;;;;;3612:26;;;3660:4;3653:11;;;;;;;;2445:1273;3702:5;3695:12;;;;;385:2677:0;;;;;;;;:::o;:::-;;;;;;;;:::o;5:130:-1:-;72:20;;-1:-1;;;;;19625:54;;20778:35;;20768:2;;20827:1;;20817:12;692:241;;796:2;784:9;775:7;771:23;767:32;764:2;;;-1:-1;;802:12;764:2;864:53;909:7;885:22;864:53;;940:366;;;1061:2;1049:9;1040:7;1036:23;1032:32;1029:2;;;-1:-1;;1067:12;1029:2;1129:53;1174:7;1150:22;1129:53;;;1119:63;1219:2;1258:22;;;;481:20;;-1:-1;;;1023:283;1313:257;;1425:2;1413:9;1404:7;1400:23;1396:32;1393:2;;;-1:-1;;1431:12;1393:2;223:6;217:13;20924:5;19458:13;19451:21;20902:5;20899:32;20889:2;;-1:-1;;20935:12;1577:241;;1681:2;1669:9;1660:7;1656:23;1652:32;1649:2;;;-1:-1;;1687:12;1649:2;-1:-1;344:20;;1643:175;-1:-1;1643:175;1825:366;;;1946:2;1934:9;1925:7;1921:23;1917:32;1914:2;;;-1:-1;;1952:12;1914:2;344:20;;;-1:-1;2104:2;2143:22;;72:20;-1:-1;;;;;19625:54;;20778:35;;20768:2;;-1:-1;;20817:12;20768:2;2112:63;;;;1908:283;;;;;;2198:366;;;2319:2;2307:9;2298:7;2294:23;2290:32;2287:2;;;-1:-1;;2325:12;2287:2;-1:-1;;344:20;;;2477:2;2516:22;;;344:20;;-1:-1;2281:283;2944:263;;3059:2;3047:9;3038:7;3034:23;3030:32;3027:2;;;-1:-1;;3065:12;3027:2;-1:-1;629:13;;3021:186;-1:-1;3021:186;10146:372;-1:-1;;;5076:42;;5060:2;5137:12;;10326:192;10525:372;-1:-1;;;6164:34;;6148:2;6217:12;;10705:192;10904:372;-1:-1;;;6520:36;;6504:2;6575:12;;11084:192;11283:372;-1:-1;;;8425:34;;8409:2;8478:12;;11463:192;11662:372;-1:-1;;;8781:34;;8765:2;8834:12;;11842:192;12041:213;-1:-1;;;;;19625:54;;;;3434:37;;12159:2;12144:18;;12130:124;12261:340;-1:-1;;;;;19625:54;;;3434:37;;19625:54;;12587:2;12572:18;;3293:58;12415:2;12400:18;;12386:215;12608:324;-1:-1;;;;;19625:54;;;;3434:37;;12918:2;12903:18;;3665:37;12754:2;12739:18;;12725:207;12939:201;19458:13;;19451:21;3548:34;;13051:2;13036:18;;13022:118;13147:213;3665:37;;;13265:2;13250:18;;13236:124;13367:324;3665:37;;;-1:-1;;;;;19625:54;13677:2;13662:18;;3434:37;13513:2;13498:18;;13484:207;14194:407;14385:2;14399:47;;;4261:2;14370:18;;;19072:19;4297:34;19112:14;;;4277:55;-1:-1;;;4352:12;;;4345:26;4390:12;;;14356:245;14608:407;14799:2;14813:47;;;4641:2;14784:18;;;19072:19;4677:34;19112:14;;;4657:55;-1:-1;;;4732:12;;;4725:29;4773:12;;;14770:245;15022:407;15213:2;15227:47;;;5388:2;15198:18;;;19072:19;5424:34;19112:14;;;5404:55;-1:-1;;;5479:12;;;5472:39;5530:12;;;15184:245;15436:407;15627:2;15641:47;;;5781:2;15612:18;;;19072:19;-1:-1;;;19112:14;;;5797:45;5861:12;;;15598:245;15850:407;16041:2;16055:47;;;6826:2;16026:18;;;19072:19;6862:34;19112:14;;;6842:55;-1:-1;;;6917:12;;;6910:25;6954:12;;;16012:245;16264:407;16455:2;16469:47;;;7205:2;16440:18;;;19072:19;7241:34;19112:14;;;7221:55;-1:-1;;;7296:12;;;7289:28;7336:12;;;16426:245;16678:407;16869:2;16883:47;;;7587:2;16854:18;;;19072:19;7623:34;19112:14;;;7603:55;-1:-1;;;7678:12;;;7671:40;7730:12;;;16840:245;17092:407;17283:2;17297:47;;;7981:2;17268:18;;;19072:19;8017:34;19112:14;;;7997:55;-1:-1;;;8072:12;;;8065:38;8122:12;;;17254:245;17506:407;17697:2;17711:47;;;9085:2;17682:18;;;19072:19;9121:34;19112:14;;;9101:55;-1:-1;;;9176:12;;;9169:29;9217:12;;;17668:245;17920:407;18111:2;18125:47;;;9468:2;18096:18;;;19072:19;9504:34;19112:14;;;9484:55;-1:-1;;;9559:12;;;9552:36;9607:12;;;18082:245;18334:407;18525:2;18539:47;;;9858:2;18510:18;;;19072:19;9894:34;19112:14;;;9874:55;-1:-1;;;9949:12;;;9942:39;10000:12;;;18496:245
Swarm Source
ipfs://062ff29caa9fb83e030acb922feb057204cd2a5c38816a82f996dd0f7178683c
Loading...
Loading
Loading...
Loading
OVERVIEW
The deployer address for Fei Protocol's contract.Net Worth in USD
$243,484,984.50
Net Worth in ETH
123,415.729407
Token Allocations
TRIBE
100.00%
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|---|---|---|---|---|
| ETH | 100.00% | $0.460328 | 528,937,887.0262 | $243,484,984.5 |
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.