| Transaction Hash |
Method
|
Block
|
From
|
To
|
|||||
|---|---|---|---|---|---|---|---|---|---|
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
ERC20Handler
Compiler Version
v0.8.11+commit.d7f03943
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
// The Licensed Work is (c) 2022 Sygma
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.11;
import "../interfaces/IHandler.sol";
import "./ERCHandlerHelpers.sol";
import "../ERC20Safe.sol";
/**
@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 IHandler, ERCHandlerHelpers, ERC20Safe {
/**
@param bridgeAddress Contract address of previously deployed Bridge.
*/
constructor(
address bridgeAddress
) ERCHandlerHelpers(bridgeAddress) {
}
/**
@notice A deposit is initiated by making a deposit in the Bridge contract.
@param resourceID ResourceID used to find address of token to be used for deposit.
@param depositor Address of account making the deposit in the Bridge contract.
@param data Consists of {amount} 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
@dev Depending if the corresponding {tokenAddress} for the parsed {resourceID} is
marked true in {_tokenContractAddressToTokenProperties[tokenAddress].isBurnable}, deposited tokens will be burned, if not, they will be locked.
@return an empty data.
*/
function deposit(
bytes32 resourceID,
address depositor,
bytes calldata data
) external override onlyBridge returns (bytes memory) {
uint256 amount;
(amount) = abi.decode(data, (uint));
address tokenAddress = _resourceIDToTokenContractAddress[resourceID];
if (!_tokenContractAddressToTokenProperties[tokenAddress].isWhitelisted) revert ContractAddressNotWhitelisted(tokenAddress);
if (_tokenContractAddressToTokenProperties[tokenAddress].isBurnable) {
burnERC20(tokenAddress, depositor, amount);
} else {
lockERC20(tokenAddress, depositor, address(this), amount);
}
return abi.encodePacked(convertToInternalBalance(tokenAddress, amount));
}
/**
@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 ResourceID to be used when making deposits.
@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 returns (bytes memory) {
uint256 amount;
uint256 lenDestinationRecipientAddress;
bytes memory destinationRecipientAddress;
(amount, lenDestinationRecipientAddress) = abi.decode(data, (uint, uint));
destinationRecipientAddress = bytes(data[64:64 + lenDestinationRecipientAddress]);
bytes20 recipientAddress;
address tokenAddress = _resourceIDToTokenContractAddress[resourceID];
assembly {
recipientAddress := mload(add(destinationRecipientAddress, 0x20))
}
if (!_tokenContractAddressToTokenProperties[tokenAddress].isWhitelisted) revert ContractAddressNotWhitelisted(tokenAddress);
if (_tokenContractAddressToTokenProperties[tokenAddress].isBurnable) {
mintERC20(tokenAddress, address(recipientAddress), convertToExternalBalance(tokenAddress, amount));
} else {
releaseERC20(tokenAddress, address(recipientAddress), convertToExternalBalance(tokenAddress, amount));
}
return abi.encode(tokenAddress, address(recipientAddress), amount);
}
/**
@notice Used to manually release ERC20 tokens from ERC20Safe.
@param data Consists of {tokenAddress}, {recipient}, and {amount} all padded to 32 bytes.
@notice Data passed into the function should be constructed as follows:
tokenAddress address bytes 0 - 32
recipient address bytes 32 - 64
amount uint bytes 64 - 96
*/
function withdraw(bytes memory data) external override onlyBridge {
address tokenAddress;
address recipient;
uint amount;
(tokenAddress, recipient, amount) = abi.decode(data, (address, address, uint));
releaseERC20(tokenAddress, recipient, amount);
}
/**
@notice Sets {_resourceIDToContractAddress} with {contractAddress},
{_tokenContractAddressToTokenProperties[tokenAddress].resourceID} with {resourceID} and
{_tokenContractAddressToTokenProperties[tokenAddress].isWhitelisted} to true for {contractAddress} in ERCHandlerHelpers contract.
Sets decimals value for contractAddress if value is provided in args.
@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.
@param args Additional data to be passed to specified handler.
*/
function setResource(bytes32 resourceID, address contractAddress, bytes calldata args) external onlyBridge {
_setResource(resourceID, contractAddress);
if (args.length > 0) {
uint8 externalTokenDecimals = uint8(bytes1(args));
_setDecimals(contractAddress, externalTokenDecimals);
}
}
}// The Licensed Work is (c) 2022 Sygma
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.11;
/**
@title Interface for handler that handles generic deposits and deposit executions.
@author ChainSafe Systems.
*/
interface IHandler {
/**
@notice It is intended that deposit are made using the Bridge contract.
@param resourceID ResourceID used to find address of handler to be used for deposit.
@param depositor 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, address depositor, bytes calldata data) external returns (bytes memory);
/**
@notice It is intended that proposals are executed by the Bridge contract.
@param resourceID ResourceID to be used when making deposits.
@param data Consists of additional data needed for a specific deposit execution.
*/
function executeProposal(bytes32 resourceID, bytes calldata data) external returns (bytes memory);
/**
@notice Correlates {_resourceIDToContractAddress} with {contractAddress}, {_tokenContractAddressToTokenProperties[tokenAddress].resourceID} with {resourceID} and marks
{_tokenContractAddressToTokenProperties[tokenAddress].isWhitelisted} to true for {contractAddress} in ERCHandlerHelpers contract.
@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.
@param args Additional data to be passed to specified handler.
*/
function setResource(bytes32 resourceID, address contractAddress, bytes calldata args) external;
}// The Licensed Work is (c) 2022 Sygma
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.11;
/**
@title Interface to be used with handlers that support ERC20s and ERC721s.
@author ChainSafe Systems.
*/
interface IERCHandler {
/**
@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 Withdraw funds from ERC safes.
@param data ABI-encoded withdrawal params relevant to the handler.
*/
function withdraw(bytes memory data) external;
/**
@notice Exposing getter for {_resourceIDToTokenContractAddress}.
@param resourceID ResourceID to be used.
@return address The {tokenContractAddress} that is currently set for the resourceID.
*/
function _resourceIDToTokenContractAddress(bytes32 resourceID) external view returns (address);
}// The Licensed Work is (c) 2022 Sygma
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.11;
import "../interfaces/IERCHandler.sol";
/**
@title Function used across handler contracts.
@author ChainSafe Systems.
@notice This contract is intended to be used with the Bridge contract.
*/
contract ERCHandlerHelpers is IERCHandler {
address public immutable _bridgeAddress;
uint8 public constant defaultDecimals = 18;
struct Decimals {
bool isSet;
uint8 externalDecimals;
}
struct ERCTokenContractProperties {
bytes32 resourceID;
bool isWhitelisted;
bool isBurnable;
Decimals decimals;
}
error ContractAddressNotWhitelisted(address contractAddress);
// resourceID => token contract address
mapping (bytes32 => address) public _resourceIDToTokenContractAddress;
// token contract address => ERCTokenContractProperties
mapping (address => ERCTokenContractProperties) public _tokenContractAddressToTokenProperties;
modifier onlyBridge() {
_onlyBridge();
_;
}
/**
@param bridgeAddress Contract address of previously deployed Bridge.
*/
constructor(
address bridgeAddress
) {
_bridgeAddress = bridgeAddress;
}
function _onlyBridge() private view {
require(msg.sender == _bridgeAddress, "sender must be bridge contract");
}
/**
@notice First verifies {contractAddress} is whitelisted, then sets
{_tokenContractAddressToTokenProperties[contractAddress].isBurnable} to true.
@param contractAddress Address of contract to be used when making or executing deposits.
*/
function setBurnable(address contractAddress) external override onlyBridge{
_setBurnable(contractAddress);
}
function withdraw(bytes memory data) external virtual override {}
function _setResource(bytes32 resourceID, address contractAddress) internal {
_resourceIDToTokenContractAddress[resourceID] = contractAddress;
_tokenContractAddressToTokenProperties[contractAddress].resourceID = resourceID;
_tokenContractAddressToTokenProperties[contractAddress].isWhitelisted = true;
_tokenContractAddressToTokenProperties[contractAddress].isBurnable = false;
}
function _setBurnable(address contractAddress) internal {
if (!_tokenContractAddressToTokenProperties[contractAddress].isWhitelisted) revert ContractAddressNotWhitelisted(contractAddress);
_tokenContractAddressToTokenProperties[contractAddress].isBurnable = true;
}
/**
@notice First verifies {contractAddress} is whitelisted,
then sets {_tokenContractAddressToTokenProperties[contractAddress].decimals.externalDecimals} to it's decimals value and
{_tokenContractAddressToTokenProperties[contractAddress].decimals.isSet} to true.
@param contractAddress Address of contract to be used when making or executing deposits.
@param externalDecimals Decimal places of token that is transferred.
*/
function _setDecimals(address contractAddress, uint8 externalDecimals) internal {
if (!_tokenContractAddressToTokenProperties[contractAddress].isWhitelisted) revert ContractAddressNotWhitelisted(contractAddress);
_tokenContractAddressToTokenProperties[contractAddress].decimals = Decimals({
isSet: true,
externalDecimals: externalDecimals
});
}
/**
@notice Converts token amount based on decimal places difference between the nework
deposit is made on and bridge.
@param tokenAddress Address of contract to be used when executing proposals.
@param amount Decimals value to be set for {contractAddress}.
*/
function convertToExternalBalance(address tokenAddress, uint256 amount) internal view returns(uint256) {
Decimals memory decimals = _tokenContractAddressToTokenProperties[tokenAddress].decimals;
if (!decimals.isSet) {
return amount;
} else if (decimals.externalDecimals >= defaultDecimals) {
return amount * (10 ** (decimals.externalDecimals - defaultDecimals));
} else {
return amount / (10 ** (defaultDecimals - decimals.externalDecimals));
}
}
/**
@notice Converts token amount based on decimal places difference between the bridge and nework
deposit is executed on.
@param tokenAddress Address of contract to be used when executing proposals.
@param amount Decimals value to be set for {contractAddress}.
*/
function convertToInternalBalance(address tokenAddress, uint256 amount) internal view returns(bytes memory) {
Decimals memory decimals = _tokenContractAddressToTokenProperties[tokenAddress].decimals;
uint256 convertedBalance;
if (!decimals.isSet) {
return "";
} else if (decimals.externalDecimals >= defaultDecimals) {
convertedBalance = amount / (10 ** (decimals.externalDecimals - defaultDecimals));
} else {
convertedBalance = amount * (10 ** (defaultDecimals - decimals.externalDecimals));
}
return abi.encodePacked(convertedBalance);
}
}// The Licensed Work is (c) 2022 Sygma
// SPDX-License-Identifier: BUSL-1.1
pragma solidity 0.8.11;
import "@openzeppelin/contracts/token/ERC20/IERC20.sol";
import "@openzeppelin/contracts/token/ERC20/presets/ERC20PresetMinterPauser.sol";
import "@openzeppelin/contracts/token/ERC20/extensions/ERC20Burnable.sol";
/**
@title Manages deposited ERC20s.
@author ChainSafe Systems.
@notice This contract is intended to be used with ERC20Handler contract.
*/
contract ERC20Safe {
/**
@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) virtual 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) virtual 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) virtual 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) virtual 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) internal {
_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 {
uint256 tokenSize;
assembly {
tokenSize := extcodesize(token)
}
require(tokenSize > 0, "ERC20: not a contract");
(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");
}
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/structs/EnumerableSet.sol)
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.
*/
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) {
return _values(set._inner);
}
// 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;
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 on the set. O(1).
*/
function length(UintSet storage set) internal view returns (uint256) {
return _length(set._inner);
}
/**
* @dev Returns the value stored at position `index` in the set. O(1).
*
* Note that there are no guarantees on the ordering of values inside the
* array, and it may change when more values are added or removed.
*
* Requirements:
*
* - `index` must be strictly less than {length}.
*/
function at(UintSet storage set, uint256 index) internal view returns (uint256) {
return uint256(_at(set._inner, index));
}
/**
* @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;
assembly {
result := store
}
return result;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/IERC165.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC165 standard, as defined in the
* https://eips.ethereum.org/EIPS/eip-165[EIP].
*
* Implementers can declare support of contract interfaces, which can then be
* queried by others ({ERC165Checker}).
*
* For an implementation, see {ERC165}.
*/
interface IERC165 {
/**
* @dev Returns true if this contract implements the interface defined by
* `interfaceId`. See the corresponding
* https://eips.ethereum.org/EIPS/eip-165#how-interfaces-are-identified[EIP section]
* to learn more about how these ids are created.
*
* This function call must use less than 30 000 gas.
*/
function supportsInterface(bytes4 interfaceId) external view returns (bool);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/introspection/ERC165.sol)
pragma solidity ^0.8.0;
import "./IERC165.sol";
/**
* @dev Implementation of the {IERC165} interface.
*
* Contracts that want to implement ERC165 should inherit from this contract and override {supportsInterface} to check
* for the additional interface id that will be supported. For example:
*
* ```solidity
* function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
* return interfaceId == type(MyInterface).interfaceId || super.supportsInterface(interfaceId);
* }
* ```
*
* Alternatively, {ERC165Storage} provides an easier to use but more expensive implementation.
*/
abstract contract ERC165 is IERC165 {
/**
* @dev See {IERC165-supportsInterface}.
*/
function supportsInterface(bytes4 interfaceId) public view virtual override returns (bool) {
return interfaceId == type(IERC165).interfaceId;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Strings.sol)
pragma solidity ^0.8.0;
/**
* @dev String operations.
*/
library Strings {
bytes16 private constant _HEX_SYMBOLS = "0123456789abcdef";
/**
* @dev Converts a `uint256` to its ASCII `string` decimal representation.
*/
function toString(uint256 value) internal pure returns (string memory) {
// Inspired by OraclizeAPI's implementation - MIT licence
// https://github.com/oraclize/ethereum-api/blob/b42146b063c7d6ee1358846c198246239e9360e8/oraclizeAPI_0.4.25.sol
if (value == 0) {
return "0";
}
uint256 temp = value;
uint256 digits;
while (temp != 0) {
digits++;
temp /= 10;
}
bytes memory buffer = new bytes(digits);
while (value != 0) {
digits -= 1;
buffer[digits] = bytes1(uint8(48 + uint256(value % 10)));
value /= 10;
}
return string(buffer);
}
/**
* @dev Converts a `uint256` to its ASCII `string` hexadecimal representation.
*/
function toHexString(uint256 value) internal pure returns (string memory) {
if (value == 0) {
return "0x00";
}
uint256 temp = value;
uint256 length = 0;
while (temp != 0) {
length++;
temp >>= 8;
}
return toHexString(value, length);
}
/**
* @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] = _HEX_SYMBOLS[value & 0xf];
value >>= 4;
}
require(value == 0, "Strings: hex length insufficient");
return string(buffer);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (utils/Context.sol)
pragma solidity ^0.8.0;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/presets/ERC20PresetMinterPauser.sol)
pragma solidity ^0.8.0;
import "../ERC20.sol";
import "../extensions/ERC20Burnable.sol";
import "../extensions/ERC20Pausable.sol";
import "../../../access/AccessControlEnumerable.sol";
import "../../../utils/Context.sol";
/**
* @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);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/IERC20Metadata.sol)
pragma solidity ^0.8.0;
import "../IERC20.sol";
/**
* @dev Interface for the optional metadata functions from the ERC20 standard.
*
* _Available since v4.1._
*/
interface IERC20Metadata is IERC20 {
/**
* @dev Returns the name of the token.
*/
function name() external view returns (string memory);
/**
* @dev Returns the symbol of the token.
*/
function symbol() external view returns (string memory);
/**
* @dev Returns the decimals places of the token.
*/
function decimals() external view returns (uint8);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (token/ERC20/extensions/ERC20Pausable.sol)
pragma solidity ^0.8.0;
import "../ERC20.sol";
import "../../../security/Pausable.sol";
/**
* @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");
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/extensions/ERC20Burnable.sol)
pragma solidity ^0.8.0;
import "../ERC20.sol";
import "../../../utils/Context.sol";
/**
* @dev Extension of {ERC20} that allows token holders to destroy both their own
* tokens and those that they have an allowance for, in a way that can be
* recognized off-chain (via event analysis).
*/
abstract contract ERC20Burnable is Context, ERC20 {
/**
* @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);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/IERC20.sol)
pragma solidity ^0.8.0;
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `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);
/**
* @dev Emitted when `value` tokens are moved from one account (`from`) to
* another (`to`).
*
* Note that `value` may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);
/**
* @dev Emitted when the allowance of a `spender` for an `owner` is set by
* a call to {approve}. `value` is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (token/ERC20/ERC20.sol)
pragma solidity ^0.8.0;
import "./IERC20.sol";
import "./extensions/IERC20Metadata.sol";
import "../../utils/Context.sol";
/**
* @dev Implementation of the {IERC20} interface.
*
* This implementation is agnostic to the way tokens are created. This means
* that a supply mechanism has to be added in a derived contract using {_mint}.
* For a generic mechanism see {ERC20PresetMinterPauser}.
*
* TIP: For a detailed writeup see our guide
* https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How
* to implement supply mechanisms].
*
* We have followed general OpenZeppelin 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, _allowances[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 = _allowances[owner][spender];
require(currentAllowance >= subtractedValue, "ERC20: decreased allowance below zero");
unchecked {
_approve(owner, spender, currentAllowance - subtractedValue);
}
return true;
}
/**
* @dev Moves `amount` of tokens from `sender` to `recipient`.
*
* This internal function is equivalent to {transfer}, and can be used to
* e.g. implement automatic token fees, slashing mechanisms, etc.
*
* Emits a {Transfer} event.
*
* Requirements:
*
* - `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;
}
_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;
_balances[account] += amount;
emit Transfer(address(0), account, amount);
_afterTokenTransfer(address(0), account, amount);
}
/**
* @dev Destroys `amount` tokens from `account`, reducing the
* total supply.
*
* Emits a {Transfer} event with `to` set to the zero address.
*
* Requirements:
*
* - `account` cannot be the zero address.
* - `account` must have at least `amount` tokens.
*/
function _burn(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: burn from the zero address");
_beforeTokenTransfer(account, address(0), amount);
uint256 accountBalance = _balances[account];
require(accountBalance >= amount, "ERC20: burn amount exceeds balance");
unchecked {
_balances[account] = accountBalance - amount;
}
_totalSupply -= amount;
emit Transfer(account, address(0), amount);
_afterTokenTransfer(account, address(0), amount);
}
/**
* @dev Sets `amount` as the allowance of `spender` over the `owner` s tokens.
*
* This internal function is equivalent to `approve`, and can be used to
* e.g. set automatic allowances for certain subsystems, etc.
*
* Emits an {Approval} event.
*
* Requirements:
*
* - `owner` cannot be the zero address.
* - `spender` cannot be the zero address.
*/
function _approve(
address owner,
address spender,
uint256 amount
) internal virtual {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");
_allowances[owner][spender] = amount;
emit Approval(owner, spender, amount);
}
/**
* @dev Spend `amount` form the allowance of `owner` toward `spender`.
*
* 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 {}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (security/Pausable.sol)
pragma solidity ^0.8.0;
import "../utils/Context.sol";
/**
* @dev Contract module which allows children to implement an emergency stop
* mechanism that can be triggered by an authorized account.
*
* This module is used through inheritance. It will make available the
* modifiers `whenNotPaused` and `whenPaused`, which can be applied to
* the functions of your contract. Note that they will not be pausable by
* simply including this module, only once the modifiers are put in place.
*/
abstract contract Pausable is Context {
/**
* @dev Emitted when the pause is triggered by `account`.
*/
event Paused(address account);
/**
* @dev Emitted when the pause is lifted by `account`.
*/
event Unpaused(address account);
bool private _paused;
/**
* @dev Initializes the contract in unpaused state.
*/
constructor() {
_paused = false;
}
/**
* @dev Returns true if the contract is paused, and false otherwise.
*/
function paused() public view virtual returns (bool) {
return _paused;
}
/**
* @dev Modifier to make a function callable only when the contract is not paused.
*
* Requirements:
*
* - The contract must not be paused.
*/
modifier whenNotPaused() {
require(!paused(), "Pausable: paused");
_;
}
/**
* @dev Modifier to make a function callable only when the contract is paused.
*
* Requirements:
*
* - The contract must be paused.
*/
modifier whenPaused() {
require(paused(), "Pausable: not paused");
_;
}
/**
* @dev Triggers stopped state.
*
* Requirements:
*
* - The contract must not be paused.
*/
function _pause() internal virtual whenNotPaused {
_paused = true;
emit Paused(_msgSender());
}
/**
* @dev Returns to normal state.
*
* Requirements:
*
* - The contract must be paused.
*/
function _unpause() internal virtual whenPaused {
_paused = false;
emit Unpaused(_msgSender());
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (access/IAccessControlEnumerable.sol)
pragma solidity ^0.8.0;
import "./IAccessControl.sol";
/**
* @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);
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts v4.4.1 (access/IAccessControl.sol)
pragma solidity ^0.8.0;
/**
* @dev External interface of AccessControl declared to support ERC165 detection.
*/
interface IAccessControl {
/**
* @dev Emitted when `newAdminRole` is set as ``role``'s admin role, replacing `previousAdminRole`
*
* `DEFAULT_ADMIN_ROLE` is the starting admin for all roles, despite
* {RoleAdminChanged} not being emitted signaling this.
*
* _Available since v3.1._
*/
event RoleAdminChanged(bytes32 indexed role, bytes32 indexed previousAdminRole, bytes32 indexed newAdminRole);
/**
* @dev Emitted when `account` is granted `role`.
*
* `sender` is the account that originated the contract call, an admin role
* bearer except when using {AccessControl-_setupRole}.
*/
event RoleGranted(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Emitted when `account` is revoked `role`.
*
* `sender` is the account that originated the contract call:
* - if using `revokeRole`, it is the admin role bearer
* - if using `renounceRole`, it is the role bearer (i.e. `account`)
*/
event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);
/**
* @dev Returns `true` if `account` has been granted `role`.
*/
function hasRole(bytes32 role, address account) external view returns (bool);
/**
* @dev Returns the admin role that controls `role`. See {grantRole} and
* {revokeRole}.
*
* To change a role's admin, use {AccessControl-_setRoleAdmin}.
*/
function getRoleAdmin(bytes32 role) external view returns (bytes32);
/**
* @dev Grants `role` to `account`.
*
* If `account` had not been already granted `role`, emits a {RoleGranted}
* event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function grantRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from `account`.
*
* If `account` had been granted `role`, emits a {RoleRevoked} event.
*
* Requirements:
*
* - the caller must have ``role``'s admin role.
*/
function revokeRole(bytes32 role, address account) external;
/**
* @dev Revokes `role` from the calling account.
*
* Roles are often managed via {grantRole} and {revokeRole}: this function's
* purpose is to provide a mechanism for accounts to lose their privileges
* if they are compromised (such as when a trusted device is misplaced).
*
* If the calling account had been granted `role`, emits a {RoleRevoked}
* event.
*
* Requirements:
*
* - the caller must be `account`.
*/
function renounceRole(bytes32 role, address account) external;
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (access/AccessControlEnumerable.sol)
pragma solidity ^0.8.0;
import "./IAccessControlEnumerable.sol";
import "./AccessControl.sol";
import "../utils/structs/EnumerableSet.sol";
/**
* @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);
}
}// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v4.5.0) (access/AccessControl.sol)
pragma solidity ^0.8.0;
import "./IAccessControl.sol";
import "../utils/Context.sol";
import "../utils/Strings.sol";
import "../utils/introspection/ERC165.sol";
/**
* @dev Contract module that allows children to implement role-based access
* control mechanisms. This is a lightweight version that doesn't allow enumerating role
* members except through off-chain means by accessing the contract event logs. Some
* applications may benefit from on-chain enumerability, for those cases see
* {AccessControlEnumerable}.
*
* Roles are referred to by their `bytes32` identifier. These should be exposed
* in the external API and be unique. The best way to achieve this is by
* using `public constant` hash digests:
*
* ```
* 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, _msgSender());
_;
}
/**
* @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 `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(uint160(account), 20),
" 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.
*/
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.
*/
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`.
*/
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.
*
* [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.
*/
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.
*/
function _revokeRole(bytes32 role, address account) internal virtual {
if (hasRole(role, account)) {
_roles[role].members[account] = false;
emit RoleRevoked(role, account, _msgSender());
}
}
}{
"remappings": [],
"optimizer": {
"enabled": true,
"runs": 200
},
"evmVersion": "london",
"libraries": {},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"address","name":"bridgeAddress","type":"address"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[{"internalType":"address","name":"contractAddress","type":"address"}],"name":"ContractAddressNotWhitelisted","type":"error"},{"inputs":[],"name":"_bridgeAddress","outputs":[{"internalType":"address","name":"","type":"address"}],"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":"_tokenContractAddressToTokenProperties","outputs":[{"internalType":"bytes32","name":"resourceID","type":"bytes32"},{"internalType":"bool","name":"isWhitelisted","type":"bool"},{"internalType":"bool","name":"isBurnable","type":"bool"},{"components":[{"internalType":"bool","name":"isSet","type":"bool"},{"internalType":"uint8","name":"externalDecimals","type":"uint8"}],"internalType":"struct ERCHandlerHelpers.Decimals","name":"decimals","type":"tuple"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"defaultDecimals","outputs":[{"internalType":"uint8","name":"","type":"uint8"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32","name":"resourceID","type":"bytes32"},{"internalType":"address","name":"depositor","type":"address"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"deposit","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes32","name":"resourceID","type":"bytes32"},{"internalType":"bytes","name":"data","type":"bytes"}],"name":"executeProposal","outputs":[{"internalType":"bytes","name":"","type":"bytes"}],"stateMutability":"nonpayable","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"},{"internalType":"bytes","name":"args","type":"bytes"}],"name":"setResource","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"bytes","name":"data","type":"bytes"}],"name":"withdraw","outputs":[],"stateMutability":"nonpayable","type":"function"}]Contract Creation Code
60a060405234801561001057600080fd5b506040516110d83803806110d883398101604081905261002f91610040565b6001600160a01b0316608052610070565b60006020828403121561005257600080fd5b81516001600160a01b038116811461006957600080fd5b9392505050565b60805161104661009260003960008181610125015261054b01526110466000f3fe608060405234801561001057600080fd5b50600436106100935760003560e01c8063318c136e11610066578063318c136e14610120578063ac607c2114610147578063b07e54bb146101dc578063e248cff2146101fc578063fa8675b01461020f57600080fd5b806307b7ed99146100985780630968f264146100ad5780630a6d55d8146100c057806330f08abd14610106575b600080fd5b6100ab6100a6366004610b3a565b610222565b005b6100ab6100bb366004610b74565b610236565b6100e96100ce366004610c25565b6000602081905290815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b61010e601281565b60405160ff90911681526020016100fd565b6100e97f000000000000000000000000000000000000000000000000000000000000000081565b6101a4610155366004610b3a565b600160208181526000928352604092839020805492810154845180860190955260029091015460ff81811615158652610100918290048116938601939093529293828216939091049091169084565b6040805194855292151560208086019190915291151592840192909252815115156060840152015160ff16608082015260a0016100fd565b6101ef6101ea366004610c87565b61026f565b6040516100fd9190610d0f565b6101ef61020a366004610d42565b61035c565b6100ab61021d366004610c87565b6104c9565b61022a610540565b610233816105ba565b50565b61023e610540565b6000806000838060200190518101906102579190610d8e565b9194509250905061026983838361062c565b50505050565b6060610279610540565b600061028783850185610c25565b600087815260208181526040808320546001600160a01b0316808452600192839052922001549192509060ff166102e1576040516325df77c560e11b81526001600160a01b03821660048201526024015b60405180910390fd5b6001600160a01b03811660009081526001602081905260409091200154610100900460ff161561031b57610316818784610638565b610327565b610327818730856106a4565b61033181836106b1565b6040516020016103419190610dd1565b60405160208183030381529060405292505050949350505050565b6060610366610540565b600080606061037785870187610ded565b90935091508560408661038a8583610e25565b9261039793929190610e3d565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201829052508b81526020818152604080832054828801516001600160a01b039091168085526001938490529190932090910154959650909490935060ff16915061042c9050576040516325df77c560e11b81526001600160a01b03821660048201526024016102d8565b6001600160a01b03811660009081526001602081905260409091200154610100900460ff16156104725761046d818360601c610468848961079f565b610851565b610489565b610489818360601c610484848961079f565b61062c565b604080516001600160a01b03929092166020830152606092831c828201528282019590955284518082039092018252608001909352509095945050505050565b6104d1610540565b60008481526020818152604080832080546001600160a01b0319166001600160a01b03881690811790915583526001918290529091208581558101805461ffff19169091179055801561026957600061052a8284610e67565b60f81c90506105398482610889565b5050505050565b336001600160a01b037f000000000000000000000000000000000000000000000000000000000000000016146105b85760405162461bcd60e51b815260206004820152601e60248201527f73656e646572206d7573742062652062726964676520636f6e7472616374000060448201526064016102d8565b565b6001600160a01b0381166000908152600160208190526040909120015460ff16610602576040516325df77c560e11b81526001600160a01b03821660048201526024016102d8565b6001600160a01b0316600090815260016020819052604090912001805461ff001916610100179055565b82610269818484610933565b60405163079cc67960e41b81526001600160a01b038381166004830152602482018390528491908216906379cc6790906044015b600060405180830381600087803b15801561068657600080fd5b505af115801561069a573d6000803e3d6000fd5b5050505050505050565b836105398185858561099b565b6001600160a01b038216600090815260016020908152604080832081518083019092526002015460ff808216151580845261010090920416928201929092526060929091610712576040518060200160405280600081525092505050610799565b601260ff16826020015160ff161061075157601282602001516107359190610e97565b61074090600a610f9e565b61074a9085610fad565b9050610779565b6020820151610761906012610e97565b61076c90600a610f9e565b6107769085610fcf565b90505b604080516020810183905201604051602081830303815290604052925050505b92915050565b6001600160a01b038216600090815260016020908152604080832081518083019092526002015460ff80821615158084526101009092041692820192909252906107ec5782915050610799565b601260ff16816020015160ff161061082c576012816020015161080f9190610e97565b61081a90600a610f9e565b6108249084610fcf565b915050610799565b602081015161083c906012610e97565b61084790600a610f9e565b6108249084610fad565b6040516340c10f1960e01b81526001600160a01b038381166004830152602482018390528491908216906340c10f199060440161066c565b6001600160a01b0382166000908152600160208190526040909120015460ff166108d1576040516325df77c560e11b81526001600160a01b03831660048201526024016102d8565b604080518082018252600180825260ff93841660208084019182526001600160a01b039690961660009081529190955291909120905160029091018054935161ffff1990941691151561ff001916919091176101009390921692909202179055565b6040516001600160a01b03831660248201526044810182905261099690849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526109d3565b505050565b6040516001600160a01b03808516602483015283166044820152606481018290526102699085906323b872dd60e01b9060840161095f565b813b80610a1a5760405162461bcd60e51b8152602060048201526015602482015274115490cc8c0e881b9bdd08184818dbdb9d1c9858dd605a1b60448201526064016102d8565b600080846001600160a01b031684604051610a359190610dd1565b6000604051808303816000865af19150503d8060008114610a72576040519150601f19603f3d011682016040523d82523d6000602084013e610a77565b606091505b509150915081610abe5760405162461bcd60e51b8152602060048201526012602482015271115490cc8c0e8818d85b1b0819985a5b195960721b60448201526064016102d8565b8051156105395780806020019051810190610ad99190610fee565b6105395760405162461bcd60e51b815260206004820181905260248201527f45524332303a206f7065726174696f6e20646964206e6f74207375636365656460448201526064016102d8565b6001600160a01b038116811461023357600080fd5b600060208284031215610b4c57600080fd5b8135610b5781610b25565b9392505050565b634e487b7160e01b600052604160045260246000fd5b600060208284031215610b8657600080fd5b813567ffffffffffffffff80821115610b9e57600080fd5b818401915084601f830112610bb257600080fd5b813581811115610bc457610bc4610b5e565b604051601f8201601f19908116603f01168101908382118183101715610bec57610bec610b5e565b81604052828152876020848701011115610c0557600080fd5b826020860160208301376000928101602001929092525095945050505050565b600060208284031215610c3757600080fd5b5035919050565b60008083601f840112610c5057600080fd5b50813567ffffffffffffffff811115610c6857600080fd5b602083019150836020828501011115610c8057600080fd5b9250929050565b60008060008060608587031215610c9d57600080fd5b843593506020850135610caf81610b25565b9250604085013567ffffffffffffffff811115610ccb57600080fd5b610cd787828801610c3e565b95989497509550505050565b60005b83811015610cfe578181015183820152602001610ce6565b838111156102695750506000910152565b6020815260008251806020840152610d2e816040850160208701610ce3565b601f01601f19169190910160400192915050565b600080600060408486031215610d5757600080fd5b83359250602084013567ffffffffffffffff811115610d7557600080fd5b610d8186828701610c3e565b9497909650939450505050565b600080600060608486031215610da357600080fd5b8351610dae81610b25565b6020850151909350610dbf81610b25565b80925050604084015190509250925092565b60008251610de3818460208701610ce3565b9190910192915050565b60008060408385031215610e0057600080fd5b50508035926020909101359150565b634e487b7160e01b600052601160045260246000fd5b60008219821115610e3857610e38610e0f565b500190565b60008085851115610e4d57600080fd5b83861115610e5a57600080fd5b5050820193919092039150565b6001600160f81b03198135818116916001851015610e8f5780818660010360031b1b83161692505b505092915050565b600060ff821660ff841680821015610eb157610eb1610e0f565b90039392505050565b600181815b80851115610ef5578160001904821115610edb57610edb610e0f565b80851615610ee857918102915b93841c9390800290610ebf565b509250929050565b600082610f0c57506001610799565b81610f1957506000610799565b8160018114610f2f5760028114610f3957610f55565b6001915050610799565b60ff841115610f4a57610f4a610e0f565b50506001821b610799565b5060208310610133831016604e8410600b8410161715610f78575081810a610799565b610f828383610eba565b8060001904821115610f9657610f96610e0f565b029392505050565b6000610b5760ff841683610efd565b600082610fca57634e487b7160e01b600052601260045260246000fd5b500490565b6000816000190483118215151615610fe957610fe9610e0f565b500290565b60006020828403121561100057600080fd5b81518015158114610b5757600080fdfea26469706673582212201644e0293e879e2c200d5ba493d7773d21d6eaa59c9bff6310db0d588c11816564736f6c634300080b00330000000000000000000000004d878e8fb90178588cda4cf1dccdc9a6d2757089
Deployed Bytecode
0x608060405234801561001057600080fd5b50600436106100935760003560e01c8063318c136e11610066578063318c136e14610120578063ac607c2114610147578063b07e54bb146101dc578063e248cff2146101fc578063fa8675b01461020f57600080fd5b806307b7ed99146100985780630968f264146100ad5780630a6d55d8146100c057806330f08abd14610106575b600080fd5b6100ab6100a6366004610b3a565b610222565b005b6100ab6100bb366004610b74565b610236565b6100e96100ce366004610c25565b6000602081905290815260409020546001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b61010e601281565b60405160ff90911681526020016100fd565b6100e97f0000000000000000000000004d878e8fb90178588cda4cf1dccdc9a6d275708981565b6101a4610155366004610b3a565b600160208181526000928352604092839020805492810154845180860190955260029091015460ff81811615158652610100918290048116938601939093529293828216939091049091169084565b6040805194855292151560208086019190915291151592840192909252815115156060840152015160ff16608082015260a0016100fd565b6101ef6101ea366004610c87565b61026f565b6040516100fd9190610d0f565b6101ef61020a366004610d42565b61035c565b6100ab61021d366004610c87565b6104c9565b61022a610540565b610233816105ba565b50565b61023e610540565b6000806000838060200190518101906102579190610d8e565b9194509250905061026983838361062c565b50505050565b6060610279610540565b600061028783850185610c25565b600087815260208181526040808320546001600160a01b0316808452600192839052922001549192509060ff166102e1576040516325df77c560e11b81526001600160a01b03821660048201526024015b60405180910390fd5b6001600160a01b03811660009081526001602081905260409091200154610100900460ff161561031b57610316818784610638565b610327565b610327818730856106a4565b61033181836106b1565b6040516020016103419190610dd1565b60405160208183030381529060405292505050949350505050565b6060610366610540565b600080606061037785870187610ded565b90935091508560408661038a8583610e25565b9261039793929190610e3d565b8080601f01602080910402602001604051908101604052809392919081815260200183838082843760009201829052508b81526020818152604080832054828801516001600160a01b039091168085526001938490529190932090910154959650909490935060ff16915061042c9050576040516325df77c560e11b81526001600160a01b03821660048201526024016102d8565b6001600160a01b03811660009081526001602081905260409091200154610100900460ff16156104725761046d818360601c610468848961079f565b610851565b610489565b610489818360601c610484848961079f565b61062c565b604080516001600160a01b03929092166020830152606092831c828201528282019590955284518082039092018252608001909352509095945050505050565b6104d1610540565b60008481526020818152604080832080546001600160a01b0319166001600160a01b03881690811790915583526001918290529091208581558101805461ffff19169091179055801561026957600061052a8284610e67565b60f81c90506105398482610889565b5050505050565b336001600160a01b037f0000000000000000000000004d878e8fb90178588cda4cf1dccdc9a6d275708916146105b85760405162461bcd60e51b815260206004820152601e60248201527f73656e646572206d7573742062652062726964676520636f6e7472616374000060448201526064016102d8565b565b6001600160a01b0381166000908152600160208190526040909120015460ff16610602576040516325df77c560e11b81526001600160a01b03821660048201526024016102d8565b6001600160a01b0316600090815260016020819052604090912001805461ff001916610100179055565b82610269818484610933565b60405163079cc67960e41b81526001600160a01b038381166004830152602482018390528491908216906379cc6790906044015b600060405180830381600087803b15801561068657600080fd5b505af115801561069a573d6000803e3d6000fd5b5050505050505050565b836105398185858561099b565b6001600160a01b038216600090815260016020908152604080832081518083019092526002015460ff808216151580845261010090920416928201929092526060929091610712576040518060200160405280600081525092505050610799565b601260ff16826020015160ff161061075157601282602001516107359190610e97565b61074090600a610f9e565b61074a9085610fad565b9050610779565b6020820151610761906012610e97565b61076c90600a610f9e565b6107769085610fcf565b90505b604080516020810183905201604051602081830303815290604052925050505b92915050565b6001600160a01b038216600090815260016020908152604080832081518083019092526002015460ff80821615158084526101009092041692820192909252906107ec5782915050610799565b601260ff16816020015160ff161061082c576012816020015161080f9190610e97565b61081a90600a610f9e565b6108249084610fcf565b915050610799565b602081015161083c906012610e97565b61084790600a610f9e565b6108249084610fad565b6040516340c10f1960e01b81526001600160a01b038381166004830152602482018390528491908216906340c10f199060440161066c565b6001600160a01b0382166000908152600160208190526040909120015460ff166108d1576040516325df77c560e11b81526001600160a01b03831660048201526024016102d8565b604080518082018252600180825260ff93841660208084019182526001600160a01b039690961660009081529190955291909120905160029091018054935161ffff1990941691151561ff001916919091176101009390921692909202179055565b6040516001600160a01b03831660248201526044810182905261099690849063a9059cbb60e01b906064015b60408051601f198184030181529190526020810180516001600160e01b03166001600160e01b0319909316929092179091526109d3565b505050565b6040516001600160a01b03808516602483015283166044820152606481018290526102699085906323b872dd60e01b9060840161095f565b813b80610a1a5760405162461bcd60e51b8152602060048201526015602482015274115490cc8c0e881b9bdd08184818dbdb9d1c9858dd605a1b60448201526064016102d8565b600080846001600160a01b031684604051610a359190610dd1565b6000604051808303816000865af19150503d8060008114610a72576040519150601f19603f3d011682016040523d82523d6000602084013e610a77565b606091505b509150915081610abe5760405162461bcd60e51b8152602060048201526012602482015271115490cc8c0e8818d85b1b0819985a5b195960721b60448201526064016102d8565b8051156105395780806020019051810190610ad99190610fee565b6105395760405162461bcd60e51b815260206004820181905260248201527f45524332303a206f7065726174696f6e20646964206e6f74207375636365656460448201526064016102d8565b6001600160a01b038116811461023357600080fd5b600060208284031215610b4c57600080fd5b8135610b5781610b25565b9392505050565b634e487b7160e01b600052604160045260246000fd5b600060208284031215610b8657600080fd5b813567ffffffffffffffff80821115610b9e57600080fd5b818401915084601f830112610bb257600080fd5b813581811115610bc457610bc4610b5e565b604051601f8201601f19908116603f01168101908382118183101715610bec57610bec610b5e565b81604052828152876020848701011115610c0557600080fd5b826020860160208301376000928101602001929092525095945050505050565b600060208284031215610c3757600080fd5b5035919050565b60008083601f840112610c5057600080fd5b50813567ffffffffffffffff811115610c6857600080fd5b602083019150836020828501011115610c8057600080fd5b9250929050565b60008060008060608587031215610c9d57600080fd5b843593506020850135610caf81610b25565b9250604085013567ffffffffffffffff811115610ccb57600080fd5b610cd787828801610c3e565b95989497509550505050565b60005b83811015610cfe578181015183820152602001610ce6565b838111156102695750506000910152565b6020815260008251806020840152610d2e816040850160208701610ce3565b601f01601f19169190910160400192915050565b600080600060408486031215610d5757600080fd5b83359250602084013567ffffffffffffffff811115610d7557600080fd5b610d8186828701610c3e565b9497909650939450505050565b600080600060608486031215610da357600080fd5b8351610dae81610b25565b6020850151909350610dbf81610b25565b80925050604084015190509250925092565b60008251610de3818460208701610ce3565b9190910192915050565b60008060408385031215610e0057600080fd5b50508035926020909101359150565b634e487b7160e01b600052601160045260246000fd5b60008219821115610e3857610e38610e0f565b500190565b60008085851115610e4d57600080fd5b83861115610e5a57600080fd5b5050820193919092039150565b6001600160f81b03198135818116916001851015610e8f5780818660010360031b1b83161692505b505092915050565b600060ff821660ff841680821015610eb157610eb1610e0f565b90039392505050565b600181815b80851115610ef5578160001904821115610edb57610edb610e0f565b80851615610ee857918102915b93841c9390800290610ebf565b509250929050565b600082610f0c57506001610799565b81610f1957506000610799565b8160018114610f2f5760028114610f3957610f55565b6001915050610799565b60ff841115610f4a57610f4a610e0f565b50506001821b610799565b5060208310610133831016604e8410600b8410161715610f78575081810a610799565b610f828383610eba565b8060001904821115610f9657610f96610e0f565b029392505050565b6000610b5760ff841683610efd565b600082610fca57634e487b7160e01b600052601260045260246000fd5b500490565b6000816000190483118215151615610fe957610fe9610e0f565b500290565b60006020828403121561100057600080fd5b81518015158114610b5757600080fdfea26469706673582212201644e0293e879e2c200d5ba493d7773d21d6eaa59c9bff6310db0d588c11816564736f6c634300080b0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
0000000000000000000000004d878e8fb90178588cda4cf1dccdc9a6d2757089
-----Decoded View---------------
Arg [0] : bridgeAddress (address): 0x4D878E8Fb90178588Cda4cf1DCcdC9a6d2757089
-----Encoded View---------------
1 Constructor Arguments found :
Arg [0] : 0000000000000000000000004d878e8fb90178588cda4cf1dccdc9a6d2757089
Loading...
Loading
Loading...
Loading
Multichain Portfolio | 34 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|---|---|---|---|---|
| ETH | 100.00% | $0.049902 | 338,477,558.3127 | $16,890,673.27 |
Loading...
Loading
Loading...
Loading
Loading...
Loading
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.