Source Code
Latest 1 from a total of 1 transactions
| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Withdraw | 17994637 | 926 days ago | IN | 0 ETH | 0.00059679 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
ERC20Handler
Compiler Version
v0.8.17+commit.8df45f5f
Contract Source Code (Solidity)
/**
*Submitted for verification at Etherscan.io on 2023-07-12
*/
// File: contracts/interfaces/IDepositExecute.sol
pragma solidity 0.8.17;
/**
@title Interface for handler contracts that support deposits and deposit executions.
@author ChainSafe Systems.
*/
interface IDepositExecute {
/**
@notice It is intended that deposit are made using the Bridge contract.
@param resourceID ID of the resource that is being bridged.
@param destinationChainID Chain ID deposit is expected to be bridged to.
@param depositNonce This value is generated as an ID by the Bridge contract.
@param depositer Address of account making the deposit in the Bridge contract.
@param data Consists of additional data needed for a specific deposit.
*/
function deposit(bytes32 resourceID, uint8 destinationChainID, uint64 depositNonce, address depositer, bytes calldata data) external payable;
/**
@notice It is intended that proposals are executed by the Bridge contract.
@param resourceID ID of the resource that is being bridged.
@param data Consists of additional data needed for a specific deposit execution.
*/
function executeProposal(bytes32 resourceID, bytes calldata data) external;
}
// File: contracts/interfaces/IERCHandler.sol
pragma solidity 0.8.17;
/**
@title Interface to be used with handlers that support ERC20s and ERC721s.
@author ChainSafe Systems.
*/
interface IERCHandler {
/**
@notice Correlates {resourceID} with {contractAddress}.
@param resourceID ResourceID to be used when making deposits.
@param contractAddress Address of contract to be called when a deposit is made and a deposited is executed.
*/
function setResource(bytes32 resourceID, address contractAddress) external;
/**
@notice Marks {contractAddress} as mintable/burnable.
@param contractAddress Address of contract to be used when making or executing deposits.
*/
function setBurnable(address contractAddress) external;
/**
@notice Used to manually release funds {native tokens} from Native safes.
@param recipient Address to release tokens to.
@param amount The amount of native token to release.
*/
function withdraw(address recipient, uint256 amount) external;
/**
@notice Used to manually release funds {erc20 tokens, nft} from ERC safes.
@param tokenAddress Address of token contract to release
@param recipient Address to release tokens to.
@param amountOrTokenID Either the amount of ERC20 tokens or the ERC721 token ID to release.
*/
function withdrawToken(address tokenAddress, address recipient, uint256 amountOrTokenID) external;
}
// File: contracts/handlers/HandlerHelpers.sol
pragma solidity 0.8.17;
/**
@title Function used across handler contracts.
@author ChainSafe Systems.
@notice This contract is intended to be used with the Bridge contract.
*/
contract HandlerHelpers is IERCHandler {
address public _bridgeAddress;
// resourceID => token contract address
mapping (bytes32 => address) public _resourceIDToTokenContractAddress;
// token contract address => resourceID
mapping (address => bytes32) public _tokenContractAddressToResourceID;
// token contract address => is whitelisted
mapping (address => bool) public _contractWhitelist;
// token contract address => is burnable
mapping (address => bool) public _burnList;
modifier onlyBridge() {
_onlyBridge();
_;
}
function _onlyBridge() private {
require(msg.sender == _bridgeAddress, "sender must be bridge contract");
}
/**
@notice First verifies {_resourceIDToContractAddress}[{resourceID}] and
{_contractAddressToResourceID}[{contractAddress}] are not already set,
then sets {_resourceIDToContractAddress} with {contractAddress},
{_contractAddressToResourceID} with {resourceID},
and {_contractWhitelist} to true for {contractAddress}.
@param resourceID ResourceID to be used when making deposits.
@param contractAddress Address of contract to be called when a deposit is made and a deposited is executed.
*/
function setResource(bytes32 resourceID, address contractAddress) external override onlyBridge {
_setResource(resourceID, contractAddress);
}
/**
@notice First verifies {contractAddress} is whitelisted, then sets {_burnList}[{contractAddress}]
to true.
@param contractAddress Address of contract to be used when making or executing deposits.
*/
function setBurnable(address contractAddress) external override onlyBridge{
_setBurnable(contractAddress);
}
/**
@notice Used to manually release funds(native token) from Native safes.
@param recipient Address to release tokens to.
@param amount The amount of native token to release.
*/
function withdraw(address recipient, uint256 amount) external virtual override {}
/**
@notice Used to manually release funds(ERC20 & ERC721) from ERC safes.
@param tokenAddress Address of token contract to release.
@param recipient Address to release tokens to.
@param amountOrTokenID Either the amount of ERC20 tokens or the ERC721 token ID to release.
*/
function withdrawToken(address tokenAddress, address recipient, uint256 amountOrTokenID) external virtual override {}
function _setResource(bytes32 resourceID, address contractAddress) internal {
_resourceIDToTokenContractAddress[resourceID] = contractAddress;
_tokenContractAddressToResourceID[contractAddress] = resourceID;
_contractWhitelist[contractAddress] = true;
}
function _setBurnable(address contractAddress) internal {
require(_contractWhitelist[contractAddress], "provided contract is not whitelisted");
_burnList[contractAddress] = true;
}
}
// File: @openzeppelin/contracts/token/ERC20/IERC20.sol
// OpenZeppelin Contracts (last updated v4.6.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `to`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address to, uint256 amount) external returns (bool);
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `from` to `to` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address from,
address to,
uint256 amount
) external returns (bool);
}
// File: @openzeppelin/contracts/token/ERC20/extensions/IERC20Metadata.sol
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface for the optional metadata functions from the ERC20 standard.
*
* _Available since v4.1._
*/
interface IERC20Metadata is IERC20 {
/**
* @dev Returns the name of the token.
*/
function name() external view returns (string memory);
/**
* @dev Returns the symbol of the token.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the decimals places of the token.
*/
function decimals() external view returns (uint8);
}
// File: @openzeppelin/contracts/utils/Context.sol
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
pragma solidity ^0.8.0;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}
// File: @openzeppelin/contracts/token/ERC20/ERC20.sol
// OpenZeppelin Contracts (last updated v4.8.0) (token/ERC20/ERC20.sol)
pragma solidity ^0.8.0;
/**
* @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.openzeppelin.com/t/how-to-implement-erc20-supply-mechanisms/226[How
* to implement supply mechanisms].
*
* We have followed general OpenZeppelin Contracts guidelines: functions revert
* instead returning `false` on failure. This behavior is nonetheless
* conventional and does not conflict with the expectations of ERC20
* applications.
*
* Additionally, an {Approval} event is emitted on calls to {transferFrom}.
* This allows applications to reconstruct the allowance for all accounts just
* by listening to said events. Other implementations of the EIP may not emit
* these events, as it isn't required by the specification.
*
* Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
* functions have been added to mitigate the well-known issues around setting
* allowances. See {IERC20-approve}.
*/
contract ERC20 is Context, IERC20, IERC20Metadata {
mapping(address => uint256) private _balances;
mapping(address => mapping(address => uint256)) private _allowances;
uint256 private _totalSupply;
string private _name;
string private _symbol;
/**
* @dev Sets the values for {name} and {symbol}.
*
* The default value of {decimals} is 18. To select a different value for
* {decimals} you should overload it.
*
* All two of these values are immutable: they can only be set once during
* construction.
*/
constructor(string memory name_, string memory symbol_) {
_name = name_;
_symbol = symbol_;
}
/**
* @dev Returns the name of the token.
*/
function name() public view virtual override returns (string memory) {
return _name;
}
/**
* @dev Returns the symbol of the token, usually a shorter version of the
* name.
*/
function symbol() public view virtual override returns (string memory) {
return _symbol;
}
/**
* @dev Returns the number of decimals used to get its user representation.
* For example, if `decimals` equals `2`, a balance of `505` tokens should
* be displayed to a user as `5.05` (`505 / 10 ** 2`).
*
* Tokens usually opt for a value of 18, imitating the relationship between
* Ether and Wei. This is the value {ERC20} uses, unless this function is
* overridden;
*
* NOTE: This information is only used for _display_ purposes: it in
* no way affects any of the arithmetic of the contract, including
* {IERC20-balanceOf} and {IERC20-transfer}.
*/
function decimals() public view virtual override returns (uint8) {
return 18;
}
/**
* @dev See {IERC20-totalSupply}.
*/
function totalSupply() public view virtual override returns (uint256) {
return _totalSupply;
}
/**
* @dev See {IERC20-balanceOf}.
*/
function balanceOf(address account) public view virtual override returns (uint256) {
return _balances[account];
}
/**
* @dev See {IERC20-transfer}.
*
* Requirements:
*
* - `to` cannot be the zero address.
* - the caller must have a balance of at least `amount`.
*/
function transfer(address to, uint256 amount) public virtual override returns (bool) {
address owner = _msgSender();
_transfer(owner, to, 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}.
*
* NOTE: If `amount` is the maximum `uint256`, the allowance is not updated on
* `transferFrom`. This is semantically equivalent to an infinite approval.
*
* Requirements:
*
* - `spender` cannot be the zero address.
*/
function approve(address spender, uint256 amount) public virtual override returns (bool) {
address owner = _msgSender();
_approve(owner, 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}.
*
* NOTE: Does not update the allowance if the current allowance
* is the maximum `uint256`.
*
* Requirements:
*
* - `from` and `to` cannot be the zero address.
* - `from` must have a balance of at least `amount`.
* - the caller must have allowance for ``from``'s tokens of at least
* `amount`.
*/
function transferFrom(
address from,
address to,
uint256 amount
) public virtual override returns (bool) {
address spender = _msgSender();
_spendAllowance(from, spender, amount);
_transfer(from, to, amount);
return true;
}
/**
* @dev Atomically increases the allowance granted to `spender` by the caller.
*
* This is an alternative to {approve} that can be used as a mitigation for
* problems described in {IERC20-approve}.
*
* Emits an {Approval} event indicating the updated allowance.
*
* Requirements:
*
* - `spender` cannot be the zero address.
*/
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
address owner = _msgSender();
_approve(owner, spender, allowance(owner, spender) + addedValue);
return true;
}
/**
* @dev Atomically decreases the allowance granted to `spender` by the caller.
*
* This is an alternative to {approve} that can be used as a mitigation for
* problems described in {IERC20-approve}.
*
* Emits an {Approval} event indicating the updated allowance.
*
* Requirements:
*
* - `spender` cannot be the zero address.
* - `spender` must have allowance for the caller of at least
* `subtractedValue`.
*/
function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
address owner = _msgSender();
uint256 currentAllowance = allowance(owner, spender);
require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
unchecked {
_approve(owner, spender, currentAllowance - subtractedValue);
}
return true;
}
/**
* @dev Moves `amount` of tokens from `from` to `to`.
*
* This internal function is equivalent to {transfer}, and can be used to
* e.g. implement automatic token fees, slashing mechanisms, etc.
*
* Emits a {Transfer} event.
*
* Requirements:
*
* - `from` cannot be the zero address.
* - `to` cannot be the zero address.
* - `from` must have a balance of at least `amount`.
*/
function _transfer(
address from,
address to,
uint256 amount
) internal virtual {
require(from != address(0), "ERC20: transfer from the zero address");
require(to != address(0), "ERC20: transfer to the zero address");
_beforeTokenTransfer(from, to, amount);
uint256 fromBalance = _balances[from];
require(fromBalance >= amount, "ERC20: transfer amount exceeds balance");
unchecked {
_balances[from] = fromBalance - amount;
// Overflow not possible: the sum of all balances is capped by totalSupply, and the sum is preserved by
// decrementing then incrementing.
_balances[to] += amount;
}
emit Transfer(from, to, amount);
_afterTokenTransfer(from, to, amount);
}
/** @dev Creates `amount` tokens and assigns them to `account`, increasing
* the total supply.
*
* Emits a {Transfer} event with `from` set to the zero address.
*
* Requirements:
*
* - `account` cannot be the zero address.
*/
function _mint(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: mint to the zero address");
_beforeTokenTransfer(address(0), account, amount);
_totalSupply += amount;
unchecked {
// Overflow not possible: balance + amount is at most totalSupply + amount, which is checked above.
_balances[account] += amount;
}
emit Transfer(address(0), account, amount);
_afterTokenTransfer(address(0), account, amount);
}
/**
* @dev Destroys `amount` tokens from `account`, reducing the
* total supply.
*
* Emits a {Transfer} event with `to` set to the zero address.
*
* Requirements:
*
* - `account` cannot be the zero address.
* - `account` must have at least `amount` tokens.
*/
function _burn(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: burn from the zero address");
_beforeTokenTransfer(account, address(0), amount);
uint256 accountBalance = _balances[account];
require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
unchecked {
_balances[account] = accountBalance - amount;
// Overflow not possible: amount <= accountBalance <= totalSupply.
_totalSupply -= amount;
}
emit Transfer(account, address(0), amount);
_afterTokenTransfer(account, address(0), amount);
}
/**
* @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
*
* This internal function is equivalent to `approve`, and can be used to
* e.g. set automatic allowances for certain subsystems, etc.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `owner` cannot be the zero address.
* - `spender` cannot be the zero address.
*/
function _approve(
address owner,
address spender,
uint256 amount
) internal virtual {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
/**
* @dev Updates `owner` s allowance for `spender` based on spent `amount`.
*
* Does not update the allowance amount in case of infinite allowance.
* Revert if not enough allowance is available.
*
* Might emit an {Approval} event.
*/
function _spendAllowance(
address owner,
address spender,
uint256 amount
) internal virtual {
uint256 currentAllowance = allowance(owner, spender);
if (currentAllowance != type(uint256).max) {
require(currentAllowance >= amount, "ERC20: insufficient allowance");
unchecked {
_approve(owner, spender, currentAllowance - amount);
}
}
}
/**
* @dev Hook that is called before any transfer of tokens. This includes
* minting and burning.
*
* Calling conditions:
*
* - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
* will be transferred to `to`.
* - when `from` is zero, `amount` tokens will be minted for `to`.
* - when `to` is zero, `amount` of ``from``'s tokens will be burned.
* - `from` and `to` are never both zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _beforeTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual {}
/**
* @dev Hook that is called after any transfer of tokens. This includes
* minting and burning.
*
* Calling conditions:
*
* - when `from` and `to` are both non-zero, `amount` of ``from``'s tokens
* has been transferred to `to`.
* - when `from` is zero, `amount` tokens have been minted for `to`.
* - when `to` is zero, `amount` of ``from``'s tokens have been burned.
* - `from` and `to` are never both zero.
*
* To learn more about hooks, head to xref:ROOT:extending-contracts.adoc#using-hooks[Using Hooks].
*/
function _afterTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual {}
}
// File: @openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol
// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Burnable.sol)
pragma solidity ^0.8.0;
/**
* @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 {
/**
* @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 {
_spendAllowance(account, _msgSender(), amount);
_burn(account, amount);
}
}
// File: @openzeppelin/contracts/security/Pausable.sol
// OpenZeppelin Contracts (last updated v4.7.0) (security/Pausable.sol)
pragma solidity ^0.8.0;
/**
* @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() {
_paused = false;
}
/**
* @dev Modifier to make a function callable only when the contract is not paused.
*
* Requirements:
*
* - The contract must not be paused.
*/
modifier whenNotPaused() {
_requireNotPaused();
_;
}
/**
* @dev Modifier to make a function callable only when the contract is paused.
*
* Requirements:
*
* - The contract must be paused.
*/
modifier whenPaused() {
_requirePaused();
_;
}
/**
* @dev Returns true if the contract is paused, and false otherwise.
*/
function paused() public view virtual returns (bool) {
return _paused;
}
/**
* @dev Throws if the contract is paused.
*/
function _requireNotPaused() internal view virtual {
require(!paused(), "Pausable: paused");
}
/**
* @dev Throws if the contract is not paused.
*/
function _requirePaused() internal view virtual {
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());
}
}
// File: @openzeppelin/contracts/token/ERC20/extensions/ERC20Pausable.sol
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/ERC20Pausable.sol)
pragma solidity ^0.8.0;
/**
* @dev ERC20 token with pausable token transfers, minting and burning.
*
* Useful for scenarios such as preventing trades until the end of an evaluation
* period, or having an emergency switch for freezing all token transfers in the
* event of a large bug.
*/
abstract contract ERC20Pausable is ERC20, Pausable {
/**
* @dev See {ERC20-_beforeTokenTransfer}.
*
* Requirements:
*
* - the contract must not be paused.
*/
function _beforeTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual override {
super._beforeTokenTransfer(from, to, amount);
require(!paused(), "ERC20Pausable: token transfer while paused");
}
}
// File: @openzeppelin/contracts/access/IAccessControl.sol
// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)
pragma solidity ^0.8.0;
/**
* @dev External interface of AccessControl declared to support ERC165 detection.
*/
interface IAccessControl {
/**
* @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
*
* `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
* {RoleAdminChanged} not being emitted signaling this.
*
* _Available since v3.1._
*/
event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);
/**
* @dev Emitted when `account` is granted `role`.
*
* `sender` is the account that originated the contract call, an admin role
* bearer except when using {AccessControl-_setupRole}.
*/
event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Emitted when `account` is revoked `role`.
*
* `sender` is the account that originated the contract call:
* - if using `revokeRole`, it is the admin role bearer
* - if using `renounceRole`, it is the role bearer (i.e. `account`)
*/
event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) external view returns (bool);
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {AccessControl-_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) external view returns (bytes32);
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function grantRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from `account`.
*
* If `account` had been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function revokeRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from the calling account.
*
* Roles are often managed via {grantRole} and {revokeRole}: this function's
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* If the calling account had been granted `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `account`.
*/
function renounceRole(bytes32 role, address account) external;
}
// File: @openzeppelin/contracts/access/IAccessControlEnumerable.sol
// OpenZeppelin Contracts v4.4.1 (access/IAccessControlEnumerable.sol)
pragma solidity ^0.8.0;
/**
* @dev External interface of AccessControlEnumerable declared to support ERC165 detection.
*/
interface IAccessControlEnumerable is IAccessControl {
/**
* @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) external view returns (address);
/**
* @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) external view returns (uint256);
}
// File: @openzeppelin/contracts/utils/math/Math.sol
// OpenZeppelin Contracts (last updated v4.8.0) (utils/math/Math.sol)
pragma solidity ^0.8.0;
/**
* @dev Standard math utilities missing in the Solidity language.
*/
library Math {
enum Rounding {
Down, // Toward negative infinity
Up, // Toward infinity
Zero // Toward zero
}
/**
* @dev Returns the largest of two numbers.
*/
function max(uint256 a, uint256 b) internal pure returns (uint256) {
return a > b ? a : b;
}
/**
* @dev Returns the smallest of two numbers.
*/
function min(uint256 a, uint256 b) internal pure returns (uint256) {
return a < b ? a : b;
}
/**
* @dev Returns the average of two numbers. The result is rounded towards
* zero.
*/
function average(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b) / 2 can overflow.
return (a & b) + (a ^ b) / 2;
}
/**
* @dev Returns the ceiling of the division of two numbers.
*
* This differs from standard division with `/` in that it rounds up instead
* of rounding down.
*/
function ceilDiv(uint256 a, uint256 b) internal pure returns (uint256) {
// (a + b - 1) / b can overflow on addition, so we distribute.
return a == 0 ? 0 : (a - 1) / b + 1;
}
/**
* @notice Calculates floor(x * y / denominator) with full precision. Throws if result overflows a uint256 or denominator == 0
* @dev Original credit to Remco Bloemen under MIT license (https://xn--2-umb.com/21/muldiv)
* with further edits by Uniswap Labs also under MIT license.
*/
function mulDiv(
uint256 x,
uint256 y,
uint256 denominator
) internal pure returns (uint256 result) {
unchecked {
// 512-bit multiply [prod1 prod0] = x * y. Compute the product mod 2^256 and mod 2^256 - 1, then use
// use the Chinese Remainder Theorem to reconstruct the 512 bit result. The result is stored in two 256
// variables such that product = prod1 * 2^256 + prod0.
uint256 prod0; // Least significant 256 bits of the product
uint256 prod1; // Most significant 256 bits of the product
assembly {
let mm := mulmod(x, y, not(0))
prod0 := mul(x, y)
prod1 := sub(sub(mm, prod0), lt(mm, prod0))
}
// Handle non-overflow cases, 256 by 256 division.
if (prod1 == 0) {
return prod0 / denominator;
}
// Make sure the result is less than 2^256. Also prevents denominator == 0.
require(denominator > prod1);
///////////////////////////////////////////////
// 512 by 256 division.
///////////////////////////////////////////////
// Make division exact by subtracting the remainder from [prod1 prod0].
uint256 remainder;
assembly {
// Compute remainder using mulmod.
remainder := mulmod(x, y, denominator)
// Subtract 256 bit number from 512 bit number.
prod1 := sub(prod1, gt(remainder, prod0))
prod0 := sub(prod0, remainder)
}
// Factor powers of two out of denominator and compute largest power of two divisor of denominator. Always >= 1.
// See https://cs.stackexchange.com/q/138556/92363.
// Does not overflow because the denominator cannot be zero at this stage in the function.
uint256 twos = denominator & (~denominator + 1);
assembly {
// Divide denominator by twos.
denominator := div(denominator, twos)
// Divide [prod1 prod0] by twos.
prod0 := div(prod0, twos)
// Flip twos such that it is 2^256 / twos. If twos is zero, then it becomes one.
twos := add(div(sub(0, twos), twos), 1)
}
// Shift in bits from prod1 into prod0.
prod0 |= prod1 * twos;
// Invert denominator mod 2^256. Now that denominator is an odd number, it has an inverse modulo 2^256 such
// that denominator * inv = 1 mod 2^256. Compute the inverse by starting with a seed that is correct for
// four bits. That is, denominator * inv = 1 mod 2^4.
uint256 inverse = (3 * denominator) ^ 2;
// Use the Newton-Raphson iteration to improve the precision. Thanks to Hensel's lifting lemma, this also works
// in modular arithmetic, doubling the correct bits in each step.
inverse *= 2 - denominator * inverse; // inverse mod 2^8
inverse *= 2 - denominator * inverse; // inverse mod 2^16
inverse *= 2 - denominator * inverse; // inverse mod 2^32
inverse *= 2 - denominator * inverse; // inverse mod 2^64
inverse *= 2 - denominator * inverse; // inverse mod 2^128
inverse *= 2 - denominator * inverse; // inverse mod 2^256
// Because the division is now exact we can divide by multiplying with the modular inverse of denominator.
// This will give us the correct result modulo 2^256. Since the preconditions guarantee that the outcome is
// less than 2^256, this is the final result. We don't need to compute the high bits of the result and prod1
// is no longer required.
result = prod0 * inverse;
return result;
}
}
/**
* @notice Calculates x * y / denominator with full precision, following the selected rounding direction.
*/
function mulDiv(
uint256 x,
uint256 y,
uint256 denominator,
Rounding rounding
) internal pure returns (uint256) {
uint256 result = mulDiv(x, y, denominator);
if (rounding == Rounding.Up && mulmod(x, y, denominator) > 0) {
result += 1;
}
return result;
}
/**
* @dev Returns the square root of a number. If the number is not a perfect square, the value is rounded down.
*
* Inspired by Henry S. Warren, Jr.'s "Hacker's Delight" (Chapter 11).
*/
function sqrt(uint256 a) internal pure returns (uint256) {
if (a == 0) {
return 0;
}
// For our first guess, we get the biggest power of 2 which is smaller than the square root of the target.
//
// We know that the "msb" (most significant bit) of our target number `a` is a power of 2 such that we have
// `msb(a) <= a < 2*msb(a)`. This value can be written `msb(a)=2**k` with `k=log2(a)`.
//
// This can be rewritten `2**log2(a) <= a < 2**(log2(a) + 1)`
// → `sqrt(2**k) <= sqrt(a) < sqrt(2**(k+1))`
// → `2**(k/2) <= sqrt(a) < 2**((k+1)/2) <= 2**(k/2 + 1)`
//
// Consequently, `2**(log2(a) / 2)` is a good first approximation of `sqrt(a)` with at least 1 correct bit.
uint256 result = 1 << (log2(a) >> 1);
// At this point `result` is an estimation with one bit of precision. We know the true value is a uint128,
// since it is the square root of a uint256. Newton's method converges quadratically (precision doubles at
// every iteration). We thus need at most 7 iteration to turn our partial result with one bit of precision
// into the expected uint128 result.
unchecked {
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
result = (result + a / result) >> 1;
return min(result, a / result);
}
}
/**
* @notice Calculates sqrt(a), following the selected rounding direction.
*/
function sqrt(uint256 a, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = sqrt(a);
return result + (rounding == Rounding.Up && result * result < a ? 1 : 0);
}
}
/**
* @dev Return the log in base 2, rounded down, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 128;
}
if (value >> 64 > 0) {
value >>= 64;
result += 64;
}
if (value >> 32 > 0) {
value >>= 32;
result += 32;
}
if (value >> 16 > 0) {
value >>= 16;
result += 16;
}
if (value >> 8 > 0) {
value >>= 8;
result += 8;
}
if (value >> 4 > 0) {
value >>= 4;
result += 4;
}
if (value >> 2 > 0) {
value >>= 2;
result += 2;
}
if (value >> 1 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 2, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log2(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log2(value);
return result + (rounding == Rounding.Up && 1 << result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 10, rounded down, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >= 10**64) {
value /= 10**64;
result += 64;
}
if (value >= 10**32) {
value /= 10**32;
result += 32;
}
if (value >= 10**16) {
value /= 10**16;
result += 16;
}
if (value >= 10**8) {
value /= 10**8;
result += 8;
}
if (value >= 10**4) {
value /= 10**4;
result += 4;
}
if (value >= 10**2) {
value /= 10**2;
result += 2;
}
if (value >= 10**1) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log10(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log10(value);
return result + (rounding == Rounding.Up && 10**result < value ? 1 : 0);
}
}
/**
* @dev Return the log in base 256, rounded down, of a positive value.
* Returns 0 if given 0.
*
* Adding one to the result gives the number of pairs of hex symbols needed to represent `value` as a hex string.
*/
function log256(uint256 value) internal pure returns (uint256) {
uint256 result = 0;
unchecked {
if (value >> 128 > 0) {
value >>= 128;
result += 16;
}
if (value >> 64 > 0) {
value >>= 64;
result += 8;
}
if (value >> 32 > 0) {
value >>= 32;
result += 4;
}
if (value >> 16 > 0) {
value >>= 16;
result += 2;
}
if (value >> 8 > 0) {
result += 1;
}
}
return result;
}
/**
* @dev Return the log in base 10, following the selected rounding direction, of a positive value.
* Returns 0 if given 0.
*/
function log256(uint256 value, Rounding rounding) internal pure returns (uint256) {
unchecked {
uint256 result = log256(value);
return result + (rounding == Rounding.Up && 1 << (result * 8) < value ? 1 : 0);
}
}
}
// File: @openzeppelin/contracts/utils/Strings.sol
// OpenZeppelin Contracts (last updated v4.8.0) (utils/Strings.sol)
pragma solidity ^0.8.0;
/**
* @dev String operations.
*/
library Strings {
bytes16 private constant _SYMBOLS = "0123456789abcdef";
uint8 private constant _ADDRESS_LENGTH = 20;
/**
* @dev Converts a `uint256` to its ASCII `string` decimal representation.
*/
function toString(uint256 value) internal pure returns (string memory) {
unchecked {
uint256 length = Math.log10(value) + 1;
string memory buffer = new string(length);
uint256 ptr;
/// @solidity memory-safe-assembly
assembly {
ptr := add(buffer, add(32, length))
}
while (true) {
ptr--;
/// @solidity memory-safe-assembly
assembly {
mstore8(ptr, byte(mod(value, 10), _SYMBOLS))
}
value /= 10;
if (value == 0) break;
}
return buffer;
}
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
*/
function toHexString(uint256 value) internal pure returns (string memory) {
unchecked {
return toHexString(value, Math.log256(value) + 1);
}
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation with fixed length.
*/
function toHexString(uint256 value, uint256 length) internal pure returns (string memory) {
bytes memory buffer = new bytes(2 * length + 2);
buffer[0] = "0";
buffer[1] = "x";
for (uint256 i = 2 * length + 1; i > 1; --i) {
buffer[i] = _SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
/**
* @dev Converts an `address` with fixed length of 20 bytes to its not checksummed ASCII `string` hexadecimal representation.
*/
function toHexString(address addr) internal pure returns (string memory) {
return toHexString(uint256(uint160(addr)), _ADDRESS_LENGTH);
}
}
// File: @openzeppelin/contracts/utils/introspection/IERC165.sol
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}
// File: @openzeppelin/contracts/utils/introspection/ERC165.sol
// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)
pragma solidity ^0.8.0;
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
* for the additional interface id that will be supported. For example:
*
* ```solidity
* function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
* return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
* }
* ```
*
* Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
*/
abstract contract ERC165 is IERC165 {
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}
// File: @openzeppelin/contracts/access/AccessControl.sol
// OpenZeppelin Contracts (last updated v4.8.0) (access/AccessControl.sol)
pragma solidity ^0.8.0;
/**
* @dev Contract module that allows children to implement role-based access
* control mechanisms. This is a lightweight version that doesn't allow enumerating role
* members except through off-chain means by accessing the contract event logs. Some
* applications may benefit from on-chain enumerability, for those cases see
* {AccessControlEnumerable}.
*
* Roles are referred to by their `bytes32` identifier. These should be exposed
* in the external API and be unique. The best way to achieve this is by
* using `public constant` hash digests:
*
* ```
* 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, IAccessControl, ERC165 {
struct RoleData {
mapping(address => bool) members;
bytes32 adminRole;
}
mapping(bytes32 => RoleData) private _roles;
bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;
/**
* @dev Modifier that checks that an account has a specific role. Reverts
* with a standardized message including the required role.
*
* The format of the revert reason is given by the following regular expression:
*
* /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
*
* _Available since v4.1._
*/
modifier onlyRole(bytes32 role) {
_checkRole(role);
_;
}
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IAccessControl).interfaceId || super.supportsInterface(interfaceId);
}
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) public view virtual override returns (bool) {
return _roles[role].members[account];
}
/**
* @dev Revert with a standard message if `_msgSender()` is missing `role`.
* Overriding this function changes the behavior of the {onlyRole} modifier.
*
* Format of the revert message is described in {_checkRole}.
*
* _Available since v4.6._
*/
function _checkRole(bytes32 role) internal view virtual {
_checkRole(role, _msgSender());
}
/**
* @dev Revert with a standard message if `account` is missing `role`.
*
* The format of the revert reason is given by the following regular expression:
*
* /^AccessControl: account (0x[0-9a-f]{40}) is missing role (0x[0-9a-f]{64})$/
*/
function _checkRole(bytes32 role, address account) internal view virtual {
if (!hasRole(role, account)) {
revert(
string(
abi.encodePacked(
"AccessControl: account ",
Strings.toHexString(account),
" is missing role ",
Strings.toHexString(uint256(role), 32)
)
)
);
}
}
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) public view virtual override returns (bytes32) {
return _roles[role].adminRole;
}
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*
* May emit a {RoleGranted} event.
*/
function grantRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
_grantRole(role, account);
}
/**
* @dev Revokes `role` from `account`.
*
* If `account` had been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*
* May emit a {RoleRevoked} event.
*/
function revokeRole(bytes32 role, address account) public virtual override onlyRole(getRoleAdmin(role)) {
_revokeRole(role, account);
}
/**
* @dev Revokes `role` from the calling account.
*
* Roles are often managed via {grantRole} and {revokeRole}: this function's
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* If the calling account had been revoked `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `account`.
*
* May emit a {RoleRevoked} event.
*/
function renounceRole(bytes32 role, address account) public virtual override {
require(account == _msgSender(), "AccessControl: can only renounce roles for self");
_revokeRole(role, account);
}
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event. Note that unlike {grantRole}, this function doesn't perform any
* checks on the calling account.
*
* May emit a {RoleGranted} event.
*
* [WARNING]
* ====
* This function should only be called from the constructor when setting
* up the initial roles for the system.
*
* Using this function in any other way is effectively circumventing the admin
* system imposed by {AccessControl}.
* ====
*
* NOTE: This function is deprecated in favor of {_grantRole}.
*/
function _setupRole(bytes32 role, address account) internal virtual {
_grantRole(role, account);
}
/**
* @dev Sets `adminRole` as ``role``'s admin role.
*
* Emits a {RoleAdminChanged} event.
*/
function _setRoleAdmin(bytes32 role, bytes32 adminRole) internal virtual {
bytes32 previousAdminRole = getRoleAdmin(role);
_roles[role].adminRole = adminRole;
emit RoleAdminChanged(role, previousAdminRole, adminRole);
}
/**
* @dev Grants `role` to `account`.
*
* Internal function without access restriction.
*
* May emit a {RoleGranted} event.
*/
function _grantRole(bytes32 role, address account) internal virtual {
if (!hasRole(role, account)) {
_roles[role].members[account] = true;
emit RoleGranted(role, account, _msgSender());
}
}
/**
* @dev Revokes `role` from `account`.
*
* Internal function without access restriction.
*
* May emit a {RoleRevoked} event.
*/
function _revokeRole(bytes32 role, address account) internal virtual {
if (hasRole(role, account)) {
_roles[role].members[account] = false;
emit RoleRevoked(role, account, _msgSender());
}
}
}
// File: @openzeppelin/contracts/utils/structs/EnumerableSet.sol
// OpenZeppelin Contracts (last updated v4.8.0) (utils/structs/EnumerableSet.sol)
// This file was procedurally generated from scripts/generate/templates/EnumerableSet.js.
pragma solidity ^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.
*
* [WARNING]
* ====
* Trying to delete such a structure from storage will likely result in data corruption, rendering the structure
* unusable.
* See https://github.com/ethereum/solidity/pull/11843[ethereum/solidity#11843] for more info.
*
* In order to clean an EnumerableSet, you can either remove all elements one by one or create a fresh instance using an
* array of EnumerableSet.
* ====
*/
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;
if (lastIndex != toDeleteIndex) {
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] = valueIndex; // Replace lastValue's index to valueIndex
}
// 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) {
return set._values[index];
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function _values(Set storage set) private view returns (bytes32[] memory) {
return set._values;
}
// 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);
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(Bytes32Set storage set) internal view returns (bytes32[] memory) {
bytes32[] memory store = _values(set._inner);
bytes32[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
// 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))));
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(AddressSet storage set) internal view returns (address[] memory) {
bytes32[] memory store = _values(set._inner);
address[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
// 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 in 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));
}
/**
* @dev Return the entire set in an array
*
* WARNING: This operation will copy the entire storage to memory, which can be quite expensive. This is designed
* to mostly be used by view accessors that are queried without any gas fees. Developers should keep in mind that
* this function has an unbounded cost, and using it as part of a state-changing function may render the function
* uncallable if the set grows to a point where copying to memory consumes too much gas to fit in a block.
*/
function values(UintSet storage set) internal view returns (uint256[] memory) {
bytes32[] memory store = _values(set._inner);
uint256[] memory result;
/// @solidity memory-safe-assembly
assembly {
result := store
}
return result;
}
}
// File: @openzeppelin/contracts/access/AccessControlEnumerable.sol
// OpenZeppelin Contracts (last updated v4.5.0) (access/AccessControlEnumerable.sol)
pragma solidity ^0.8.0;
/**
* @dev Extension of {AccessControl} that allows enumerating the members of each role.
*/
abstract contract AccessControlEnumerable is IAccessControlEnumerable, AccessControl {
using EnumerableSet for EnumerableSet.AddressSet;
mapping(bytes32 => EnumerableSet.AddressSet) private _roleMembers;
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IAccessControlEnumerable).interfaceId || super.supportsInterface(interfaceId);
}
/**
* @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 virtual override returns (address) {
return _roleMembers[role].at(index);
}
/**
* @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 virtual override returns (uint256) {
return _roleMembers[role].length();
}
/**
* @dev Overload {_grantRole} to track enumerable memberships
*/
function _grantRole(bytes32 role, address account) internal virtual override {
super._grantRole(role, account);
_roleMembers[role].add(account);
}
/**
* @dev Overload {_revokeRole} to track enumerable memberships
*/
function _revokeRole(bytes32 role, address account) internal virtual override {
super._revokeRole(role, account);
_roleMembers[role].remove(account);
}
}
// File: @openzeppelin/contracts/token/ERC20/presets/ERC20PresetMinterPauser.sol
// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/presets/ERC20PresetMinterPauser.sol)
pragma solidity ^0.8.0;
/**
* @dev {ERC20} token, including:
*
* - ability for holders to burn (destroy) their tokens
* - a minter role that allows for token minting (creation)
* - a pauser role that allows to stop all token transfers
*
* This contract uses {AccessControl} to lock permissioned functions using the
* different roles - head to its documentation for details.
*
* The account that deploys the contract will be granted the minter and pauser
* roles, as well as the default admin role, which will let it grant both minter
* and pauser roles to other accounts.
*
* _Deprecated in favor of https://wizard.openzeppelin.com/[Contracts Wizard]._
*/
contract ERC20PresetMinterPauser is Context, AccessControlEnumerable, ERC20Burnable, ERC20Pausable {
bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE");
bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE");
/**
* @dev Grants `DEFAULT_ADMIN_ROLE`, `MINTER_ROLE` and `PAUSER_ROLE` to the
* account that deploys the contract.
*
* See {ERC20-constructor}.
*/
constructor(string memory name, string memory symbol) ERC20(name, symbol) {
_setupRole(DEFAULT_ADMIN_ROLE, _msgSender());
_setupRole(MINTER_ROLE, _msgSender());
_setupRole(PAUSER_ROLE, _msgSender());
}
/**
* @dev Creates `amount` new tokens for `to`.
*
* See {ERC20-_mint}.
*
* Requirements:
*
* - the caller must have the `MINTER_ROLE`.
*/
function mint(address to, uint256 amount) public virtual {
require(hasRole(MINTER_ROLE, _msgSender()), "ERC20PresetMinterPauser: must have minter role to mint");
_mint(to, amount);
}
/**
* @dev Pauses all token transfers.
*
* See {ERC20Pausable} and {Pausable-_pause}.
*
* Requirements:
*
* - the caller must have the `PAUSER_ROLE`.
*/
function pause() public virtual {
require(hasRole(PAUSER_ROLE, _msgSender()), "ERC20PresetMinterPauser: must have pauser role to pause");
_pause();
}
/**
* @dev Unpauses all token transfers.
*
* See {ERC20Pausable} and {Pausable-_unpause}.
*
* Requirements:
*
* - the caller must have the `PAUSER_ROLE`.
*/
function unpause() public virtual {
require(hasRole(PAUSER_ROLE, _msgSender()), "ERC20PresetMinterPauser: must have pauser role to unpause");
_unpause();
}
function _beforeTokenTransfer(
address from,
address to,
uint256 amount
) internal virtual override(ERC20, ERC20Pausable) {
super._beforeTokenTransfer(from, to, amount);
}
}
// File: contracts/ERC20Safe.sol
pragma solidity 0.8.17;
/**
@title Manages deposited ERC20s.
@author ChainSafe Systems.
@notice This contract is intended to be used with ERC20Handler contract.
*/
contract ERC20Safe {
/**
@notice Used to transfer tokens into the safe to fund proposals.
@param tokenAddress Address of ERC20 to transfer.
@param owner Address of current token owner.
@param amount Amount of tokens to transfer.
*/
function fundERC20(address tokenAddress, address owner, uint256 amount) public {
IERC20 erc20 = IERC20(tokenAddress);
_safeTransferFrom(erc20, owner, address(this), amount);
}
/**
@notice Used to gain custody of deposited token.
@param tokenAddress Address of ERC20 to transfer.
@param owner Address of current token owner.
@param recipient Address to transfer tokens to.
@param amount Amount of tokens to transfer.
*/
function lockERC20(address tokenAddress, address owner, address recipient, uint256 amount) internal {
IERC20 erc20 = IERC20(tokenAddress);
_safeTransferFrom(erc20, owner, recipient, amount);
}
/**
@notice Transfers custody of token to recipient.
@param tokenAddress Address of ERC20 to transfer.
@param recipient Address to transfer tokens to.
@param amount Amount of tokens to transfer.
*/
function releaseERC20(address tokenAddress, address recipient, uint256 amount) internal {
IERC20 erc20 = IERC20(tokenAddress);
_safeTransfer(erc20, recipient, amount);
}
/**
@notice Used to create new ERC20s.
@param tokenAddress Address of ERC20 to transfer.
@param recipient Address to mint token to.
@param amount Amount of token to mint.
*/
function mintERC20(address tokenAddress, address recipient, uint256 amount) internal {
ERC20PresetMinterPauser erc20 = ERC20PresetMinterPauser(tokenAddress);
erc20.mint(recipient, amount);
}
/**
@notice Used to burn ERC20s.
@param tokenAddress Address of ERC20 to burn.
@param owner Current owner of tokens.
@param amount Amount of tokens to burn.
*/
function burnERC20(address tokenAddress, address owner, uint256 amount) internal {
ERC20Burnable erc20 = ERC20Burnable(tokenAddress);
erc20.burnFrom(owner, amount);
}
/**
@notice used to transfer ERC20s safely
@param token Token instance to transfer
@param to Address to transfer token to
@param value Amount of token to transfer
*/
function _safeTransfer(IERC20 token, address to, uint256 value) private {
_safeCall(token, abi.encodeWithSelector(token.transfer.selector, to, value));
}
/**
@notice used to transfer ERC20s safely
@param token Token instance to transfer
@param from Address to transfer token from
@param to Address to transfer token to
@param value Amount of token to transfer
*/
function _safeTransferFrom(IERC20 token, address from, address to, uint256 value) private {
_safeCall(token, abi.encodeWithSelector(token.transferFrom.selector, from, to, value));
}
/**
@notice used to make calls to ERC20s safely
@param token Token instance call targets
@param data encoded call data
*/
function _safeCall(IERC20 token, bytes memory data) private {
(bool success, bytes memory returndata) = address(token).call(data);
require(success, "ERC20: call failed");
if (returndata.length != 0) {
require(abi.decode(returndata, (bool)), "ERC20: operation did not succeed");
}
}
}
// File: contracts/handlers/ERC20Handler.sol
pragma solidity 0.8.17;
/**
@title Handles ERC20 deposits and deposit executions.
@author ChainSafe Systems.
@notice This contract is intended to be used with the Bridge contract.
*/
contract ERC20Handler is IDepositExecute, HandlerHelpers, ERC20Safe {
struct DepositRecord {
address _tokenAddress;
uint8 _lenDestinationRecipientAddress;
uint8 _destinationChainID;
bytes32 _resourceID;
bytes _destinationRecipientAddress;
address _depositer;
uint _amount;
}
// depositNonce => Deposit Record
mapping (uint8 => mapping(uint64 => DepositRecord)) public _depositRecords;
/**
@param bridgeAddress Contract address of previously deployed Bridge.
@param initialResourceIDs Resource IDs are used to identify a specific contract address.
These are the Resource IDs this contract will initially support.
@param initialContractAddresses These are the addresses the {initialResourceIDs} will point to, and are the contracts that will be
called to perform various deposit calls.
@param burnableContractAddresses These addresses will be set as burnable and when {deposit} is called, the deposited token will be burned.
When {executeProposal} is called, new tokens will be minted.
@dev {initialResourceIDs} and {initialContractAddresses} must have the same length (one resourceID for every address).
Also, these arrays must be ordered in the way that {initialResourceIDs}[0] is the intended resourceID for {initialContractAddresses}[0].
*/
constructor(
address bridgeAddress,
bytes32[] memory initialResourceIDs,
address[] memory initialContractAddresses,
address[] memory burnableContractAddresses
) {
require(initialResourceIDs.length == initialContractAddresses.length,
"initialResourceIDs and initialContractAddresses len mismatch");
_bridgeAddress = bridgeAddress;
for (uint256 i = 0; i < initialResourceIDs.length; i++) {
_setResource(initialResourceIDs[i], initialContractAddresses[i]);
}
for (uint256 i = 0; i < burnableContractAddresses.length; i++) {
_setBurnable(burnableContractAddresses[i]);
}
}
/**
@param depositNonce This ID will have been generated by the Bridge contract.
@param destId ID of chain deposit will be bridged to.
@return DepositRecord which consists of:
- _tokenAddress Address used when {deposit} was executed.
- _destinationChainID ChainID deposited tokens are intended to end up on.
- _resourceID ResourceID used when {deposit} was executed.
- _lenDestinationRecipientAddress Used to parse recipient's address from {_destinationRecipientAddress}
- _destinationRecipientAddress Address tokens are intended to be deposited to on desitnation chain.
- _depositer Address that initially called {deposit} in the Bridge contract.
- _amount Amount of tokens that were deposited.
*/
function getDepositRecord(uint64 depositNonce, uint8 destId) external view returns (DepositRecord memory) {
return _depositRecords[destId][depositNonce];
}
/**
@notice A deposit is initiatied by making a deposit in the Bridge contract.
@param resourceID ID of the resource that is being bridged.
@param destinationChainID Chain ID of chain tokens are expected to be bridged to.
@param depositNonce This value is generated as an ID by the Bridge contract.
@param depositer Address of account making the deposit in the Bridge contract.
@param data Consists of: {resourceID}, {amount}, {lenRecipientAddress}, and {recipientAddress}
all padded to 32 bytes.
@notice Data passed into the function should be constructed as follows:
amount uint256 bytes 0 - 32
recipientAddress length uint256 bytes 32 - 64
recipientAddress bytes bytes 64 - END
@dev Depending if the corresponding {tokenAddress} for the parsed {resourceID} is
marked true in {_burnList}, deposited tokens will be burned, if not, they will be locked.
*/
function deposit(
bytes32 resourceID,
uint8 destinationChainID,
uint64 depositNonce,
address depositer,
bytes calldata data
) external override payable onlyBridge {
bytes memory recipientAddress;
uint256 amount;
uint256 lenRecipientAddress;
assembly {
amount := calldataload(0xC4)
recipientAddress := mload(0x40)
lenRecipientAddress := calldataload(0xE4)
mstore(0x40, add(0x20, add(recipientAddress, lenRecipientAddress)))
calldatacopy(
recipientAddress, // copy to destinationRecipientAddress
0xE4, // copy from calldata @ 0x104
sub(calldatasize(), 0xE) // copy size (calldatasize - 0x104)
)
}
address tokenAddress = _resourceIDToTokenContractAddress[resourceID];
require(_contractWhitelist[tokenAddress], "provided tokenAddress is not whitelisted");
if (_burnList[tokenAddress]) {
burnERC20(tokenAddress, depositer, amount);
} else {
lockERC20(tokenAddress, depositer, address(this), amount);
}
_depositRecords[destinationChainID][depositNonce] = DepositRecord(
tokenAddress,
uint8(lenRecipientAddress),
destinationChainID,
resourceID,
recipientAddress,
depositer,
amount
);
if (msg.value != 0) {
depositer.call{value: msg.value}("");
}
}
/**
@notice Proposal execution should be initiated when a proposal is finalized in the Bridge contract.
by a relayer on the deposit's destination chain.
@param resourceID ID of the resource that is being bridged.
@param data Consists of {resourceID}, {amount}, {lenDestinationRecipientAddress},
and {destinationRecipientAddress} all padded to 32 bytes.
@notice Data passed into the function should be constructed as follows:
amount uint256 bytes 0 - 32
destinationRecipientAddress length uint256 bytes 32 - 64
destinationRecipientAddress bytes bytes 64 - END
*/
function executeProposal(bytes32 resourceID, bytes calldata data) external override onlyBridge {
uint256 amount;
bytes memory destinationRecipientAddress;
assembly {
amount := calldataload(0x64)
destinationRecipientAddress := mload(0x40)
let lenDestinationRecipientAddress := calldataload(0x84)
mstore(0x40, add(0x20, add(destinationRecipientAddress, lenDestinationRecipientAddress)))
// in the calldata the destinationRecipientAddress is stored at 0xC4 after accounting for the function signature and length declaration
calldatacopy(
destinationRecipientAddress, // copy to destinationRecipientAddress
0x84, // copy from calldata @ 0x84
sub(calldatasize(), 0x84) // copy size to the end of calldata
)
}
bytes20 recipientAddress;
address tokenAddress = _resourceIDToTokenContractAddress[resourceID];
assembly {
recipientAddress := mload(add(destinationRecipientAddress, 0x20))
}
require(_contractWhitelist[tokenAddress], "provided tokenAddress is not whitelisted");
if (_burnList[tokenAddress]) {
mintERC20(tokenAddress, address(recipientAddress), amount);
} else {
releaseERC20(tokenAddress, address(recipientAddress), amount);
}
}
/**
@notice Used to manually release ERC20 tokens from ERC20Safe.
@param tokenAddress Address of token contract to release.
@param recipient Address to release tokens to.
@param amount The amount of ERC20 tokens to release.
*/
function withdrawToken(address tokenAddress, address recipient, uint amount) external override onlyBridge {
releaseERC20(tokenAddress, recipient, amount);
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"bridgeAddress","type":"address"},{"internalType":"bytes32[]","name":"initialResourceIDs","type":"bytes32[]"},{"internalType":"address[]","name":"initialContractAddresses","type":"address[]"},{"internalType":"address[]","name":"burnableContractAddresses","type":"address[]"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"_bridgeAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"_burnList","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"_contractWhitelist","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint8","name":"","type":"uint8"},{"internalType":"uint64","name":"","type":"uint64"}],"name":"_depositRecords","outputs":[{"internalType":"address","name":"_tokenAddress","type":"address"},{"internalType":"uint8","name":"_lenDestinationRecipientAddress","type":"uint8"},{"internalType":"uint8","name":"_destinationChainID","type":"uint8"},{"internalType":"bytes32","name":"_resourceID","type":"bytes32"},{"internalType":"bytes","name":"_destinationRecipientAddress","type":"bytes"},{"internalType":"address","name":"_depositer","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"name":"_resourceIDToTokenContractAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"_tokenContractAddressToResourceID","outputs":[{"internalType":"bytes32","name":"","type":"bytes32"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"resourceID","type":"bytes32"},{"internalType":"uint8","name":"destinationChainID","type":"uint8"},{"internalType":"uint64","name":"depositNonce","type":"uint64"},{"internalType":"address","name":"depositer","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"deposit","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"resourceID","type":"bytes32"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"executeProposal","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"address","name":"owner","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"fundERC20","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint64","name":"depositNonce","type":"uint64"},{"internalType":"uint8","name":"destId","type":"uint8"}],"name":"getDepositRecord","outputs":[{"components":[{"internalType":"address","name":"_tokenAddress","type":"address"},{"internalType":"uint8","name":"_lenDestinationRecipientAddress","type":"uint8"},{"internalType":"uint8","name":"_destinationChainID","type":"uint8"},{"internalType":"bytes32","name":"_resourceID","type":"bytes32"},{"internalType":"bytes","name":"_destinationRecipientAddress","type":"bytes"},{"internalType":"address","name":"_depositer","type":"address"},{"internalType":"uint256","name":"_amount","type":"uint256"}],"internalType":"struct ERC20Handler.DepositRecord","name":"","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"contractAddress","type":"address"}],"name":"setBurnable","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"resourceID","type":"bytes32"},{"internalType":"address","name":"contractAddress","type":"address"}],"name":"setResource","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"tokenAddress","type":"address"},{"internalType":"address","name":"recipient","type":"address"},{"internalType":"uint256","name":"amount","type":"uint256"}],"name":"withdrawToken","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
60806040523480156200001157600080fd5b5060405162002a4938038062002a49833981810160405281019062000037919062000665565b81518351146200007e576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016200007590620007bb565b60405180910390fd5b836000806101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060005b83518110156200012d5762000117848281518110620000e557620000e4620007dd565b5b6020026020010151848381518110620001035762000102620007dd565b5b60200260200101516200018a60201b60201c565b8080620001249062000845565b915050620000c1565b5060005b81518110156200017f5762000169828281518110620001555762000154620007dd565b5b60200260200101516200027c60201b60201c565b8080620001769062000845565b91505062000131565b50505050506200092a565b806001600084815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555081600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506001600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055505050565b600360008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff166200030b576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401620003029062000908565b60405180910390fd5b6001600460008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff02191690831515021790555050565b6000604051905090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b6000620003a7826200037a565b9050919050565b620003b9816200039a565b8114620003c557600080fd5b50565b600081519050620003d981620003ae565b92915050565b600080fd5b6000601f19601f8301169050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b6200042f82620003e4565b810181811067ffffffffffffffff82111715620004515762000450620003f5565b5b80604052505050565b60006200046662000366565b905062000474828262000424565b919050565b600067ffffffffffffffff821115620004975762000496620003f5565b5b602082029050602081019050919050565b600080fd5b6000819050919050565b620004c281620004ad565b8114620004ce57600080fd5b50565b600081519050620004e281620004b7565b92915050565b6000620004ff620004f98462000479565b6200045a565b90508083825260208201905060208402830185811115620005255762000524620004a8565b5b835b818110156200055257806200053d8882620004d1565b84526020840193505060208101905062000527565b5050509392505050565b600082601f830112620005745762000573620003df565b5b815162000586848260208601620004e8565b91505092915050565b600067ffffffffffffffff821115620005ad57620005ac620003f5565b5b602082029050602081019050919050565b6000620005d5620005cf846200058f565b6200045a565b90508083825260208201905060208402830185811115620005fb57620005fa620004a8565b5b835b81811015620006285780620006138882620003c8565b845260208401935050602081019050620005fd565b5050509392505050565b600082601f8301126200064a5762000649620003df565b5b81516200065c848260208601620005be565b91505092915050565b6000806000806080858703121562000682576200068162000370565b5b60006200069287828801620003c8565b945050602085015167ffffffffffffffff811115620006b657620006b562000375565b5b620006c4878288016200055c565b935050604085015167ffffffffffffffff811115620006e857620006e762000375565b5b620006f68782880162000632565b925050606085015167ffffffffffffffff8111156200071a576200071962000375565b5b620007288782880162000632565b91505092959194509250565b600082825260208201905092915050565b7f696e697469616c5265736f7572636549447320616e6420696e697469616c436f60008201527f6e7472616374416464726573736573206c656e206d69736d6174636800000000602082015250565b6000620007a3603c8362000734565b9150620007b08262000745565b604082019050919050565b60006020820190508181036000830152620007d68162000794565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052603260045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052601160045260246000fd5b6000819050919050565b600062000852826200083b565b91507fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82036200088757620008866200080c565b5b600182019050919050565b7f70726f766964656420636f6e7472616374206973206e6f742077686974656c6960008201527f7374656400000000000000000000000000000000000000000000000000000000602082015250565b6000620008f060248362000734565b9150620008fd8262000892565b604082019050919050565b600060208201905081810360008301526200092381620008e1565b9050919050565b61210f806200093a6000396000f3fe6080604052600436106100dd5760003560e01c80637f79bea81161007f578063ba484c0911610059578063ba484c09146102c7578063c8ba6c8714610304578063e248cff214610341578063f3fef3a31461036a576100dd565b80637f79bea81461023857806395601f0914610275578063b8fa37361461029e576100dd565b8063318c136e116100bb578063318c136e1461017157806338995da91461019c5780634402027f146101b85780636a70d081146101fb576100dd565b806301e33667146100e257806307b7ed991461010b5780630a6d55d814610134575b600080fd5b3480156100ee57600080fd5b506101096004803603810190610104919061135f565b610393565b005b34801561011757600080fd5b50610132600480360381019061012d91906113b2565b6103ab565b005b34801561014057600080fd5b5061015b60048036038101906101569190611415565b6103bf565b6040516101689190611451565b60405180910390f35b34801561017d57600080fd5b506101866103f2565b6040516101939190611451565b60405180910390f35b6101b660048036038101906101b1919061154a565b610416565b005b3480156101c457600080fd5b506101df60048036038101906101da91906115e4565b610794565b6040516101f297969594939291906116e1565b60405180910390f35b34801561020757600080fd5b50610222600480360381019061021d91906113b2565b6108c5565b60405161022f9190611772565b60405180910390f35b34801561024457600080fd5b5061025f600480360381019061025a91906113b2565b6108e5565b60405161026c9190611772565b60405180910390f35b34801561028157600080fd5b5061029c6004803603810190610297919061135f565b610905565b005b3480156102aa57600080fd5b506102c560048036038101906102c0919061178d565b61091c565b005b3480156102d357600080fd5b506102ee60048036038101906102e991906117cd565b610932565b6040516102fb919061192f565b60405180910390f35b34801561031057600080fd5b5061032b600480360381019061032691906113b2565b610b17565b6040516103389190611951565b60405180910390f35b34801561034d57600080fd5b506103686004803603810190610363919061196c565b610b2f565b005b34801561037657600080fd5b50610391600480360381019061038c91906119cc565b610ca3565b005b61039b610ca7565b6103a6838383610d37565b505050565b6103b3610ca7565b6103bc81610d4d565b50565b60016020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b61041e610ca7565b606060008060c4359150604051925060e4359050808301602001604052600e360360e484376000600160008b815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600360008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16610507576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104fe90611a8f565b60405180910390fd5b600460008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161561056957610564818885610e34565b610576565b61057581883086610eac565b5b6040518060e001604052808273ffffffffffffffffffffffffffffffffffffffff1681526020018360ff1681526020018a60ff1681526020018b81526020018581526020018873ffffffffffffffffffffffffffffffffffffffff16815260200184815250600560008b60ff1660ff16815260200190815260200160002060008a67ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160000160146101000a81548160ff021916908360ff16021790555060408201518160000160156101000a81548160ff021916908360ff1602179055506060820151816001015560808201518160020190816106c19190611cea565b5060a08201518160030160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060c0820151816004015590505060003414610788578673ffffffffffffffffffffffffffffffffffffffff163460405161074290611ded565b60006040518083038185875af1925050503d806000811461077f576040519150601f19603f3d011682016040523d82523d6000602084013e610784565b606091505b5050505b50505050505050505050565b6005602052816000526040600020602052806000526040600020600091509150508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060000160149054906101000a900460ff16908060000160159054906101000a900460ff169080600101549080600201805461081690611b0d565b80601f016020809104026020016040519081016040528092919081815260200182805461084290611b0d565b801561088f5780601f106108645761010080835404028352916020019161088f565b820191906000526020600020905b81548152906001019060200180831161087257829003601f168201915b5050505050908060030160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060040154905087565b60046020528060005260406000206000915054906101000a900460ff1681565b60036020528060005260406000206000915054906101000a900460ff1681565b600083905061091681843085610ec4565b50505050565b610924610ca7565b61092e8282610f4d565b5050565b61093a61124f565b600560008360ff1660ff16815260200190815260200160002060008467ffffffffffffffff1667ffffffffffffffff1681526020019081526020016000206040518060e00160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016000820160149054906101000a900460ff1660ff1660ff1681526020016000820160159054906101000a900460ff1660ff1660ff16815260200160018201548152602001600282018054610a2d90611b0d565b80601f0160208091040260200160405190810160405280929190818152602001828054610a5990611b0d565b8015610aa65780601f10610a7b57610100808354040283529160200191610aa6565b820191906000526020600020905b815481529060010190602001808311610a8957829003601f168201915b505050505081526020016003820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600482015481525050905092915050565b60026020528060005260406000206000915090505481565b610b37610ca7565b60006060606435915060405190506084358082016020016040526084360360848337506000806001600088815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905060208301519150600360008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16610c26576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c1d90611a8f565b60405180910390fd5b600460008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615610c8b57610c86818360601c8661103f565b610c9a565b610c99818360601c86610d37565b5b50505050505050565b5050565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610d35576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d2c90611e4e565b60405180910390fd5b565b6000839050610d478184846110b7565b50505050565b600360008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16610dd9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dd090611ee0565b60405180910390fd5b6001600460008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff02191690831515021790555050565b60008390508073ffffffffffffffffffffffffffffffffffffffff166379cc679084846040518363ffffffff1660e01b8152600401610e74929190611f00565b600060405180830381600087803b158015610e8e57600080fd5b505af1158015610ea2573d6000803e3d6000fd5b5050505050505050565b6000849050610ebd81858585610ec4565b5050505050565b610f47846323b872dd60e01b858585604051602401610ee593929190611f29565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505061113d565b50505050565b806001600084815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555081600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506001600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055505050565b60008390508073ffffffffffffffffffffffffffffffffffffffff166340c10f1984846040518363ffffffff1660e01b815260040161107f929190611f00565b600060405180830381600087803b15801561109957600080fd5b505af11580156110ad573d6000803e3d6000fd5b5050505050505050565b6111388363a9059cbb60e01b84846040516024016110d6929190611f00565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505061113d565b505050565b6000808373ffffffffffffffffffffffffffffffffffffffff16836040516111659190611f91565b6000604051808303816000865af19150503d80600081146111a2576040519150601f19603f3d011682016040523d82523d6000602084013e6111a7565b606091505b5091509150816111ec576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111e390611ff4565b60405180910390fd5b600081511461124957808060200190518101906112099190612040565b611248576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161123f906120b9565b60405180910390fd5b5b50505050565b6040518060e00160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600060ff168152602001600060ff1681526020016000801916815260200160608152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600081525090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006112f6826112cb565b9050919050565b611306816112eb565b811461131157600080fd5b50565b600081359050611323816112fd565b92915050565b6000819050919050565b61133c81611329565b811461134757600080fd5b50565b60008135905061135981611333565b92915050565b600080600060608486031215611378576113776112c1565b5b600061138686828701611314565b935050602061139786828701611314565b92505060406113a88682870161134a565b9150509250925092565b6000602082840312156113c8576113c76112c1565b5b60006113d684828501611314565b91505092915050565b6000819050919050565b6113f2816113df565b81146113fd57600080fd5b50565b60008135905061140f816113e9565b92915050565b60006020828403121561142b5761142a6112c1565b5b600061143984828501611400565b91505092915050565b61144b816112eb565b82525050565b60006020820190506114666000830184611442565b92915050565b600060ff82169050919050565b6114828161146c565b811461148d57600080fd5b50565b60008135905061149f81611479565b92915050565b600067ffffffffffffffff82169050919050565b6114c2816114a5565b81146114cd57600080fd5b50565b6000813590506114df816114b9565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f84011261150a576115096114e5565b5b8235905067ffffffffffffffff811115611527576115266114ea565b5b602083019150836001820283011115611543576115426114ef565b5b9250929050565b60008060008060008060a08789031215611567576115666112c1565b5b600061157589828a01611400565b965050602061158689828a01611490565b955050604061159789828a016114d0565b94505060606115a889828a01611314565b935050608087013567ffffffffffffffff8111156115c9576115c86112c6565b5b6115d589828a016114f4565b92509250509295509295509295565b600080604083850312156115fb576115fa6112c1565b5b600061160985828601611490565b925050602061161a858286016114d0565b9150509250929050565b61162d8161146c565b82525050565b61163c816113df565b82525050565b600081519050919050565b600082825260208201905092915050565b60005b8381101561167c578082015181840152602081019050611661565b60008484015250505050565b6000601f19601f8301169050919050565b60006116a482611642565b6116ae818561164d565b93506116be81856020860161165e565b6116c781611688565b840191505092915050565b6116db81611329565b82525050565b600060e0820190506116f6600083018a611442565b6117036020830189611624565b6117106040830188611624565b61171d6060830187611633565b818103608083015261172f8186611699565b905061173e60a0830185611442565b61174b60c08301846116d2565b98975050505050505050565b60008115159050919050565b61176c81611757565b82525050565b60006020820190506117876000830184611763565b92915050565b600080604083850312156117a4576117a36112c1565b5b60006117b285828601611400565b92505060206117c385828601611314565b9150509250929050565b600080604083850312156117e4576117e36112c1565b5b60006117f2858286016114d0565b925050602061180385828601611490565b9150509250929050565b611816816112eb565b82525050565b6118258161146c565b82525050565b611834816113df565b82525050565b600082825260208201905092915050565b600061185682611642565b611860818561183a565b935061187081856020860161165e565b61187981611688565b840191505092915050565b61188d81611329565b82525050565b600060e0830160008301516118ab600086018261180d565b5060208301516118be602086018261181c565b5060408301516118d1604086018261181c565b5060608301516118e4606086018261182b565b50608083015184820360808601526118fc828261184b565b91505060a083015161191160a086018261180d565b5060c083015161192460c0860182611884565b508091505092915050565b600060208201905081810360008301526119498184611893565b905092915050565b60006020820190506119666000830184611633565b92915050565b600080600060408486031215611985576119846112c1565b5b600061199386828701611400565b935050602084013567ffffffffffffffff8111156119b4576119b36112c6565b5b6119c0868287016114f4565b92509250509250925092565b600080604083850312156119e3576119e26112c1565b5b60006119f185828601611314565b9250506020611a028582860161134a565b9150509250929050565b600082825260208201905092915050565b7f70726f766964656420746f6b656e41646472657373206973206e6f742077686960008201527f74656c6973746564000000000000000000000000000000000000000000000000602082015250565b6000611a79602883611a0c565b9150611a8482611a1d565b604082019050919050565b60006020820190508181036000830152611aa881611a6c565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680611b2557607f821691505b602082108103611b3857611b37611ade565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b600060088302611ba07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82611b63565b611baa8683611b63565b95508019841693508086168417925050509392505050565b6000819050919050565b6000611be7611be2611bdd84611329565b611bc2565b611329565b9050919050565b6000819050919050565b611c0183611bcc565b611c15611c0d82611bee565b848454611b70565b825550505050565b600090565b611c2a611c1d565b611c35818484611bf8565b505050565b5b81811015611c5957611c4e600082611c22565b600181019050611c3b565b5050565b601f821115611c9e57611c6f81611b3e565b611c7884611b53565b81016020851015611c87578190505b611c9b611c9385611b53565b830182611c3a565b50505b505050565b600082821c905092915050565b6000611cc160001984600802611ca3565b1980831691505092915050565b6000611cda8383611cb0565b9150826002028217905092915050565b611cf382611642565b67ffffffffffffffff811115611d0c57611d0b611aaf565b5b611d168254611b0d565b611d21828285611c5d565b600060209050601f831160018114611d545760008415611d42578287015190505b611d4c8582611cce565b865550611db4565b601f198416611d6286611b3e565b60005b82811015611d8a57848901518255600182019150602085019450602081019050611d65565b86831015611da75784890151611da3601f891682611cb0565b8355505b6001600288020188555050505b505050505050565b600081905092915050565b50565b6000611dd7600083611dbc565b9150611de282611dc7565b600082019050919050565b6000611df882611dca565b9150819050919050565b7f73656e646572206d7573742062652062726964676520636f6e74726163740000600082015250565b6000611e38601e83611a0c565b9150611e4382611e02565b602082019050919050565b60006020820190508181036000830152611e6781611e2b565b9050919050565b7f70726f766964656420636f6e7472616374206973206e6f742077686974656c6960008201527f7374656400000000000000000000000000000000000000000000000000000000602082015250565b6000611eca602483611a0c565b9150611ed582611e6e565b604082019050919050565b60006020820190508181036000830152611ef981611ebd565b9050919050565b6000604082019050611f156000830185611442565b611f2260208301846116d2565b9392505050565b6000606082019050611f3e6000830186611442565b611f4b6020830185611442565b611f5860408301846116d2565b949350505050565b6000611f6b82611642565b611f758185611dbc565b9350611f8581856020860161165e565b80840191505092915050565b6000611f9d8284611f60565b915081905092915050565b7f45524332303a2063616c6c206661696c65640000000000000000000000000000600082015250565b6000611fde601283611a0c565b9150611fe982611fa8565b602082019050919050565b6000602082019050818103600083015261200d81611fd1565b9050919050565b61201d81611757565b811461202857600080fd5b50565b60008151905061203a81612014565b92915050565b600060208284031215612056576120556112c1565b5b60006120648482850161202b565b91505092915050565b7f45524332303a206f7065726174696f6e20646964206e6f742073756363656564600082015250565b60006120a3602083611a0c565b91506120ae8261206d565b602082019050919050565b600060208201905081810360008301526120d281612096565b905091905056fea26469706673582212203ca21f6aa369fabc50310a22651b84838b0789e7f5f268cf398c89734b2d610664736f6c63430008110033000000000000000000000000c94c4ec62a59fcf4964873cc6529559cc7717388000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
Deployed Bytecode
0x6080604052600436106100dd5760003560e01c80637f79bea81161007f578063ba484c0911610059578063ba484c09146102c7578063c8ba6c8714610304578063e248cff214610341578063f3fef3a31461036a576100dd565b80637f79bea81461023857806395601f0914610275578063b8fa37361461029e576100dd565b8063318c136e116100bb578063318c136e1461017157806338995da91461019c5780634402027f146101b85780636a70d081146101fb576100dd565b806301e33667146100e257806307b7ed991461010b5780630a6d55d814610134575b600080fd5b3480156100ee57600080fd5b506101096004803603810190610104919061135f565b610393565b005b34801561011757600080fd5b50610132600480360381019061012d91906113b2565b6103ab565b005b34801561014057600080fd5b5061015b60048036038101906101569190611415565b6103bf565b6040516101689190611451565b60405180910390f35b34801561017d57600080fd5b506101866103f2565b6040516101939190611451565b60405180910390f35b6101b660048036038101906101b1919061154a565b610416565b005b3480156101c457600080fd5b506101df60048036038101906101da91906115e4565b610794565b6040516101f297969594939291906116e1565b60405180910390f35b34801561020757600080fd5b50610222600480360381019061021d91906113b2565b6108c5565b60405161022f9190611772565b60405180910390f35b34801561024457600080fd5b5061025f600480360381019061025a91906113b2565b6108e5565b60405161026c9190611772565b60405180910390f35b34801561028157600080fd5b5061029c6004803603810190610297919061135f565b610905565b005b3480156102aa57600080fd5b506102c560048036038101906102c0919061178d565b61091c565b005b3480156102d357600080fd5b506102ee60048036038101906102e991906117cd565b610932565b6040516102fb919061192f565b60405180910390f35b34801561031057600080fd5b5061032b600480360381019061032691906113b2565b610b17565b6040516103389190611951565b60405180910390f35b34801561034d57600080fd5b506103686004803603810190610363919061196c565b610b2f565b005b34801561037657600080fd5b50610391600480360381019061038c91906119cc565b610ca3565b005b61039b610ca7565b6103a6838383610d37565b505050565b6103b3610ca7565b6103bc81610d4d565b50565b60016020528060005260406000206000915054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1681565b61041e610ca7565b606060008060c4359150604051925060e4359050808301602001604052600e360360e484376000600160008b815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff169050600360008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16610507576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016104fe90611a8f565b60405180910390fd5b600460008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff161561056957610564818885610e34565b610576565b61057581883086610eac565b5b6040518060e001604052808273ffffffffffffffffffffffffffffffffffffffff1681526020018360ff1681526020018a60ff1681526020018b81526020018581526020018873ffffffffffffffffffffffffffffffffffffffff16815260200184815250600560008b60ff1660ff16815260200190815260200160002060008a67ffffffffffffffff1667ffffffffffffffff16815260200190815260200160002060008201518160000160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060208201518160000160146101000a81548160ff021916908360ff16021790555060408201518160000160156101000a81548160ff021916908360ff1602179055506060820151816001015560808201518160020190816106c19190611cea565b5060a08201518160030160006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555060c0820151816004015590505060003414610788578673ffffffffffffffffffffffffffffffffffffffff163460405161074290611ded565b60006040518083038185875af1925050503d806000811461077f576040519150601f19603f3d011682016040523d82523d6000602084013e610784565b606091505b5050505b50505050505050505050565b6005602052816000526040600020602052806000526040600020600091509150508060000160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060000160149054906101000a900460ff16908060000160159054906101000a900460ff169080600101549080600201805461081690611b0d565b80601f016020809104026020016040519081016040528092919081815260200182805461084290611b0d565b801561088f5780601f106108645761010080835404028352916020019161088f565b820191906000526020600020905b81548152906001019060200180831161087257829003601f168201915b5050505050908060030160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16908060040154905087565b60046020528060005260406000206000915054906101000a900460ff1681565b60036020528060005260406000206000915054906101000a900460ff1681565b600083905061091681843085610ec4565b50505050565b610924610ca7565b61092e8282610f4d565b5050565b61093a61124f565b600560008360ff1660ff16815260200190815260200160002060008467ffffffffffffffff1667ffffffffffffffff1681526020019081526020016000206040518060e00160405290816000820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1681526020016000820160149054906101000a900460ff1660ff1660ff1681526020016000820160159054906101000a900460ff1660ff1660ff16815260200160018201548152602001600282018054610a2d90611b0d565b80601f0160208091040260200160405190810160405280929190818152602001828054610a5990611b0d565b8015610aa65780601f10610a7b57610100808354040283529160200191610aa6565b820191906000526020600020905b815481529060010190602001808311610a8957829003601f168201915b505050505081526020016003820160009054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001600482015481525050905092915050565b60026020528060005260406000206000915090505481565b610b37610ca7565b60006060606435915060405190506084358082016020016040526084360360848337506000806001600088815260200190815260200160002060009054906101000a900473ffffffffffffffffffffffffffffffffffffffff16905060208301519150600360008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16610c26576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610c1d90611a8f565b60405180910390fd5b600460008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff1615610c8b57610c86818360601c8661103f565b610c9a565b610c99818360601c86610d37565b5b50505050505050565b5050565b60008054906101000a900473ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff163373ffffffffffffffffffffffffffffffffffffffff1614610d35576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610d2c90611e4e565b60405180910390fd5b565b6000839050610d478184846110b7565b50505050565b600360008273ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060009054906101000a900460ff16610dd9576040517f08c379a0000000000000000000000000000000000000000000000000000000008152600401610dd090611ee0565b60405180910390fd5b6001600460008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff02191690831515021790555050565b60008390508073ffffffffffffffffffffffffffffffffffffffff166379cc679084846040518363ffffffff1660e01b8152600401610e74929190611f00565b600060405180830381600087803b158015610e8e57600080fd5b505af1158015610ea2573d6000803e3d6000fd5b5050505050505050565b6000849050610ebd81858585610ec4565b5050505050565b610f47846323b872dd60e01b858585604051602401610ee593929190611f29565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505061113d565b50505050565b806001600084815260200190815260200160002060006101000a81548173ffffffffffffffffffffffffffffffffffffffff021916908373ffffffffffffffffffffffffffffffffffffffff16021790555081600260008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff168152602001908152602001600020819055506001600360008373ffffffffffffffffffffffffffffffffffffffff1673ffffffffffffffffffffffffffffffffffffffff16815260200190815260200160002060006101000a81548160ff0219169083151502179055505050565b60008390508073ffffffffffffffffffffffffffffffffffffffff166340c10f1984846040518363ffffffff1660e01b815260040161107f929190611f00565b600060405180830381600087803b15801561109957600080fd5b505af11580156110ad573d6000803e3d6000fd5b5050505050505050565b6111388363a9059cbb60e01b84846040516024016110d6929190611f00565b604051602081830303815290604052907bffffffffffffffffffffffffffffffffffffffffffffffffffffffff19166020820180517bffffffffffffffffffffffffffffffffffffffffffffffffffffffff838183161783525050505061113d565b505050565b6000808373ffffffffffffffffffffffffffffffffffffffff16836040516111659190611f91565b6000604051808303816000865af19150503d80600081146111a2576040519150601f19603f3d011682016040523d82523d6000602084013e6111a7565b606091505b5091509150816111ec576040517f08c379a00000000000000000000000000000000000000000000000000000000081526004016111e390611ff4565b60405180910390fd5b600081511461124957808060200190518101906112099190612040565b611248576040517f08c379a000000000000000000000000000000000000000000000000000000000815260040161123f906120b9565b60405180910390fd5b5b50505050565b6040518060e00160405280600073ffffffffffffffffffffffffffffffffffffffff168152602001600060ff168152602001600060ff1681526020016000801916815260200160608152602001600073ffffffffffffffffffffffffffffffffffffffff168152602001600081525090565b600080fd5b600080fd5b600073ffffffffffffffffffffffffffffffffffffffff82169050919050565b60006112f6826112cb565b9050919050565b611306816112eb565b811461131157600080fd5b50565b600081359050611323816112fd565b92915050565b6000819050919050565b61133c81611329565b811461134757600080fd5b50565b60008135905061135981611333565b92915050565b600080600060608486031215611378576113776112c1565b5b600061138686828701611314565b935050602061139786828701611314565b92505060406113a88682870161134a565b9150509250925092565b6000602082840312156113c8576113c76112c1565b5b60006113d684828501611314565b91505092915050565b6000819050919050565b6113f2816113df565b81146113fd57600080fd5b50565b60008135905061140f816113e9565b92915050565b60006020828403121561142b5761142a6112c1565b5b600061143984828501611400565b91505092915050565b61144b816112eb565b82525050565b60006020820190506114666000830184611442565b92915050565b600060ff82169050919050565b6114828161146c565b811461148d57600080fd5b50565b60008135905061149f81611479565b92915050565b600067ffffffffffffffff82169050919050565b6114c2816114a5565b81146114cd57600080fd5b50565b6000813590506114df816114b9565b92915050565b600080fd5b600080fd5b600080fd5b60008083601f84011261150a576115096114e5565b5b8235905067ffffffffffffffff811115611527576115266114ea565b5b602083019150836001820283011115611543576115426114ef565b5b9250929050565b60008060008060008060a08789031215611567576115666112c1565b5b600061157589828a01611400565b965050602061158689828a01611490565b955050604061159789828a016114d0565b94505060606115a889828a01611314565b935050608087013567ffffffffffffffff8111156115c9576115c86112c6565b5b6115d589828a016114f4565b92509250509295509295509295565b600080604083850312156115fb576115fa6112c1565b5b600061160985828601611490565b925050602061161a858286016114d0565b9150509250929050565b61162d8161146c565b82525050565b61163c816113df565b82525050565b600081519050919050565b600082825260208201905092915050565b60005b8381101561167c578082015181840152602081019050611661565b60008484015250505050565b6000601f19601f8301169050919050565b60006116a482611642565b6116ae818561164d565b93506116be81856020860161165e565b6116c781611688565b840191505092915050565b6116db81611329565b82525050565b600060e0820190506116f6600083018a611442565b6117036020830189611624565b6117106040830188611624565b61171d6060830187611633565b818103608083015261172f8186611699565b905061173e60a0830185611442565b61174b60c08301846116d2565b98975050505050505050565b60008115159050919050565b61176c81611757565b82525050565b60006020820190506117876000830184611763565b92915050565b600080604083850312156117a4576117a36112c1565b5b60006117b285828601611400565b92505060206117c385828601611314565b9150509250929050565b600080604083850312156117e4576117e36112c1565b5b60006117f2858286016114d0565b925050602061180385828601611490565b9150509250929050565b611816816112eb565b82525050565b6118258161146c565b82525050565b611834816113df565b82525050565b600082825260208201905092915050565b600061185682611642565b611860818561183a565b935061187081856020860161165e565b61187981611688565b840191505092915050565b61188d81611329565b82525050565b600060e0830160008301516118ab600086018261180d565b5060208301516118be602086018261181c565b5060408301516118d1604086018261181c565b5060608301516118e4606086018261182b565b50608083015184820360808601526118fc828261184b565b91505060a083015161191160a086018261180d565b5060c083015161192460c0860182611884565b508091505092915050565b600060208201905081810360008301526119498184611893565b905092915050565b60006020820190506119666000830184611633565b92915050565b600080600060408486031215611985576119846112c1565b5b600061199386828701611400565b935050602084013567ffffffffffffffff8111156119b4576119b36112c6565b5b6119c0868287016114f4565b92509250509250925092565b600080604083850312156119e3576119e26112c1565b5b60006119f185828601611314565b9250506020611a028582860161134a565b9150509250929050565b600082825260208201905092915050565b7f70726f766964656420746f6b656e41646472657373206973206e6f742077686960008201527f74656c6973746564000000000000000000000000000000000000000000000000602082015250565b6000611a79602883611a0c565b9150611a8482611a1d565b604082019050919050565b60006020820190508181036000830152611aa881611a6c565b9050919050565b7f4e487b7100000000000000000000000000000000000000000000000000000000600052604160045260246000fd5b7f4e487b7100000000000000000000000000000000000000000000000000000000600052602260045260246000fd5b60006002820490506001821680611b2557607f821691505b602082108103611b3857611b37611ade565b5b50919050565b60008190508160005260206000209050919050565b60006020601f8301049050919050565b600082821b905092915050565b600060088302611ba07fffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffffff82611b63565b611baa8683611b63565b95508019841693508086168417925050509392505050565b6000819050919050565b6000611be7611be2611bdd84611329565b611bc2565b611329565b9050919050565b6000819050919050565b611c0183611bcc565b611c15611c0d82611bee565b848454611b70565b825550505050565b600090565b611c2a611c1d565b611c35818484611bf8565b505050565b5b81811015611c5957611c4e600082611c22565b600181019050611c3b565b5050565b601f821115611c9e57611c6f81611b3e565b611c7884611b53565b81016020851015611c87578190505b611c9b611c9385611b53565b830182611c3a565b50505b505050565b600082821c905092915050565b6000611cc160001984600802611ca3565b1980831691505092915050565b6000611cda8383611cb0565b9150826002028217905092915050565b611cf382611642565b67ffffffffffffffff811115611d0c57611d0b611aaf565b5b611d168254611b0d565b611d21828285611c5d565b600060209050601f831160018114611d545760008415611d42578287015190505b611d4c8582611cce565b865550611db4565b601f198416611d6286611b3e565b60005b82811015611d8a57848901518255600182019150602085019450602081019050611d65565b86831015611da75784890151611da3601f891682611cb0565b8355505b6001600288020188555050505b505050505050565b600081905092915050565b50565b6000611dd7600083611dbc565b9150611de282611dc7565b600082019050919050565b6000611df882611dca565b9150819050919050565b7f73656e646572206d7573742062652062726964676520636f6e74726163740000600082015250565b6000611e38601e83611a0c565b9150611e4382611e02565b602082019050919050565b60006020820190508181036000830152611e6781611e2b565b9050919050565b7f70726f766964656420636f6e7472616374206973206e6f742077686974656c6960008201527f7374656400000000000000000000000000000000000000000000000000000000602082015250565b6000611eca602483611a0c565b9150611ed582611e6e565b604082019050919050565b60006020820190508181036000830152611ef981611ebd565b9050919050565b6000604082019050611f156000830185611442565b611f2260208301846116d2565b9392505050565b6000606082019050611f3e6000830186611442565b611f4b6020830185611442565b611f5860408301846116d2565b949350505050565b6000611f6b82611642565b611f758185611dbc565b9350611f8581856020860161165e565b80840191505092915050565b6000611f9d8284611f60565b915081905092915050565b7f45524332303a2063616c6c206661696c65640000000000000000000000000000600082015250565b6000611fde601283611a0c565b9150611fe982611fa8565b602082019050919050565b6000602082019050818103600083015261200d81611fd1565b9050919050565b61201d81611757565b811461202857600080fd5b50565b60008151905061203a81612014565b92915050565b600060208284031215612056576120556112c1565b5b60006120648482850161202b565b91505092915050565b7f45524332303a206f7065726174696f6e20646964206e6f742073756363656564600082015250565b60006120a3602083611a0c565b91506120ae8261206d565b602082019050919050565b600060208201905081810360008301526120d281612096565b905091905056fea26469706673582212203ca21f6aa369fabc50310a22651b84838b0789e7f5f268cf398c89734b2d610664736f6c63430008110033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
000000000000000000000000c94c4ec62a59fcf4964873cc6529559cc7717388000000000000000000000000000000000000000000000000000000000000008000000000000000000000000000000000000000000000000000000000000000a000000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : bridgeAddress (address): 0xC94c4Ec62a59fCF4964873cC6529559Cc7717388
Arg [1] : initialResourceIDs (bytes32[]):
Arg [2] : initialContractAddresses (address[]):
Arg [3] : burnableContractAddresses (address[]):
-----Encoded View---------------
7 Constructor Arguments found :
Arg [0] : 000000000000000000000000c94c4ec62a59fcf4964873cc6529559cc7717388
Arg [1] : 0000000000000000000000000000000000000000000000000000000000000080
Arg [2] : 00000000000000000000000000000000000000000000000000000000000000a0
Arg [3] : 00000000000000000000000000000000000000000000000000000000000000c0
Arg [4] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [5] : 0000000000000000000000000000000000000000000000000000000000000000
Arg [6] : 0000000000000000000000000000000000000000000000000000000000000000
Deployed Bytecode Sourcemap
81279:8426:0:-:0;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;89532:170;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;4734:122;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;3153:69;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;3070:29;;;;;;;;;;;;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;85462:1615;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;81683:74;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;;;;;;;:::i;:::-;;;;;;;;3509:42;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;3403:51;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;77626:198;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;4328:157;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;84247:169;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;3276:69;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;;;;;;:::i;:::-;;;;;;;;87803:1447;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;5081:81;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;:::i;:::-;;89532:170;3593:13;:11;:13::i;:::-;89649:45:::1;89662:12;89676:9;89687:6;89649:12;:45::i;:::-;89532:170:::0;;;:::o;4734:122::-;3593:13;:11;:13::i;:::-;4819:29:::1;4832:15;4819:12;:29::i;:::-;4734:122:::0;:::o;3153:69::-;;;;;;;;;;;;;;;;;;;;;;:::o;3070:29::-;;;;;;;;;;;;:::o;85462:1615::-;3593:13;:11;:13::i;:::-;85691:31:::1;85733:21;85765:34:::0;85861:4:::1;85848:18;85838:28;;85908:4;85902:11;85882:31;;85963:4;85950:18;85927:41;;86027:19;86009:16;86005:42;85999:4;85995:53;85989:4;85982:67;86243:3;86227:14;86223:24;86170:4;86096:16;86065:233;86321:20;86344:33;:45;86378:10;86344:45;;;;;;;;;;;;;;;;;;;;;86321:68;;86408:18;:32;86427:12;86408:32;;;;;;;;;;;;;;;;;;;;;;;;;86400:85;;;;;;;;;;;;:::i;:::-;;;;;;;;;86502:9;:23;86512:12;86502:23;;;;;;;;;;;;;;;;;;;;;;;;;86498:188;;;86542:42;86552:12;86566:9;86577:6;86542:9;:42::i;:::-;86498:188;;;86617:57;86627:12;86641:9;86660:4;86667:6;86617:9;:57::i;:::-;86498:188;86750:226;;;;;;;;86778:12;86750:226;;;;;;86811:19;86750:226;;;;;;86846:18;86750:226;;;;;;86879:10;86750:226;;;;86904:16;86750:226;;;;86935:9;86750:226;;;;;;86959:6;86750:226;;::::0;86698:15:::1;:35;86714:18;86698:35;;;;;;;;;;;;;;;:49;86734:12;86698:49;;;;;;;;;;;;;;;:278;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;87004:1;86991:9;:14;86987:83;;87022:9;:14;;87044:9;87022:36;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;86987:83;85680:1397;;;;85462:1615:::0;;;;;;:::o;81683:74::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;3509:42::-;;;;;;;;;;;;;;;;;;;;;;:::o;3403:51::-;;;;;;;;;;;;;;;;;;;;;;:::o;77626:198::-;77716:12;77738;77716:35;;77762:54;77780:5;77787;77802:4;77809:6;77762:17;:54::i;:::-;77705:119;77626:198;;;:::o;4328:157::-;3593:13;:11;:13::i;:::-;4436:41:::1;4449:10;4461:15;4436:12;:41::i;:::-;4328:157:::0;;:::o;84247:169::-;84331:20;;:::i;:::-;84371:15;:23;84387:6;84371:23;;;;;;;;;;;;;;;:37;84395:12;84371:37;;;;;;;;;;;;;;;84364:44;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;84247:169;;;;:::o;3276:69::-;;;;;;;;;;;;;;;;;:::o;87803:1447::-;3593:13;:11;:13::i;:::-;87909:20:::1;87940:41;88041:4;88028:18;88018:28;;88099:4;88093:11;88062:42;;88169:4;88156:18;88244:30;88215:27;88211:64;88205:4;88201:75;88195:4;88188:89;88630:4;88614:14;88610:25;88558:4;88473:27;88442:244;88003:694;88709:24;88744:20:::0;88767:33:::1;:45;88801:10;88767:45;;;;;;;;;;;;;;;;;;;;;88744:68;;88908:4;88879:27;88875:38;88869:45;88849:65;;88945:18;:32;88964:12;88945:32;;;;;;;;;;;;;;;;;;;;;;;;;88937:85;;;;;;;;;;;;:::i;:::-;;;;;;;;;89039:9;:23;89049:12;89039:23;;;;;;;;;;;;;;;;;;;;;;;;;89035:208;;;89079:58;89089:12;89111:16;89103:25;;89130:6;89079:9;:58::i;:::-;89035:208;;;89170:61;89183:12;89205:16;89197:25;;89224:6;89170:12;:61::i;:::-;89035:208;87898:1352;;;;87803:1447:::0;;;:::o;5081:81::-;;;:::o;3634:121::-;3698:14;;;;;;;;;;3684:28;;:10;:28;;;3676:71;;;;;;;;;;;;:::i;:::-;;;;;;;;;3634:121::o;78599:192::-;78698:12;78720;78698:35;;78744:39;78758:5;78765:9;78776:6;78744:13;:39::i;:::-;78687:104;78599:192;;;:::o;5912:203::-;5987:18;:35;6006:15;5987:35;;;;;;;;;;;;;;;;;;;;;;;;;5979:84;;;;;;;;;;;;:::i;:::-;;;;;;;;;6103:4;6074:9;:26;6084:15;6074:26;;;;;;;;;;;;;;;;:33;;;;;;;;;;;;;;;;;;5912:203;:::o;79450:189::-;79542:19;79578:12;79542:49;;79602:5;:14;;;79617:5;79624:6;79602:29;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;79531:108;79450:189;;;:::o;78131:215::-;78242:12;78264;78242:35;;78288:50;78306:5;78313;78320:9;78331:6;78288:17;:50::i;:::-;78231:115;78131:215;;;;:::o;80302:195::-;80403:86;80413:5;80443:27;;;80472:4;80478:2;80482:5;80420:68;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;80403:9;:86::i;:::-;80302:195;;;;:::o;5617:287::-;5752:15;5704:33;:45;5738:10;5704:45;;;;;;;;;;;;:63;;;;;;;;;;;;;;;;;;5831:10;5778:33;:50;5812:15;5778:50;;;;;;;;;;;;;;;:63;;;;5892:4;5854:18;:35;5873:15;5854:35;;;;;;;;;;;;;;;;:42;;;;;;;;;;;;;;;;;;5617:287;;:::o;79020:215::-;79116:29;79172:12;79116:69;;79196:5;:10;;;79207:9;79218:6;79196:29;;;;;;;;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;79105:130;79020:215;;;:::o;79860:167::-;79943:76;79953:5;79983:23;;;80008:2;80012:5;79960:58;;;;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;79943:9;:76::i;:::-;79860:167;;;:::o;80665:347::-;80745:12;80759:23;80794:5;80786:19;;80806:4;80786:25;;;;;;:::i;:::-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;80744:67;;;;80830:7;80822:38;;;;;;;;;;;;:::i;:::-;;;;;;;;;80898:1;80877:10;:17;:22;80873:132;;80937:10;80926:30;;;;;;;;;;;;:::i;:::-;80918:75;;;;;;;;;;;;:::i;:::-;;;;;;;;;80873:132;80725:287;;80665:347;;:::o;-1:-1:-1:-;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;:::o;88:117:1:-;197:1;194;187:12;211:117;320:1;317;310:12;334:126;371:7;411:42;404:5;400:54;389:65;;334:126;;;:::o;466:96::-;503:7;532:24;550:5;532:24;:::i;:::-;521:35;;466:96;;;:::o;568:122::-;641:24;659:5;641:24;:::i;:::-;634:5;631:35;621:63;;680:1;677;670:12;621:63;568:122;:::o;696:139::-;742:5;780:6;767:20;758:29;;796:33;823:5;796:33;:::i;:::-;696:139;;;;:::o;841:77::-;878:7;907:5;896:16;;841:77;;;:::o;924:122::-;997:24;1015:5;997:24;:::i;:::-;990:5;987:35;977:63;;1036:1;1033;1026:12;977:63;924:122;:::o;1052:139::-;1098:5;1136:6;1123:20;1114:29;;1152:33;1179:5;1152:33;:::i;:::-;1052:139;;;;:::o;1197:619::-;1274:6;1282;1290;1339:2;1327:9;1318:7;1314:23;1310:32;1307:119;;;1345:79;;:::i;:::-;1307:119;1465:1;1490:53;1535:7;1526:6;1515:9;1511:22;1490:53;:::i;:::-;1480:63;;1436:117;1592:2;1618:53;1663:7;1654:6;1643:9;1639:22;1618:53;:::i;:::-;1608:63;;1563:118;1720:2;1746:53;1791:7;1782:6;1771:9;1767:22;1746:53;:::i;:::-;1736:63;;1691:118;1197:619;;;;;:::o;1822:329::-;1881:6;1930:2;1918:9;1909:7;1905:23;1901:32;1898:119;;;1936:79;;:::i;:::-;1898:119;2056:1;2081:53;2126:7;2117:6;2106:9;2102:22;2081:53;:::i;:::-;2071:63;;2027:117;1822:329;;;;:::o;2157:77::-;2194:7;2223:5;2212:16;;2157:77;;;:::o;2240:122::-;2313:24;2331:5;2313:24;:::i;:::-;2306:5;2303:35;2293:63;;2352:1;2349;2342:12;2293:63;2240:122;:::o;2368:139::-;2414:5;2452:6;2439:20;2430:29;;2468:33;2495:5;2468:33;:::i;:::-;2368:139;;;;:::o;2513:329::-;2572:6;2621:2;2609:9;2600:7;2596:23;2592:32;2589:119;;;2627:79;;:::i;:::-;2589:119;2747:1;2772:53;2817:7;2808:6;2797:9;2793:22;2772:53;:::i;:::-;2762:63;;2718:117;2513:329;;;;:::o;2848:118::-;2935:24;2953:5;2935:24;:::i;:::-;2930:3;2923:37;2848:118;;:::o;2972:222::-;3065:4;3103:2;3092:9;3088:18;3080:26;;3116:71;3184:1;3173:9;3169:17;3160:6;3116:71;:::i;:::-;2972:222;;;;:::o;3200:86::-;3235:7;3275:4;3268:5;3264:16;3253:27;;3200:86;;;:::o;3292:118::-;3363:22;3379:5;3363:22;:::i;:::-;3356:5;3353:33;3343:61;;3400:1;3397;3390:12;3343:61;3292:118;:::o;3416:135::-;3460:5;3498:6;3485:20;3476:29;;3514:31;3539:5;3514:31;:::i;:::-;3416:135;;;;:::o;3557:101::-;3593:7;3633:18;3626:5;3622:30;3611:41;;3557:101;;;:::o;3664:120::-;3736:23;3753:5;3736:23;:::i;:::-;3729:5;3726:34;3716:62;;3774:1;3771;3764:12;3716:62;3664:120;:::o;3790:137::-;3835:5;3873:6;3860:20;3851:29;;3889:32;3915:5;3889:32;:::i;:::-;3790:137;;;;:::o;3933:117::-;4042:1;4039;4032:12;4056:117;4165:1;4162;4155:12;4179:117;4288:1;4285;4278:12;4315:552;4372:8;4382:6;4432:3;4425:4;4417:6;4413:17;4409:27;4399:122;;4440:79;;:::i;:::-;4399:122;4553:6;4540:20;4530:30;;4583:18;4575:6;4572:30;4569:117;;;4605:79;;:::i;:::-;4569:117;4719:4;4711:6;4707:17;4695:29;;4773:3;4765:4;4757:6;4753:17;4743:8;4739:32;4736:41;4733:128;;;4780:79;;:::i;:::-;4733:128;4315:552;;;;;:::o;4873:1103::-;4976:6;4984;4992;5000;5008;5016;5065:3;5053:9;5044:7;5040:23;5036:33;5033:120;;;5072:79;;:::i;:::-;5033:120;5192:1;5217:53;5262:7;5253:6;5242:9;5238:22;5217:53;:::i;:::-;5207:63;;5163:117;5319:2;5345:51;5388:7;5379:6;5368:9;5364:22;5345:51;:::i;:::-;5335:61;;5290:116;5445:2;5471:52;5515:7;5506:6;5495:9;5491:22;5471:52;:::i;:::-;5461:62;;5416:117;5572:2;5598:53;5643:7;5634:6;5623:9;5619:22;5598:53;:::i;:::-;5588:63;;5543:118;5728:3;5717:9;5713:19;5700:33;5760:18;5752:6;5749:30;5746:117;;;5782:79;;:::i;:::-;5746:117;5895:64;5951:7;5942:6;5931:9;5927:22;5895:64;:::i;:::-;5877:82;;;;5671:298;4873:1103;;;;;;;;:::o;5982:468::-;6047:6;6055;6104:2;6092:9;6083:7;6079:23;6075:32;6072:119;;;6110:79;;:::i;:::-;6072:119;6230:1;6255:51;6298:7;6289:6;6278:9;6274:22;6255:51;:::i;:::-;6245:61;;6201:115;6355:2;6381:52;6425:7;6416:6;6405:9;6401:22;6381:52;:::i;:::-;6371:62;;6326:117;5982:468;;;;;:::o;6456:112::-;6539:22;6555:5;6539:22;:::i;:::-;6534:3;6527:35;6456:112;;:::o;6574:118::-;6661:24;6679:5;6661:24;:::i;:::-;6656:3;6649:37;6574:118;;:::o;6698:98::-;6749:6;6783:5;6777:12;6767:22;;6698:98;;;:::o;6802:168::-;6885:11;6919:6;6914:3;6907:19;6959:4;6954:3;6950:14;6935:29;;6802:168;;;;:::o;6976:246::-;7057:1;7067:113;7081:6;7078:1;7075:13;7067:113;;;7166:1;7161:3;7157:11;7151:18;7147:1;7142:3;7138:11;7131:39;7103:2;7100:1;7096:10;7091:15;;7067:113;;;7214:1;7205:6;7200:3;7196:16;7189:27;7038:184;6976:246;;;:::o;7228:102::-;7269:6;7320:2;7316:7;7311:2;7304:5;7300:14;7296:28;7286:38;;7228:102;;;:::o;7336:373::-;7422:3;7450:38;7482:5;7450:38;:::i;:::-;7504:70;7567:6;7562:3;7504:70;:::i;:::-;7497:77;;7583:65;7641:6;7636:3;7629:4;7622:5;7618:16;7583:65;:::i;:::-;7673:29;7695:6;7673:29;:::i;:::-;7668:3;7664:39;7657:46;;7426:283;7336:373;;;;:::o;7715:118::-;7802:24;7820:5;7802:24;:::i;:::-;7797:3;7790:37;7715:118;;:::o;7839:957::-;8110:4;8148:3;8137:9;8133:19;8125:27;;8162:71;8230:1;8219:9;8215:17;8206:6;8162:71;:::i;:::-;8243:68;8307:2;8296:9;8292:18;8283:6;8243:68;:::i;:::-;8321;8385:2;8374:9;8370:18;8361:6;8321:68;:::i;:::-;8399:72;8467:2;8456:9;8452:18;8443:6;8399:72;:::i;:::-;8519:9;8513:4;8509:20;8503:3;8492:9;8488:19;8481:49;8547:76;8618:4;8609:6;8547:76;:::i;:::-;8539:84;;8633:73;8701:3;8690:9;8686:19;8677:6;8633:73;:::i;:::-;8716;8784:3;8773:9;8769:19;8760:6;8716:73;:::i;:::-;7839:957;;;;;;;;;;:::o;8802:90::-;8836:7;8879:5;8872:13;8865:21;8854:32;;8802:90;;;:::o;8898:109::-;8979:21;8994:5;8979:21;:::i;:::-;8974:3;8967:34;8898:109;;:::o;9013:210::-;9100:4;9138:2;9127:9;9123:18;9115:26;;9151:65;9213:1;9202:9;9198:17;9189:6;9151:65;:::i;:::-;9013:210;;;;:::o;9229:474::-;9297:6;9305;9354:2;9342:9;9333:7;9329:23;9325:32;9322:119;;;9360:79;;:::i;:::-;9322:119;9480:1;9505:53;9550:7;9541:6;9530:9;9526:22;9505:53;:::i;:::-;9495:63;;9451:117;9607:2;9633:53;9678:7;9669:6;9658:9;9654:22;9633:53;:::i;:::-;9623:63;;9578:118;9229:474;;;;;:::o;9709:468::-;9774:6;9782;9831:2;9819:9;9810:7;9806:23;9802:32;9799:119;;;9837:79;;:::i;:::-;9799:119;9957:1;9982:52;10026:7;10017:6;10006:9;10002:22;9982:52;:::i;:::-;9972:62;;9928:116;10083:2;10109:51;10152:7;10143:6;10132:9;10128:22;10109:51;:::i;:::-;10099:61;;10054:116;9709:468;;;;;:::o;10183:108::-;10260:24;10278:5;10260:24;:::i;:::-;10255:3;10248:37;10183:108;;:::o;10297:102::-;10370:22;10386:5;10370:22;:::i;:::-;10365:3;10358:35;10297:102;;:::o;10405:108::-;10482:24;10500:5;10482:24;:::i;:::-;10477:3;10470:37;10405:108;;:::o;10519:158::-;10592:11;10626:6;10621:3;10614:19;10666:4;10661:3;10657:14;10642:29;;10519:158;;;;:::o;10683:353::-;10759:3;10787:38;10819:5;10787:38;:::i;:::-;10841:60;10894:6;10889:3;10841:60;:::i;:::-;10834:67;;10910:65;10968:6;10963:3;10956:4;10949:5;10945:16;10910:65;:::i;:::-;11000:29;11022:6;11000:29;:::i;:::-;10995:3;10991:39;10984:46;;10763:273;10683:353;;;;:::o;11042:108::-;11119:24;11137:5;11119:24;:::i;:::-;11114:3;11107:37;11042:108;;:::o;11234:1569::-;11365:3;11401:4;11396:3;11392:14;11497:4;11490:5;11486:16;11480:23;11516:63;11573:4;11568:3;11564:14;11550:12;11516:63;:::i;:::-;11416:173;11698:4;11691:5;11687:16;11681:23;11717:59;11770:4;11765:3;11761:14;11747:12;11717:59;:::i;:::-;11599:187;11883:4;11876:5;11872:16;11866:23;11902:59;11955:4;11950:3;11946:14;11932:12;11902:59;:::i;:::-;11796:175;12060:4;12053:5;12049:16;12043:23;12079:63;12136:4;12131:3;12127:14;12113:12;12079:63;:::i;:::-;11981:171;12258:4;12251:5;12247:16;12241:23;12311:3;12305:4;12301:14;12294:4;12289:3;12285:14;12278:38;12337:71;12403:4;12389:12;12337:71;:::i;:::-;12329:79;;12162:257;12507:4;12500:5;12496:16;12490:23;12526:63;12583:4;12578:3;12574:14;12560:12;12526:63;:::i;:::-;12429:170;12684:4;12677:5;12673:16;12667:23;12703:63;12760:4;12755:3;12751:14;12737:12;12703:63;:::i;:::-;12609:167;12793:4;12786:11;;11370:1433;11234:1569;;;;:::o;12809:397::-;12964:4;13002:2;12991:9;12987:18;12979:26;;13051:9;13045:4;13041:20;13037:1;13026:9;13022:17;13015:47;13079:120;13194:4;13185:6;13079:120;:::i;:::-;13071:128;;12809:397;;;;:::o;13212:222::-;13305:4;13343:2;13332:9;13328:18;13320:26;;13356:71;13424:1;13413:9;13409:17;13400:6;13356:71;:::i;:::-;13212:222;;;;:::o;13440:672::-;13519:6;13527;13535;13584:2;13572:9;13563:7;13559:23;13555:32;13552:119;;;13590:79;;:::i;:::-;13552:119;13710:1;13735:53;13780:7;13771:6;13760:9;13756:22;13735:53;:::i;:::-;13725:63;;13681:117;13865:2;13854:9;13850:18;13837:32;13896:18;13888:6;13885:30;13882:117;;;13918:79;;:::i;:::-;13882:117;14031:64;14087:7;14078:6;14067:9;14063:22;14031:64;:::i;:::-;14013:82;;;;13808:297;13440:672;;;;;:::o;14118:474::-;14186:6;14194;14243:2;14231:9;14222:7;14218:23;14214:32;14211:119;;;14249:79;;:::i;:::-;14211:119;14369:1;14394:53;14439:7;14430:6;14419:9;14415:22;14394:53;:::i;:::-;14384:63;;14340:117;14496:2;14522:53;14567:7;14558:6;14547:9;14543:22;14522:53;:::i;:::-;14512:63;;14467:118;14118:474;;;;;:::o;14598:169::-;14682:11;14716:6;14711:3;14704:19;14756:4;14751:3;14747:14;14732:29;;14598:169;;;;:::o;14773:227::-;14913:34;14909:1;14901:6;14897:14;14890:58;14982:10;14977:2;14969:6;14965:15;14958:35;14773:227;:::o;15006:366::-;15148:3;15169:67;15233:2;15228:3;15169:67;:::i;:::-;15162:74;;15245:93;15334:3;15245:93;:::i;:::-;15363:2;15358:3;15354:12;15347:19;;15006:366;;;:::o;15378:419::-;15544:4;15582:2;15571:9;15567:18;15559:26;;15631:9;15625:4;15621:20;15617:1;15606:9;15602:17;15595:47;15659:131;15785:4;15659:131;:::i;:::-;15651:139;;15378:419;;;:::o;15803:180::-;15851:77;15848:1;15841:88;15948:4;15945:1;15938:15;15972:4;15969:1;15962:15;15989:180;16037:77;16034:1;16027:88;16134:4;16131:1;16124:15;16158:4;16155:1;16148:15;16175:320;16219:6;16256:1;16250:4;16246:12;16236:22;;16303:1;16297:4;16293:12;16324:18;16314:81;;16380:4;16372:6;16368:17;16358:27;;16314:81;16442:2;16434:6;16431:14;16411:18;16408:38;16405:84;;16461:18;;:::i;:::-;16405:84;16226:269;16175:320;;;:::o;16501:140::-;16549:4;16572:3;16564:11;;16595:3;16592:1;16585:14;16629:4;16626:1;16616:18;16608:26;;16501:140;;;:::o;16647:93::-;16684:6;16731:2;16726;16719:5;16715:14;16711:23;16701:33;;16647:93;;;:::o;16746:107::-;16790:8;16840:5;16834:4;16830:16;16809:37;;16746:107;;;;:::o;16859:393::-;16928:6;16978:1;16966:10;16962:18;17001:97;17031:66;17020:9;17001:97;:::i;:::-;17119:39;17149:8;17138:9;17119:39;:::i;:::-;17107:51;;17191:4;17187:9;17180:5;17176:21;17167:30;;17240:4;17230:8;17226:19;17219:5;17216:30;17206:40;;16935:317;;16859:393;;;;;:::o;17258:60::-;17286:3;17307:5;17300:12;;17258:60;;;:::o;17324:142::-;17374:9;17407:53;17425:34;17434:24;17452:5;17434:24;:::i;:::-;17425:34;:::i;:::-;17407:53;:::i;:::-;17394:66;;17324:142;;;:::o;17472:75::-;17515:3;17536:5;17529:12;;17472:75;;;:::o;17553:269::-;17663:39;17694:7;17663:39;:::i;:::-;17724:91;17773:41;17797:16;17773:41;:::i;:::-;17765:6;17758:4;17752:11;17724:91;:::i;:::-;17718:4;17711:105;17629:193;17553:269;;;:::o;17828:73::-;17873:3;17828:73;:::o;17907:189::-;17984:32;;:::i;:::-;18025:65;18083:6;18075;18069:4;18025:65;:::i;:::-;17960:136;17907:189;;:::o;18102:186::-;18162:120;18179:3;18172:5;18169:14;18162:120;;;18233:39;18270:1;18263:5;18233:39;:::i;:::-;18206:1;18199:5;18195:13;18186:22;;18162:120;;;18102:186;;:::o;18294:541::-;18394:2;18389:3;18386:11;18383:445;;;18428:37;18459:5;18428:37;:::i;:::-;18511:29;18529:10;18511:29;:::i;:::-;18501:8;18497:44;18694:2;18682:10;18679:18;18676:49;;;18715:8;18700:23;;18676:49;18738:80;18794:22;18812:3;18794:22;:::i;:::-;18784:8;18780:37;18767:11;18738:80;:::i;:::-;18398:430;;18383:445;18294:541;;;:::o;18841:117::-;18895:8;18945:5;18939:4;18935:16;18914:37;;18841:117;;;;:::o;18964:169::-;19008:6;19041:51;19089:1;19085:6;19077:5;19074:1;19070:13;19041:51;:::i;:::-;19037:56;19122:4;19116;19112:15;19102:25;;19015:118;18964:169;;;;:::o;19138:295::-;19214:4;19360:29;19385:3;19379:4;19360:29;:::i;:::-;19352:37;;19422:3;19419:1;19415:11;19409:4;19406:21;19398:29;;19138:295;;;;:::o;19438:1390::-;19553:36;19585:3;19553:36;:::i;:::-;19654:18;19646:6;19643:30;19640:56;;;19676:18;;:::i;:::-;19640:56;19720:38;19752:4;19746:11;19720:38;:::i;:::-;19805:66;19864:6;19856;19850:4;19805:66;:::i;:::-;19898:1;19922:4;19909:17;;19954:2;19946:6;19943:14;19971:1;19966:617;;;;20627:1;20644:6;20641:77;;;20693:9;20688:3;20684:19;20678:26;20669:35;;20641:77;20744:67;20804:6;20797:5;20744:67;:::i;:::-;20738:4;20731:81;20600:222;19936:886;;19966:617;20018:4;20014:9;20006:6;20002:22;20052:36;20083:4;20052:36;:::i;:::-;20110:1;20124:208;20138:7;20135:1;20132:14;20124:208;;;20217:9;20212:3;20208:19;20202:26;20194:6;20187:42;20268:1;20260:6;20256:14;20246:24;;20315:2;20304:9;20300:18;20287:31;;20161:4;20158:1;20154:12;20149:17;;20124:208;;;20360:6;20351:7;20348:19;20345:179;;;20418:9;20413:3;20409:19;20403:26;20461:48;20503:4;20495:6;20491:17;20480:9;20461:48;:::i;:::-;20453:6;20446:64;20368:156;20345:179;20570:1;20566;20558:6;20554:14;20550:22;20544:4;20537:36;19973:610;;;19936:886;;19528:1300;;;19438:1390;;:::o;20834:147::-;20935:11;20972:3;20957:18;;20834:147;;;;:::o;20987:114::-;;:::o;21107:398::-;21266:3;21287:83;21368:1;21363:3;21287:83;:::i;:::-;21280:90;;21379:93;21468:3;21379:93;:::i;:::-;21497:1;21492:3;21488:11;21481:18;;21107:398;;;:::o;21511:379::-;21695:3;21717:147;21860:3;21717:147;:::i;:::-;21710:154;;21881:3;21874:10;;21511:379;;;:::o;21896:180::-;22036:32;22032:1;22024:6;22020:14;22013:56;21896:180;:::o;22082:366::-;22224:3;22245:67;22309:2;22304:3;22245:67;:::i;:::-;22238:74;;22321:93;22410:3;22321:93;:::i;:::-;22439:2;22434:3;22430:12;22423:19;;22082:366;;;:::o;22454:419::-;22620:4;22658:2;22647:9;22643:18;22635:26;;22707:9;22701:4;22697:20;22693:1;22682:9;22678:17;22671:47;22735:131;22861:4;22735:131;:::i;:::-;22727:139;;22454:419;;;:::o;22879:223::-;23019:34;23015:1;23007:6;23003:14;22996:58;23088:6;23083:2;23075:6;23071:15;23064:31;22879:223;:::o;23108:366::-;23250:3;23271:67;23335:2;23330:3;23271:67;:::i;:::-;23264:74;;23347:93;23436:3;23347:93;:::i;:::-;23465:2;23460:3;23456:12;23449:19;;23108:366;;;:::o;23480:419::-;23646:4;23684:2;23673:9;23669:18;23661:26;;23733:9;23727:4;23723:20;23719:1;23708:9;23704:17;23697:47;23761:131;23887:4;23761:131;:::i;:::-;23753:139;;23480:419;;;:::o;23905:332::-;24026:4;24064:2;24053:9;24049:18;24041:26;;24077:71;24145:1;24134:9;24130:17;24121:6;24077:71;:::i;:::-;24158:72;24226:2;24215:9;24211:18;24202:6;24158:72;:::i;:::-;23905:332;;;;;:::o;24243:442::-;24392:4;24430:2;24419:9;24415:18;24407:26;;24443:71;24511:1;24500:9;24496:17;24487:6;24443:71;:::i;:::-;24524:72;24592:2;24581:9;24577:18;24568:6;24524:72;:::i;:::-;24606;24674:2;24663:9;24659:18;24650:6;24606:72;:::i;:::-;24243:442;;;;;;:::o;24691:386::-;24795:3;24823:38;24855:5;24823:38;:::i;:::-;24877:88;24958:6;24953:3;24877:88;:::i;:::-;24870:95;;24974:65;25032:6;25027:3;25020:4;25013:5;25009:16;24974:65;:::i;:::-;25064:6;25059:3;25055:16;25048:23;;24799:278;24691:386;;;;:::o;25083:271::-;25213:3;25235:93;25324:3;25315:6;25235:93;:::i;:::-;25228:100;;25345:3;25338:10;;25083:271;;;;:::o;25360:168::-;25500:20;25496:1;25488:6;25484:14;25477:44;25360:168;:::o;25534:366::-;25676:3;25697:67;25761:2;25756:3;25697:67;:::i;:::-;25690:74;;25773:93;25862:3;25773:93;:::i;:::-;25891:2;25886:3;25882:12;25875:19;;25534:366;;;:::o;25906:419::-;26072:4;26110:2;26099:9;26095:18;26087:26;;26159:9;26153:4;26149:20;26145:1;26134:9;26130:17;26123:47;26187:131;26313:4;26187:131;:::i;:::-;26179:139;;25906:419;;;:::o;26331:116::-;26401:21;26416:5;26401:21;:::i;:::-;26394:5;26391:32;26381:60;;26437:1;26434;26427:12;26381:60;26331:116;:::o;26453:137::-;26507:5;26538:6;26532:13;26523:22;;26554:30;26578:5;26554:30;:::i;:::-;26453:137;;;;:::o;26596:345::-;26663:6;26712:2;26700:9;26691:7;26687:23;26683:32;26680:119;;;26718:79;;:::i;:::-;26680:119;26838:1;26863:61;26916:7;26907:6;26896:9;26892:22;26863:61;:::i;:::-;26853:71;;26809:125;26596:345;;;;:::o;26947:182::-;27087:34;27083:1;27075:6;27071:14;27064:58;26947:182;:::o;27135:366::-;27277:3;27298:67;27362:2;27357:3;27298:67;:::i;:::-;27291:74;;27374:93;27463:3;27374:93;:::i;:::-;27492:2;27487:3;27483:12;27476:19;;27135:366;;;:::o;27507:419::-;27673:4;27711:2;27700:9;27696:18;27688:26;;27760:9;27754:4;27750:20;27746:1;27735:9;27731:17;27724:47;27788:131;27914:4;27788:131;:::i;:::-;27780:139;;27507:419;;;:::o
Swarm Source
ipfs://3ca21f6aa369fabc50310a22651b84838b0789e7f5f268cf398c89734b2d6106
Loading...
Loading
Loading...
Loading
Net Worth in USD
$78,159,749.10
Net Worth in ETH
39,034.011901
Token Allocations
CHZ
100.00%
Multichain Portfolio | 33 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|---|---|---|---|---|
| ETH | 100.00% | $0.037752 | 2,070,335,726.1523 | $78,159,749.1 |
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.