Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
Latest 1 internal transaction
Advanced mode:
| Parent Transaction Hash | Method | Block |
From
|
|
To
|
||
|---|---|---|---|---|---|---|---|
| 0x60806040 | 15365242 | 1312 days ago | Contract Creation | 0 ETH |
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
Governance
Compiler Version
v0.7.6+commit.7338295f
Optimization Enabled:
Yes with 200 runs
Other Settings:
default evmVersion
Contract Source Code (Solidity Standard Json-Input format)
pragma solidity ^0.7.0;
// SPDX-License-Identifier: MIT OR Apache-2.0
import "./Config.sol";
import "./Utils.sol";
import "./NFTFactory.sol";
import "./TokenGovernance.sol";
/// @title Governance Contract
/// @author Matter Labs
contract Governance is Config {
/// @notice Token added to Franklin net
event NewToken(address indexed token, uint16 indexed tokenId);
/// @notice Default nft factory has set
event SetDefaultNFTFactory(address indexed factory);
/// @notice NFT factory registered new creator account
event NFTFactoryRegisteredCreator(
uint32 indexed creatorAccountId,
address indexed creatorAddress,
address factoryAddress
);
/// @notice Governor changed
event NewGovernor(address newGovernor);
/// @notice Token Governance changed
event NewTokenGovernance(TokenGovernance newTokenGovernance);
/// @notice Validator's status changed
event ValidatorStatusUpdate(address indexed validatorAddress, bool isActive);
event TokenPausedUpdate(address indexed token, bool paused);
/// @notice Address which will exercise governance over the network i.e. add tokens, change validator set, conduct upgrades
address public networkGovernor;
/// @notice Total number of ERC20 tokens registered in the network (excluding ETH, which is hardcoded as tokenId = 0)
uint16 public totalTokens;
/// @notice List of registered tokens by tokenId
mapping(uint16 => address) public tokenAddresses;
/// @notice List of registered tokens by address
mapping(address => uint16) public tokenIds;
/// @notice List of permitted validators
mapping(address => bool) public validators;
/// @notice Paused tokens list, deposits are impossible to create for paused tokens
mapping(uint16 => bool) public pausedTokens;
/// @notice Address that is authorized to add tokens to the Governance.
TokenGovernance public tokenGovernance;
/// @notice NFT Creator address to factory address mapping
mapping(uint32 => mapping(address => NFTFactory)) public nftFactories;
/// @notice Address which will be used if NFT token has no factories
NFTFactory public defaultFactory;
/// @notice Governance contract initialization. Can be external because Proxy contract intercepts illegal calls of this function.
/// @param initializationParameters Encoded representation of initialization parameters:
/// _networkGovernor The address of network governor
function initialize(bytes calldata initializationParameters) external {
address _networkGovernor = abi.decode(initializationParameters, (address));
networkGovernor = _networkGovernor;
}
/// @notice Governance contract upgrade. Can be external because Proxy contract intercepts illegal calls of this function.
/// @param upgradeParameters Encoded representation of upgrade parameters
// solhint-disable-next-line no-empty-blocks
function upgrade(bytes calldata upgradeParameters) external {}
/// @notice Change current governor
/// @param _newGovernor Address of the new governor
function changeGovernor(address _newGovernor) external {
require(_newGovernor != address(0), "1n");
requireGovernor(msg.sender);
if (networkGovernor != _newGovernor) {
networkGovernor = _newGovernor;
emit NewGovernor(_newGovernor);
}
}
/// @notice Change current token governance
/// @param _newTokenGovernance Address of the new token governor
function changeTokenGovernance(TokenGovernance _newTokenGovernance) external {
requireGovernor(msg.sender);
if (tokenGovernance != _newTokenGovernance) {
tokenGovernance = _newTokenGovernance;
emit NewTokenGovernance(_newTokenGovernance);
}
}
/// @notice Add token to the list of networks tokens
/// @param _token Token address
function addToken(address _token) external {
require(msg.sender == address(tokenGovernance), "1E");
require(tokenIds[_token] == 0, "1e"); // token exists
require(totalTokens < MAX_AMOUNT_OF_REGISTERED_TOKENS, "1f"); // no free identifiers for tokens
totalTokens++;
uint16 newTokenId = totalTokens; // it is not `totalTokens - 1` because tokenId = 0 is reserved for eth
tokenAddresses[newTokenId] = _token;
tokenIds[_token] = newTokenId;
emit NewToken(_token, newTokenId);
}
/// @notice Pause token deposits for the given token
/// @param _tokenAddr Token address
/// @param _tokenPaused Token paused status
function setTokenPaused(address _tokenAddr, bool _tokenPaused) external {
requireGovernor(msg.sender);
uint16 tokenId = this.validateTokenAddress(_tokenAddr);
if (pausedTokens[tokenId] != _tokenPaused) {
pausedTokens[tokenId] = _tokenPaused;
emit TokenPausedUpdate(_tokenAddr, _tokenPaused);
}
}
/// @notice Change validator status (active or not active)
/// @param _validator Validator address
/// @param _active Active flag
function setValidator(address _validator, bool _active) external {
requireGovernor(msg.sender);
if (validators[_validator] != _active) {
validators[_validator] = _active;
emit ValidatorStatusUpdate(_validator, _active);
}
}
/// @notice Check if specified address is is governor
/// @param _address Address to check
function requireGovernor(address _address) public view {
require(_address == networkGovernor, "1g"); // only by governor
}
/// @notice Checks if validator is active
/// @param _address Validator address
function requireActiveValidator(address _address) external view {
require(validators[_address], "1h"); // validator is not active
}
/// @notice Validate token id (must be less than or equal to total tokens amount)
/// @param _tokenId Token id
/// @return bool flag that indicates if token id is less than or equal to total tokens amount
function isValidTokenId(uint16 _tokenId) external view returns (bool) {
return _tokenId <= totalTokens;
}
/// @notice Validate token address
/// @param _tokenAddr Token address
/// @return tokens id
function validateTokenAddress(address _tokenAddr) external view returns (uint16) {
uint16 tokenId = tokenIds[_tokenAddr];
require(tokenId != 0, "1i"); // 0 is not a valid token
return tokenId;
}
function packRegisterNFTFactoryMsg(
uint32 _creatorAccountId,
address _creatorAddress,
address _factoryAddress
) internal pure returns (bytes memory) {
return
abi.encodePacked(
"\x19Ethereum Signed Message:\n141",
"\nCreator's account ID in zkSync: ",
Bytes.bytesToHexASCIIBytes(abi.encodePacked((_creatorAccountId))),
"\nCreator: ",
Bytes.bytesToHexASCIIBytes(abi.encodePacked((_creatorAddress))),
"\nFactory: ",
Bytes.bytesToHexASCIIBytes(abi.encodePacked((_factoryAddress)))
);
}
/// @notice Register creator corresponding to the factory
/// @param _creatorAccountId Creator's zkSync account ID
/// @param _creatorAddress NFT creator address
/// @param _signature Creator's signature
function registerNFTFactoryCreator(
uint32 _creatorAccountId,
address _creatorAddress,
bytes memory _signature
) external {
require(address(nftFactories[_creatorAccountId][_creatorAddress]) == address(0), "Q");
bytes32 messageHash = keccak256(packRegisterNFTFactoryMsg(_creatorAccountId, _creatorAddress, msg.sender));
address recoveredAddress = Utils.recoverAddressFromEthSignature(_signature, messageHash);
require(recoveredAddress == _creatorAddress, "ws");
nftFactories[_creatorAccountId][_creatorAddress] = NFTFactory(msg.sender);
emit NFTFactoryRegisteredCreator(_creatorAccountId, _creatorAddress, msg.sender);
}
/// @notice Set default factory for our contract. This factory will be used to mint an NFT token that has no factory
/// @param _factory Address of NFT factory
function setDefaultNFTFactory(address _factory) external {
requireGovernor(msg.sender);
require(address(_factory) != address(0), "mb1"); // Factory should be non zero
require(address(defaultFactory) == address(0), "mb2"); // NFTFactory is already set
defaultFactory = NFTFactory(_factory);
emit SetDefaultNFTFactory(_factory);
}
function getNFTFactory(uint32 _creatorAccountId, address _creatorAddress) external view returns (NFTFactory) {
NFTFactory _factory = nftFactories[_creatorAccountId][_creatorAddress];
// even if the factory is undefined or has been destroyed, the user can mint NFT
if (address(_factory) == address(0) || !isContract(address(_factory))) {
require(address(defaultFactory) != address(0), "fs"); // NFTFactory does not set
return defaultFactory;
} else {
return _factory;
}
}
/// @return whether the address is a contract or not
/// NOTE: for smart contracts that called `selfdestruct` will return a negative result
function isContract(address _address) internal view returns (bool) {
uint256 contractSize;
assembly {
contractSize := extcodesize(_address)
}
return contractSize != 0;
}
}pragma solidity ^0.7.0;
// SPDX-License-Identifier: MIT OR Apache-2.0
/// @title zkSync configuration constants
/// @author Matter Labs
contract Config {
/// @dev ERC20 tokens and ETH withdrawals gas limit, used only for complete withdrawals
uint256 internal constant WITHDRAWAL_GAS_LIMIT = 100000;
/// @dev NFT withdrawals gas limit, used only for complete withdrawals
uint256 internal constant WITHDRAWAL_NFT_GAS_LIMIT = 300000;
/// @dev Bytes in one chunk
uint8 internal constant CHUNK_BYTES = 10;
/// @dev zkSync address length
uint8 internal constant ADDRESS_BYTES = 20;
uint8 internal constant PUBKEY_HASH_BYTES = 20;
/// @dev Public key bytes length
uint8 internal constant PUBKEY_BYTES = 32;
/// @dev Ethereum signature r/s bytes length
uint8 internal constant ETH_SIGN_RS_BYTES = 32;
/// @dev Success flag bytes length
uint8 internal constant SUCCESS_FLAG_BYTES = 1;
/// @dev Max amount of tokens registered in the network (excluding ETH, which is hardcoded as tokenId = 0)
uint32 internal constant MAX_AMOUNT_OF_REGISTERED_TOKENS = 1023;
/// @dev Max account id that could be registered in the network
uint32 internal constant MAX_ACCOUNT_ID = 16777215;
/// @dev Expected average period of block creation
uint256 internal constant BLOCK_PERIOD = 15 seconds;
/// @dev ETH blocks verification expectation
/// @dev Blocks can be reverted if they are not verified for at least EXPECT_VERIFICATION_IN.
/// @dev If set to 0 validator can revert blocks at any time.
uint256 internal constant EXPECT_VERIFICATION_IN = 0 hours / BLOCK_PERIOD;
uint256 internal constant NOOP_BYTES = 1 * CHUNK_BYTES;
uint256 internal constant DEPOSIT_BYTES = 6 * CHUNK_BYTES;
uint256 internal constant MINT_NFT_BYTES = 5 * CHUNK_BYTES;
uint256 internal constant TRANSFER_TO_NEW_BYTES = 6 * CHUNK_BYTES;
uint256 internal constant PARTIAL_EXIT_BYTES = 6 * CHUNK_BYTES;
uint256 internal constant TRANSFER_BYTES = 2 * CHUNK_BYTES;
uint256 internal constant FORCED_EXIT_BYTES = 6 * CHUNK_BYTES;
uint256 internal constant WITHDRAW_NFT_BYTES = 10 * CHUNK_BYTES;
/// @dev Full exit operation length
uint256 internal constant FULL_EXIT_BYTES = 11 * CHUNK_BYTES;
/// @dev ChangePubKey operation length
uint256 internal constant CHANGE_PUBKEY_BYTES = 6 * CHUNK_BYTES;
/// @dev Expiration delta for priority request to be satisfied (in seconds)
/// @dev NOTE: Priority expiration should be > (EXPECT_VERIFICATION_IN * BLOCK_PERIOD)
/// @dev otherwise incorrect block with priority op could not be reverted.
uint256 internal constant PRIORITY_EXPIRATION_PERIOD = 14 days;
/// @dev Expiration delta for priority request to be satisfied (in ETH blocks)
uint256 internal constant PRIORITY_EXPIRATION =
PRIORITY_EXPIRATION_PERIOD/BLOCK_PERIOD;
/// @dev Maximum number of priority request to clear during verifying the block
/// @dev Cause deleting storage slots cost 5k gas per each slot it's unprofitable to clear too many slots
/// @dev Value based on the assumption of ~750k gas cost of verifying and 5 used storage slots per PriorityOperation structure
uint64 internal constant MAX_PRIORITY_REQUESTS_TO_DELETE_IN_VERIFY = 6;
/// @dev Reserved time for users to send full exit priority operation in case of an upgrade (in seconds)
uint256 internal constant MASS_FULL_EXIT_PERIOD = 5 days;
/// @dev Reserved time for users to withdraw funds from full exit priority operation in case of an upgrade (in seconds)
uint256 internal constant TIME_TO_WITHDRAW_FUNDS_FROM_FULL_EXIT = 2 days;
/// @dev Notice period before activation preparation status of upgrade mode (in seconds)
/// @dev NOTE: we must reserve for users enough time to send full exit operation, wait maximum time for processing this operation and withdraw funds from it.
uint256 internal constant UPGRADE_NOTICE_PERIOD =
MASS_FULL_EXIT_PERIOD+PRIORITY_EXPIRATION_PERIOD+TIME_TO_WITHDRAW_FUNDS_FROM_FULL_EXIT;
/// @dev Timestamp - seconds since unix epoch
uint256 internal constant COMMIT_TIMESTAMP_NOT_OLDER = 24 hours;
/// @dev Maximum available error between real commit block timestamp and analog used in the verifier (in seconds)
/// @dev Must be used cause miner's `block.timestamp` value can differ on some small value (as we know - 15 seconds)
uint256 internal constant COMMIT_TIMESTAMP_APPROXIMATION_DELTA = 15 minutes;
/// @dev Bit mask to apply for verifier public input before verifying.
uint256 internal constant INPUT_MASK = 14474011154664524427946373126085988481658748083205070504932198000989141204991;
/// @dev Auth fact reset timelock.
uint256 internal constant AUTH_FACT_RESET_TIMELOCK = 1 days;
/// @dev Max deposit of ERC20 token that is possible to deposit
uint128 internal constant MAX_DEPOSIT_AMOUNT = 20282409603651670423947251286015;
uint32 internal constant SPECIAL_ACCOUNT_ID = 16777215;
address internal constant SPECIAL_ACCOUNT_ADDRESS = address(0xFFfFfFffFFfffFFfFFfFFFFFffFFFffffFfFFFfF);
uint32 internal constant SPECIAL_NFT_TOKEN_ID = 2147483646;
uint32 internal constant MAX_FUNGIBLE_TOKEN_ID = 65535;
uint256 internal constant SECURITY_COUNCIL_MEMBERS_NUMBER = 15;
string internal constant name = "ZkSync";
string internal constant version = "1.0";
bytes32 internal constant EIP712_DOMAIN_TYPEHASH =
keccak256("EIP712Domain(string name,string version,uint256 chainId)");
bytes32 internal constant EIP712_CHANGEPUBKEY_TYPEHASH =
keccak256("ChangePubKey(bytes20 pubKeyHash,uint32 nonce,uint32 accountId)");
}pragma solidity ^0.7.0;
// SPDX-License-Identifier: MIT OR Apache-2.0
import "./IERC20.sol";
import "./Bytes.sol";
library Utils {
/// @notice Returns lesser of two values
function minU32(uint32 a, uint32 b) internal pure returns (uint32) {
return a < b ? a : b;
}
/// @notice Returns lesser of two values
function minU64(uint64 a, uint64 b) internal pure returns (uint64) {
return a < b ? a : b;
}
/// @notice Returns lesser of two values
function minU128(uint128 a, uint128 b) internal pure returns (uint128) {
return a < b ? a : b;
}
/// @notice Recovers signer's address from ethereum signature for given message
/// @param _signature 65 bytes concatenated. R (32) + S (32) + V (1)
/// @param _messageHash signed message hash.
/// @return address of the signer
/// NOTE: will revert if signature is invalid
function recoverAddressFromEthSignature(bytes memory _signature, bytes32 _messageHash)
internal
pure
returns (address)
{
require(_signature.length == 65, "P"); // incorrect signature length
bytes32 signR;
bytes32 signS;
uint8 signV;
assembly {
signR := mload(add(_signature, 32))
signS := mload(add(_signature, 64))
signV := byte(0, mload(add(_signature, 96)))
}
address recoveredAddress = ecrecover(_messageHash, signV, signR, signS);
require(recoveredAddress != address(0), "p4"); // invalid signature
return recoveredAddress;
}
/// @notice Returns new_hash = hash(old_hash + bytes)
function concatHash(bytes32 _hash, bytes memory _bytes) internal pure returns (bytes32) {
bytes32 result;
assembly {
let bytesLen := add(mload(_bytes), 32)
mstore(_bytes, _hash)
result := keccak256(_bytes, bytesLen)
}
return result;
}
function hashBytesToBytes20(bytes memory _bytes) internal pure returns (bytes20) {
return bytes20(uint160(uint256(keccak256(_bytes))));
}
function getChainId() internal pure returns (uint256) {
uint256 chainId;
assembly {
chainId := chainid()
}
return chainId;
}
}pragma solidity ^0.7.0;
// SPDX-License-Identifier: UNLICENSED
interface NFTFactory {
function mintNFTFromZkSync(
address creator,
address recipient,
uint32 creatorAccountId,
uint32 serialId,
bytes32 contentHash,
// Even though the token id can fit into the uint32, we still use
// the uint256 to preserve consistency with the ERC721 parent contract
uint256 tokenId
) external;
event MintNFTFromZkSync(
address indexed creator,
address indexed recipient,
uint32 creatorAccountId,
uint32 serialId,
bytes32 contentHash,
uint256 tokenId
);
}pragma solidity ^0.7.0;
// SPDX-License-Identifier: MIT OR Apache-2.0
import "./ReentrancyGuard.sol";
import "./Governance.sol";
import "./ITrustedTransfarableERC20.sol";
import "./Utils.sol";
/// @title Token Governance Contract
/// @author Matter Labs
/// @notice Contract is used to allow anyone to add new ERC20 tokens to zkSync given sufficient payment
contract TokenGovernance is ReentrancyGuard {
/// @notice Token lister added or removed (see `tokenLister`)
event TokenListerUpdate(address indexed tokenLister, bool isActive);
/// @notice Listing fee token set
event ListingFeeTokenUpdate(ITrustedTransfarableERC20 indexed newListingFeeToken, uint256 newListingFee);
/// @notice Listing fee set
event ListingFeeUpdate(uint256 newListingFee);
/// @notice Maximum number of listed tokens updated
event ListingCapUpdate(uint16 newListingCap);
/// @notice The treasury (the account which will receive the fee) was updated
event TreasuryUpdate(address newTreasury);
/// @notice zkSync governance contract
Governance public governance;
/// @notice Token used to collect listing fee for addition of new token to zkSync network
ITrustedTransfarableERC20 public listingFeeToken;
/// @notice Token listing fee
uint256 public listingFee;
/// @notice Max number of tokens that can be listed using this contract
uint16 public listingCap;
/// @notice Addresses that can list tokens without fee
mapping(address => bool) public tokenLister;
/// @notice Address that collects listing payments
address public treasury;
constructor(
Governance _governance,
ITrustedTransfarableERC20 _listingFeeToken,
uint256 _listingFee,
uint16 _listingCap,
address _treasury
) {
initializeReentrancyGuard();
governance = _governance;
listingFeeToken = _listingFeeToken;
listingFee = _listingFee;
listingCap = _listingCap;
treasury = _treasury;
address governor = governance.networkGovernor();
// We add zkSync governor as a first token lister.
tokenLister[governor] = true;
emit TokenListerUpdate(governor, true);
}
/// @notice Adds new ERC20 token to zkSync network.
/// @notice If caller is not present in the `tokenLister` map payment of `listingFee` in `listingFeeToken` should be made.
/// @notice NOTE: before calling this function make sure to approve `listingFeeToken` transfer for this contract.
function addToken(address _token) external nonReentrant {
require(_token != address(0), "z1"); // Token should have a non-zero address
require(_token != 0xaBEA9132b05A70803a4E85094fD0e1800777fBEF, "z2"); // Address of the token cannot be the same as the address of the main zksync contract
require(governance.totalTokens() < listingCap, "can't add more tokens"); // Impossible to add more tokens using this contract
if (!tokenLister[msg.sender] && listingFee > 0) {
// Collect fees
bool feeTransferOk = listingFeeToken.transferFrom(msg.sender, treasury, listingFee);
require(feeTransferOk, "fee transfer failed"); // Failed to receive payment for token addition.
}
governance.addToken(_token);
}
/// Governance functions (this contract is governed by zkSync governor)
/// @notice Set new listing token and fee
/// @notice Can be called only by zkSync governor
function setListingFeeToken(ITrustedTransfarableERC20 _newListingFeeToken, uint256 _newListingFee) external {
governance.requireGovernor(msg.sender);
listingFeeToken = _newListingFeeToken;
listingFee = _newListingFee;
emit ListingFeeTokenUpdate(_newListingFeeToken, _newListingFee);
}
/// @notice Set new listing fee
/// @notice Can be called only by zkSync governor
function setListingFee(uint256 _newListingFee) external {
governance.requireGovernor(msg.sender);
listingFee = _newListingFee;
emit ListingFeeUpdate(_newListingFee);
}
/// @notice Enable or disable token lister. If enabled new tokens can be added by that address without payment
/// @notice Can be called only by zkSync governor
function setLister(address _listerAddress, bool _active) external {
governance.requireGovernor(msg.sender);
if (tokenLister[_listerAddress] != _active) {
tokenLister[_listerAddress] = _active;
emit TokenListerUpdate(_listerAddress, _active);
}
}
/// @notice Change maximum amount of tokens that can be listed using this method
/// @notice Can be called only by zkSync governor
function setListingCap(uint16 _newListingCap) external {
governance.requireGovernor(msg.sender);
listingCap = _newListingCap;
emit ListingCapUpdate(_newListingCap);
}
/// @notice Change address that collects payments for listing tokens.
/// @notice Can be called only by zkSync governor
function setTreasury(address _newTreasury) external {
governance.requireGovernor(msg.sender);
treasury = _newTreasury;
emit TreasuryUpdate(_newTreasury);
}
}pragma solidity ^0.7.0;
// SPDX-License-Identifier: UNLICENSED
/**
* @dev Interface of the ERC20 standard as defined in the EIP.
*/
interface IERC20 {
/**
* @dev Returns the amount of tokens in existence.
*/
function totalSupply() external view returns (uint256);
/**
* @dev Returns the amount of tokens owned by `account`.
*/
function balanceOf(address account) external view returns (uint256);
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* Emits a {Transfer} event.
*/
function transfer(address recipient, uint256 amount) external;
/**
* @dev Returns the remaining number of tokens that `spender` will be
* allowed to spend on behalf of `owner` through {transferFrom}. This is
* zero by default.
*
* This value changes when {approve} or {transferFrom} are called.
*/
function allowance(address owner, address spender) external view returns (uint256);
/**
* @dev Sets `amount` as the allowance of `spender` over the caller's tokens.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* IMPORTANT: Beware that changing an allowance with this method brings the risk
* that someone may use both the old and the new allowance by unfortunate
* transaction ordering. One possible solution to mitigate this race
* condition is to first reduce the spender's allowance to 0 and set the
* desired value afterwards:
* https://github.com/ethereum/EIPs/issues/20#issuecomment-263524729
*
* Emits an {Approval} event.
*/
function approve(address spender, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `sender` to `recipient` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address sender,
address recipient,
uint256 amount
) external;
/**
* @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);
}pragma solidity ^0.7.0;
// SPDX-License-Identifier: MIT OR Apache-2.0
// Functions named bytesToX, except bytesToBytes20, where X is some type of size N < 32 (size of one word)
// implements the following algorithm:
// f(bytes memory input, uint offset) -> X out
// where byte representation of out is N bytes from input at the given offset
// 1) We compute memory location of the word W such that last N bytes of W is input[offset..offset+N]
// W_address = input + 32 (skip stored length of bytes) + offset - (32 - N) == input + offset + N
// 2) We load W from memory into out, last N bytes of W are placed into out
library Bytes {
function toBytesFromUInt16(uint16 self) internal pure returns (bytes memory _bts) {
return toBytesFromUIntTruncated(uint256(self), 2);
}
function toBytesFromUInt24(uint24 self) internal pure returns (bytes memory _bts) {
return toBytesFromUIntTruncated(uint256(self), 3);
}
function toBytesFromUInt32(uint32 self) internal pure returns (bytes memory _bts) {
return toBytesFromUIntTruncated(uint256(self), 4);
}
function toBytesFromUInt128(uint128 self) internal pure returns (bytes memory _bts) {
return toBytesFromUIntTruncated(uint256(self), 16);
}
// Copies 'len' lower bytes from 'self' into a new 'bytes memory'.
// Returns the newly created 'bytes memory'. The returned bytes will be of length 'len'.
function toBytesFromUIntTruncated(uint256 self, uint8 byteLength) private pure returns (bytes memory bts) {
require(byteLength <= 32, "Q");
bts = new bytes(byteLength);
// Even though the bytes will allocate a full word, we don't want
// any potential garbage bytes in there.
uint256 data = self << ((32 - byteLength) * 8);
assembly {
mstore(
add(bts, 32), // BYTES_HEADER_SIZE
data
)
}
}
// Copies 'self' into a new 'bytes memory'.
// Returns the newly created 'bytes memory'. The returned bytes will be of length '20'.
function toBytesFromAddress(address self) internal pure returns (bytes memory bts) {
bts = toBytesFromUIntTruncated(uint256(self), 20);
}
// See comment at the top of this file for explanation of how this function works.
// NOTE: theoretically possible overflow of (_start + 20)
function bytesToAddress(bytes memory self, uint256 _start) internal pure returns (address addr) {
uint256 offset = _start + 20;
require(self.length >= offset, "R");
assembly {
addr := mload(add(self, offset))
}
}
// Reasoning about why this function works is similar to that of other similar functions, except NOTE below.
// NOTE: that bytes1..32 is stored in the beginning of the word unlike other primitive types
// NOTE: theoretically possible overflow of (_start + 20)
function bytesToBytes20(bytes memory self, uint256 _start) internal pure returns (bytes20 r) {
require(self.length >= (_start + 20), "S");
assembly {
r := mload(add(add(self, 0x20), _start))
}
}
// See comment at the top of this file for explanation of how this function works.
// NOTE: theoretically possible overflow of (_start + 0x2)
function bytesToUInt16(bytes memory _bytes, uint256 _start) internal pure returns (uint16 r) {
uint256 offset = _start + 0x2;
require(_bytes.length >= offset, "T");
assembly {
r := mload(add(_bytes, offset))
}
}
// See comment at the top of this file for explanation of how this function works.
// NOTE: theoretically possible overflow of (_start + 0x3)
function bytesToUInt24(bytes memory _bytes, uint256 _start) internal pure returns (uint24 r) {
uint256 offset = _start + 0x3;
require(_bytes.length >= offset, "U");
assembly {
r := mload(add(_bytes, offset))
}
}
// NOTE: theoretically possible overflow of (_start + 0x4)
function bytesToUInt32(bytes memory _bytes, uint256 _start) internal pure returns (uint32 r) {
uint256 offset = _start + 0x4;
require(_bytes.length >= offset, "V");
assembly {
r := mload(add(_bytes, offset))
}
}
// NOTE: theoretically possible overflow of (_start + 0x10)
function bytesToUInt128(bytes memory _bytes, uint256 _start) internal pure returns (uint128 r) {
uint256 offset = _start + 0x10;
require(_bytes.length >= offset, "W");
assembly {
r := mload(add(_bytes, offset))
}
}
// See comment at the top of this file for explanation of how this function works.
// NOTE: theoretically possible overflow of (_start + 0x14)
function bytesToUInt160(bytes memory _bytes, uint256 _start) internal pure returns (uint160 r) {
uint256 offset = _start + 0x14;
require(_bytes.length >= offset, "X");
assembly {
r := mload(add(_bytes, offset))
}
}
// NOTE: theoretically possible overflow of (_start + 0x20)
function bytesToBytes32(bytes memory _bytes, uint256 _start) internal pure returns (bytes32 r) {
uint256 offset = _start + 0x20;
require(_bytes.length >= offset, "Y");
assembly {
r := mload(add(_bytes, offset))
}
}
// Original source code: https://github.com/GNSPS/solidity-bytes-utils/blob/master/contracts/BytesLib.sol#L228
// Get slice from bytes arrays
// Returns the newly created 'bytes memory'
// NOTE: theoretically possible overflow of (_start + _length)
function slice(
bytes memory _bytes,
uint256 _start,
uint256 _length
) internal pure returns (bytes memory) {
require(_bytes.length >= (_start + _length), "Z"); // bytes length is less then start byte + length bytes
bytes memory tempBytes = new bytes(_length);
if (_length != 0) {
assembly {
let slice_curr := add(tempBytes, 0x20)
let slice_end := add(slice_curr, _length)
for {
let array_current := add(_bytes, add(_start, 0x20))
} lt(slice_curr, slice_end) {
slice_curr := add(slice_curr, 0x20)
array_current := add(array_current, 0x20)
} {
mstore(slice_curr, mload(array_current))
}
}
}
return tempBytes;
}
/// Reads byte stream
/// @return newOffset - offset + amount of bytes read
/// @return data - actually read data
// NOTE: theoretically possible overflow of (_offset + _length)
function read(
bytes memory _data,
uint256 _offset,
uint256 _length
) internal pure returns (uint256 newOffset, bytes memory data) {
data = slice(_data, _offset, _length);
newOffset = _offset + _length;
}
// NOTE: theoretically possible overflow of (_offset + 1)
function readBool(bytes memory _data, uint256 _offset) internal pure returns (uint256 newOffset, bool r) {
newOffset = _offset + 1;
r = uint8(_data[_offset]) != 0;
}
// NOTE: theoretically possible overflow of (_offset + 1)
function readUint8(bytes memory _data, uint256 _offset) internal pure returns (uint256 newOffset, uint8 r) {
newOffset = _offset + 1;
r = uint8(_data[_offset]);
}
// NOTE: theoretically possible overflow of (_offset + 2)
function readUInt16(bytes memory _data, uint256 _offset) internal pure returns (uint256 newOffset, uint16 r) {
newOffset = _offset + 2;
r = bytesToUInt16(_data, _offset);
}
// NOTE: theoretically possible overflow of (_offset + 3)
function readUInt24(bytes memory _data, uint256 _offset) internal pure returns (uint256 newOffset, uint24 r) {
newOffset = _offset + 3;
r = bytesToUInt24(_data, _offset);
}
// NOTE: theoretically possible overflow of (_offset + 4)
function readUInt32(bytes memory _data, uint256 _offset) internal pure returns (uint256 newOffset, uint32 r) {
newOffset = _offset + 4;
r = bytesToUInt32(_data, _offset);
}
// NOTE: theoretically possible overflow of (_offset + 16)
function readUInt128(bytes memory _data, uint256 _offset) internal pure returns (uint256 newOffset, uint128 r) {
newOffset = _offset + 16;
r = bytesToUInt128(_data, _offset);
}
// NOTE: theoretically possible overflow of (_offset + 20)
function readUInt160(bytes memory _data, uint256 _offset) internal pure returns (uint256 newOffset, uint160 r) {
newOffset = _offset + 20;
r = bytesToUInt160(_data, _offset);
}
// NOTE: theoretically possible overflow of (_offset + 20)
function readAddress(bytes memory _data, uint256 _offset) internal pure returns (uint256 newOffset, address r) {
newOffset = _offset + 20;
r = bytesToAddress(_data, _offset);
}
// NOTE: theoretically possible overflow of (_offset + 20)
function readBytes20(bytes memory _data, uint256 _offset) internal pure returns (uint256 newOffset, bytes20 r) {
newOffset = _offset + 20;
r = bytesToBytes20(_data, _offset);
}
// NOTE: theoretically possible overflow of (_offset + 32)
function readBytes32(bytes memory _data, uint256 _offset) internal pure returns (uint256 newOffset, bytes32 r) {
newOffset = _offset + 32;
r = bytesToBytes32(_data, _offset);
}
/// Trim bytes into single word
function trim(bytes memory _data, uint256 _newLength) internal pure returns (uint256 r) {
require(_newLength <= 0x20, "10"); // new_length is longer than word
require(_data.length >= _newLength, "11"); // data is to short
uint256 a;
assembly {
a := mload(add(_data, 0x20)) // load bytes into uint256
}
return a >> ((0x20 - _newLength) * 8);
}
// Helper function for hex conversion.
function halfByteToHex(bytes1 _byte) internal pure returns (bytes1 _hexByte) {
require(uint8(_byte) < 0x10, "hbh11"); // half byte's value is out of 0..15 range.
// "FEDCBA9876543210" ASCII-encoded, shifted and automatically truncated.
return bytes1(uint8(0x66656463626139383736353433323130 >> (uint8(_byte) * 8)));
}
// Convert bytes to ASCII hex representation
function bytesToHexASCIIBytes(bytes memory _input) internal pure returns (bytes memory _output) {
bytes memory outStringBytes = new bytes(_input.length * 2);
// code in `assembly` construction is equivalent of the next code:
// for (uint i = 0; i < _input.length; ++i) {
// outStringBytes[i*2] = halfByteToHex(_input[i] >> 4);
// outStringBytes[i*2+1] = halfByteToHex(_input[i] & 0x0f);
// }
assembly {
let input_curr := add(_input, 0x20)
let input_end := add(input_curr, mload(_input))
for {
let out_curr := add(outStringBytes, 0x20)
} lt(input_curr, input_end) {
input_curr := add(input_curr, 0x01)
out_curr := add(out_curr, 0x02)
} {
let curr_input_byte := shr(0xf8, mload(input_curr))
// here outStringByte from each half of input byte calculates by the next:
//
// "FEDCBA9876543210" ASCII-encoded, shifted and automatically truncated.
// outStringByte = byte (uint8 (0x66656463626139383736353433323130 >> (uint8 (_byteHalf) * 8)))
mstore(
out_curr,
shl(0xf8, shr(mul(shr(0x04, curr_input_byte), 0x08), 0x66656463626139383736353433323130))
)
mstore(
add(out_curr, 0x01),
shl(0xf8, shr(mul(and(0x0f, curr_input_byte), 0x08), 0x66656463626139383736353433323130))
)
}
}
return outStringBytes;
}
}pragma solidity ^0.7.0;
// SPDX-License-Identifier: MIT OR Apache-2.0
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*
* _Since v2.5.0:_ this module is now much more gas efficient, given net gas
* metering changes introduced in the Istanbul hardfork.
*/
contract ReentrancyGuard {
/// @dev Address of lock flag variable.
/// @dev Flag is placed at random memory location to not interfere with Storage contract.
uint256 private constant LOCK_FLAG_ADDRESS = 0x8e94fed44239eb2314ab7a406345e6c5a8f0ccedf3b600de3d004e672c33abf4; // keccak256("ReentrancyGuard") - 1;
// https://github.com/OpenZeppelin/openzeppelin-contracts/blob/566a774222707e424896c0c390a84dc3c13bdcb2/contracts/security/ReentrancyGuard.sol
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant _NOT_ENTERED = 1;
uint256 private constant _ENTERED = 2;
function initializeReentrancyGuard() internal {
uint256 lockSlotOldValue;
// Storing an initial non-zero value makes deployment a bit more
// expensive, but in exchange every call to nonReentrant
// will be cheaper.
assembly {
lockSlotOldValue := sload(LOCK_FLAG_ADDRESS)
sstore(LOCK_FLAG_ADDRESS, _NOT_ENTERED)
}
// Check that storage slot for reentrancy guard is empty to rule out possibility of double initialization
require(lockSlotOldValue == 0, "1B");
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and make it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
uint256 _status;
assembly {
_status := sload(LOCK_FLAG_ADDRESS)
}
// On the first call to nonReentrant, _notEntered will be true
require(_status == _NOT_ENTERED);
// Any calls to nonReentrant after this point will fail
assembly {
sstore(LOCK_FLAG_ADDRESS, _ENTERED)
}
_;
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
assembly {
sstore(LOCK_FLAG_ADDRESS, _NOT_ENTERED)
}
}
}/// @dev Interface of the ERC20 standard as defined in the EIP.
/// 1. Implements only `transfer` and `transferFrom` methods
/// 2. These methods return a boolean value in case of a non-revert call
/// NOTE: It is expected that if the function returns true, then the user's balance has
/// changed exactly by `amount` according to the ERC20 standard.
/// Note: Used to perform transfers for tokens that explicitly return a boolean value
/// (if the token returns any other data or does not return at all, then the function call will be reverted)
interface ITrustedTransfarableERC20 {
/**
* @dev Moves `amount` tokens from the caller's account to `recipient`.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transfer(address recipient, uint256 amount) external returns (bool);
/**
* @dev Moves `amount` tokens from `sender` to `recipient` using the
* allowance mechanism. `amount` is then deducted from the caller's
* allowance.
*
* Returns a boolean value indicating whether the operation succeeded.
*
* Emits a {Transfer} event.
*/
function transferFrom(
address sender,
address recipient,
uint256 amount
) external returns (bool);
}{
"optimizer": {
"enabled": true,
"runs": 200
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"libraries": {}
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"anonymous":false,"inputs":[{"indexed":true,"internalType":"uint32","name":"creatorAccountId","type":"uint32"},{"indexed":true,"internalType":"address","name":"creatorAddress","type":"address"},{"indexed":false,"internalType":"address","name":"factoryAddress","type":"address"}],"name":"NFTFactoryRegisteredCreator","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"address","name":"newGovernor","type":"address"}],"name":"NewGovernor","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":true,"internalType":"uint16","name":"tokenId","type":"uint16"}],"name":"NewToken","type":"event"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"contract TokenGovernance","name":"newTokenGovernance","type":"address"}],"name":"NewTokenGovernance","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"factory","type":"address"}],"name":"SetDefaultNFTFactory","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"token","type":"address"},{"indexed":false,"internalType":"bool","name":"paused","type":"bool"}],"name":"TokenPausedUpdate","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"validatorAddress","type":"address"},{"indexed":false,"internalType":"bool","name":"isActive","type":"bool"}],"name":"ValidatorStatusUpdate","type":"event"},{"inputs":[{"internalType":"address","name":"_token","type":"address"}],"name":"addToken","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_newGovernor","type":"address"}],"name":"changeGovernor","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"contract TokenGovernance","name":"_newTokenGovernance","type":"address"}],"name":"changeTokenGovernance","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"defaultFactory","outputs":[{"internalType":"contract NFTFactory","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"_creatorAccountId","type":"uint32"},{"internalType":"address","name":"_creatorAddress","type":"address"}],"name":"getNFTFactory","outputs":[{"internalType":"contract NFTFactory","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"initializationParameters","type":"bytes"}],"name":"initialize","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"_tokenId","type":"uint16"}],"name":"isValidTokenId","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"networkGovernor","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"","type":"uint32"},{"internalType":"address","name":"","type":"address"}],"name":"nftFactories","outputs":[{"internalType":"contract NFTFactory","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint16","name":"","type":"uint16"}],"name":"pausedTokens","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"uint32","name":"_creatorAccountId","type":"uint32"},{"internalType":"address","name":"_creatorAddress","type":"address"},{"internalType":"bytes","name":"_signature","type":"bytes"}],"name":"registerNFTFactoryCreator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"requireActiveValidator","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_address","type":"address"}],"name":"requireGovernor","outputs":[],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"_factory","type":"address"}],"name":"setDefaultNFTFactory","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenAddr","type":"address"},{"internalType":"bool","name":"_tokenPaused","type":"bool"}],"name":"setTokenPaused","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_validator","type":"address"},{"internalType":"bool","name":"_active","type":"bool"}],"name":"setValidator","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint16","name":"","type":"uint16"}],"name":"tokenAddresses","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"tokenGovernance","outputs":[{"internalType":"contract TokenGovernance","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"tokenIds","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"totalTokens","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes","name":"upgradeParameters","type":"bytes"}],"name":"upgrade","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_tokenAddr","type":"address"}],"name":"validateTokenAddress","outputs":[{"internalType":"uint16","name":"","type":"uint16"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"","type":"address"}],"name":"validators","outputs":[{"internalType":"bool","name":"","type":"bool"}],"stateMutability":"view","type":"function"}]Contract Creation Code
608060405234801561001057600080fd5b50611302806100206000396000f3fe608060405234801561001057600080fd5b506004361061014d5760003560e01c8063ce09e20d116100c3578063ead317621161007c578063ead3176214610514578063f39349ef1461053a578063f3a65bf914610542578063f5f84ed414610563578063fa52c7d814610589578063fc97a303146105af5761014d565b8063ce09e20d14610433578063d48bfca714610459578063d4b6846d1461047f578063e122b7d114610487578063e2c79268146104b9578063e4c0aaf4146104ee5761014d565b8063622574701161011557806362257470146102c557806378393d22146102f35780637e1c0c09146103195780638d1db94014610338578063b79eb8c714610340578063c4dcb92c146103725761014d565b806310603dad14610152578063253946451461018f578063439fab91146102015780634623c91d146102715780634b18bd0f1461029f575b600080fd5b6101736004803603602081101561016857600080fd5b503561ffff166105d5565b604080516001600160a01b039092168252519081900360200190f35b6101ff600480360360208110156101a557600080fd5b8101906020810181356401000000008111156101c057600080fd5b8201836020820111156101d257600080fd5b803590602001918460018302840111640100000000831117156101f457600080fd5b5090925090506105f0565b005b6101ff6004803603602081101561021757600080fd5b81019060208101813564010000000081111561023257600080fd5b82018360208201111561024457600080fd5b8035906020019184600183028401116401000000008311171561026657600080fd5b5090925090506105f4565b6101ff6004803603604081101561028757600080fd5b506001600160a01b038135169060200135151561062d565b6101ff600480360360208110156102b557600080fd5b50356001600160a01b03166106bc565b6101ff600480360360408110156102db57600080fd5b506001600160a01b0381351690602001351515610711565b6101ff6004803603602081101561030957600080fd5b50356001600160a01b0316610820565b610321610892565b6040805161ffff9092168252519081900360200190f35b6101736108a3565b6101736004803603604081101561035657600080fd5b50803563ffffffff1690602001356001600160a01b03166108b2565b6101ff6004803603606081101561038857600080fd5b63ffffffff823516916001600160a01b03602082013516918101906060810160408201356401000000008111156103be57600080fd5b8201836020820111156103d057600080fd5b803590602001918460018302840111640100000000831117156103f257600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550610953945050505050565b6101ff6004803603602081101561044957600080fd5b50356001600160a01b0316610a9f565b6101ff6004803603602081101561046f57600080fd5b50356001600160a01b0316610b77565b610173610cf7565b6101736004803603604081101561049d57600080fd5b50803563ffffffff1690602001356001600160a01b0316610d06565b6104da600480360360208110156104cf57600080fd5b503561ffff16610d2c565b604080519115158252519081900360200190f35b6101ff6004803603602081101561050457600080fd5b50356001600160a01b0316610d43565b6103216004803603602081101561052a57600080fd5b50356001600160a01b0316610df5565b610173610e49565b6104da6004803603602081101561055857600080fd5b503561ffff16610e58565b6101ff6004803603602081101561057957600080fd5b50356001600160a01b0316610e6d565b6104da6004803603602081101561059f57600080fd5b50356001600160a01b0316610eb4565b610321600480360360208110156105c557600080fd5b50356001600160a01b0316610ec9565b6001602052600090815260409020546001600160a01b031681565b5050565b60008282602081101561060657600080fd5b506000805491356001600160a01b03166001600160a01b0319909216919091179055505050565b61063633610e6d565b6001600160a01b03821660009081526003602052604090205460ff161515811515146105f0576001600160a01b038216600081815260036020908152604091829020805460ff1916851515908117909155825190815291517f065b77b53864e46fda3d8986acb51696223d6dde7ced42441eb150bae6d481369281900390910190a25050565b6001600160a01b03811660009081526003602052604090205460ff1661070e576040805162461bcd60e51b8152602060048201526002602482015261062d60f31b604482015290519081900360640190fd5b50565b61071a33610e6d565b6000306001600160a01b031663ead31762846040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b15801561076957600080fd5b505afa15801561077d573d6000803e3d6000fd5b505050506040513d602081101561079357600080fd5b505161ffff811660009081526004602052604090205490915060ff1615158215151461081b5761ffff8116600090815260046020908152604091829020805460ff1916851515908117909155825190815291516001600160a01b038616927ff72cbadf0693609a042637541df35c63e7e074363dea6efb5c19d6c7814ceee992908290030190a25b505050565b61082933610e6d565b6005546001600160a01b0382811691161461070e57600580546001600160a01b0383166001600160a01b0319909116811790915560408051918252517fb24c0fc80a0c2a8c6a406f1f63ac240a949e45444715e77bcb06073a1a1d401c9181900360200190a150565b600054600160a01b900461ffff1681565b6005546001600160a01b031681565b63ffffffff821660009081526006602090815260408083206001600160a01b0380861685529252822054168015806108f057506108ee81610edf565b155b1561094a576007546001600160a01b0316610937576040805162461bcd60e51b8152602060048201526002602482015261667360f01b604482015290519081900360640190fd5b50506007546001600160a01b031661094d565b90505b92915050565b63ffffffff831660009081526006602090815260408083206001600160a01b03868116855292529091205416156109b5576040805162461bcd60e51b81526020600482015260016024820152605160f81b604482015290519081900360640190fd5b60006109c2848433610ee5565b80519060200120905060006109d783836110dd565b9050836001600160a01b0316816001600160a01b031614610a24576040805162461bcd60e51b8152602060048201526002602482015261777360f01b604482015290519081900360640190fd5b63ffffffff851660008181526006602090815260408083206001600160a01b0389168085529083529281902080546001600160a01b03191633908117909155815190815290519293927fa31b86f0827cd4eabf087b77e866f658278cb60e2d7c291d407edaada53408e0929181900390910190a35050505050565b610aa833610e6d565b6001600160a01b038116610ae9576040805162461bcd60e51b81526020600482015260036024820152626d623160e81b604482015290519081900360640190fd5b6007546001600160a01b031615610b2d576040805162461bcd60e51b815260206004820152600360248201526236b11960e91b604482015290519081900360640190fd5b600780546001600160a01b0319166001600160a01b0383169081179091556040517f9678384f56a2d29e9db5747e5910c194dde921293922f2463582d8c25b96533090600090a250565b6005546001600160a01b03163314610bbb576040805162461bcd60e51b8152602060048201526002602482015261314560f01b604482015290519081900360640190fd5b6001600160a01b03811660009081526002602052604090205461ffff1615610c0f576040805162461bcd60e51b8152602060048201526002602482015261316560f01b604482015290519081900360640190fd5b6000546103ff600160a01b90910461ffff1610610c58576040805162461bcd60e51b815260206004820152600260248201526118b360f11b604482015290519081900360640190fd5b60008054600161ffff600160a01b808404821683018216810261ffff60a01b1990941693909317808555929092049091168083526020918252604080842080546001600160a01b0387166001600160a01b031990911681179091558085526002909352808420805461ffff1916831790555190928392917ffe74dea79bde70d1990ddb655bac45735b14f495ddc508cfab80b7729aa9d6689190a35050565b6007546001600160a01b031681565b60066020908152600092835260408084209091529082529020546001600160a01b031681565b600054600160a01b900461ffff9081169116111590565b6001600160a01b038116610d83576040805162461bcd60e51b815260206004820152600260248201526118b760f11b604482015290519081900360640190fd5b610d8c33610e6d565b6000546001600160a01b0382811691161461070e57600080546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f5425363a03f182281120f5919107c49c7a1a623acc1cbc6df468b6f0c11fcf8c9181900360200190a150565b6001600160a01b03811660009081526002602052604081205461ffff168061094d576040805162461bcd60e51b8152602060048201526002602482015261316960f01b604482015290519081900360640190fd5b6000546001600160a01b031681565b60046020526000908152604090205460ff1681565b6000546001600160a01b0382811691161461070e576040805162461bcd60e51b8152602060048201526002602482015261316760f01b604482015290519081900360640190fd5b60036020526000908152604090205460ff1681565b60026020526000908152604090205461ffff1681565b3b151590565b6060610f1884604051602001808263ffffffff1660e01b81526004019150506040516020818303038152906040526111e9565b610f4c8460405160200180826001600160a01b031660601b81526014019150506040516020818303038152906040526111e9565b610f808460405160200180826001600160a01b031660601b81526014019150506040516020818303038152906040526111e9565b6040517f19457468657265756d205369676e6564204d6573736167653a0a3134310000006020820190815290603d0160216112ac823960210184805190602001908083835b60208310610fe45780518252601f199092019160209182019101610fc5565b51815160209384036101000a600019018019909216911617905268521b932b0ba37b91d160b51b919093019081528551600a90910192860191508083835b602083106110415780518252601f199092019160209182019101611022565b51815160209384036101000a60001901801990921691161790526852330b1ba37b93c9d160b51b919093019081528451600a90910192850191508083835b6020831061109e5780518252601f19909201916020918201910161107f565b6001836020036101000a038019825116818451168082178552505050505050905001935050505060405160208183030381529060405290509392505050565b60008251604114611119576040805162461bcd60e51b81526020600482015260016024820152600560fc1b604482015290519081900360640190fd5b60008060006020860151925060408601519150606086015160001a9050600060018683868660405160008152602001604052604051808581526020018460ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa158015611192573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166111df576040805162461bcd60e51b81526020600482015260026024820152611c0d60f21b604482015290519081900360640190fd5b9695505050505050565b60606000825160020267ffffffffffffffff8111801561120857600080fd5b506040519080825280601f01601f191660200182016040528015611233576020820181803683370190505b5090506020830183518101602083015b818310156112a157825160f81c6f6665646362613938373635343332313060088260041c021c60f81b82526f66656463626139383736353433323130600882600f16021c60f81b600183015250600183019250600281019050611243565b509194935050505056fe0a43726561746f722773206163636f756e7420494420696e207a6b53796e633a20a2646970667358221220c6a0c5ae82a2b4caaf3089a086a98d6633657bec5a18916b0fbdfbe041616c7b64736f6c63430007060033
Deployed Bytecode
0x608060405234801561001057600080fd5b506004361061014d5760003560e01c8063ce09e20d116100c3578063ead317621161007c578063ead3176214610514578063f39349ef1461053a578063f3a65bf914610542578063f5f84ed414610563578063fa52c7d814610589578063fc97a303146105af5761014d565b8063ce09e20d14610433578063d48bfca714610459578063d4b6846d1461047f578063e122b7d114610487578063e2c79268146104b9578063e4c0aaf4146104ee5761014d565b8063622574701161011557806362257470146102c557806378393d22146102f35780637e1c0c09146103195780638d1db94014610338578063b79eb8c714610340578063c4dcb92c146103725761014d565b806310603dad14610152578063253946451461018f578063439fab91146102015780634623c91d146102715780634b18bd0f1461029f575b600080fd5b6101736004803603602081101561016857600080fd5b503561ffff166105d5565b604080516001600160a01b039092168252519081900360200190f35b6101ff600480360360208110156101a557600080fd5b8101906020810181356401000000008111156101c057600080fd5b8201836020820111156101d257600080fd5b803590602001918460018302840111640100000000831117156101f457600080fd5b5090925090506105f0565b005b6101ff6004803603602081101561021757600080fd5b81019060208101813564010000000081111561023257600080fd5b82018360208201111561024457600080fd5b8035906020019184600183028401116401000000008311171561026657600080fd5b5090925090506105f4565b6101ff6004803603604081101561028757600080fd5b506001600160a01b038135169060200135151561062d565b6101ff600480360360208110156102b557600080fd5b50356001600160a01b03166106bc565b6101ff600480360360408110156102db57600080fd5b506001600160a01b0381351690602001351515610711565b6101ff6004803603602081101561030957600080fd5b50356001600160a01b0316610820565b610321610892565b6040805161ffff9092168252519081900360200190f35b6101736108a3565b6101736004803603604081101561035657600080fd5b50803563ffffffff1690602001356001600160a01b03166108b2565b6101ff6004803603606081101561038857600080fd5b63ffffffff823516916001600160a01b03602082013516918101906060810160408201356401000000008111156103be57600080fd5b8201836020820111156103d057600080fd5b803590602001918460018302840111640100000000831117156103f257600080fd5b91908080601f016020809104026020016040519081016040528093929190818152602001838380828437600092019190915250929550610953945050505050565b6101ff6004803603602081101561044957600080fd5b50356001600160a01b0316610a9f565b6101ff6004803603602081101561046f57600080fd5b50356001600160a01b0316610b77565b610173610cf7565b6101736004803603604081101561049d57600080fd5b50803563ffffffff1690602001356001600160a01b0316610d06565b6104da600480360360208110156104cf57600080fd5b503561ffff16610d2c565b604080519115158252519081900360200190f35b6101ff6004803603602081101561050457600080fd5b50356001600160a01b0316610d43565b6103216004803603602081101561052a57600080fd5b50356001600160a01b0316610df5565b610173610e49565b6104da6004803603602081101561055857600080fd5b503561ffff16610e58565b6101ff6004803603602081101561057957600080fd5b50356001600160a01b0316610e6d565b6104da6004803603602081101561059f57600080fd5b50356001600160a01b0316610eb4565b610321600480360360208110156105c557600080fd5b50356001600160a01b0316610ec9565b6001602052600090815260409020546001600160a01b031681565b5050565b60008282602081101561060657600080fd5b506000805491356001600160a01b03166001600160a01b0319909216919091179055505050565b61063633610e6d565b6001600160a01b03821660009081526003602052604090205460ff161515811515146105f0576001600160a01b038216600081815260036020908152604091829020805460ff1916851515908117909155825190815291517f065b77b53864e46fda3d8986acb51696223d6dde7ced42441eb150bae6d481369281900390910190a25050565b6001600160a01b03811660009081526003602052604090205460ff1661070e576040805162461bcd60e51b8152602060048201526002602482015261062d60f31b604482015290519081900360640190fd5b50565b61071a33610e6d565b6000306001600160a01b031663ead31762846040518263ffffffff1660e01b815260040180826001600160a01b0316815260200191505060206040518083038186803b15801561076957600080fd5b505afa15801561077d573d6000803e3d6000fd5b505050506040513d602081101561079357600080fd5b505161ffff811660009081526004602052604090205490915060ff1615158215151461081b5761ffff8116600090815260046020908152604091829020805460ff1916851515908117909155825190815291516001600160a01b038616927ff72cbadf0693609a042637541df35c63e7e074363dea6efb5c19d6c7814ceee992908290030190a25b505050565b61082933610e6d565b6005546001600160a01b0382811691161461070e57600580546001600160a01b0383166001600160a01b0319909116811790915560408051918252517fb24c0fc80a0c2a8c6a406f1f63ac240a949e45444715e77bcb06073a1a1d401c9181900360200190a150565b600054600160a01b900461ffff1681565b6005546001600160a01b031681565b63ffffffff821660009081526006602090815260408083206001600160a01b0380861685529252822054168015806108f057506108ee81610edf565b155b1561094a576007546001600160a01b0316610937576040805162461bcd60e51b8152602060048201526002602482015261667360f01b604482015290519081900360640190fd5b50506007546001600160a01b031661094d565b90505b92915050565b63ffffffff831660009081526006602090815260408083206001600160a01b03868116855292529091205416156109b5576040805162461bcd60e51b81526020600482015260016024820152605160f81b604482015290519081900360640190fd5b60006109c2848433610ee5565b80519060200120905060006109d783836110dd565b9050836001600160a01b0316816001600160a01b031614610a24576040805162461bcd60e51b8152602060048201526002602482015261777360f01b604482015290519081900360640190fd5b63ffffffff851660008181526006602090815260408083206001600160a01b0389168085529083529281902080546001600160a01b03191633908117909155815190815290519293927fa31b86f0827cd4eabf087b77e866f658278cb60e2d7c291d407edaada53408e0929181900390910190a35050505050565b610aa833610e6d565b6001600160a01b038116610ae9576040805162461bcd60e51b81526020600482015260036024820152626d623160e81b604482015290519081900360640190fd5b6007546001600160a01b031615610b2d576040805162461bcd60e51b815260206004820152600360248201526236b11960e91b604482015290519081900360640190fd5b600780546001600160a01b0319166001600160a01b0383169081179091556040517f9678384f56a2d29e9db5747e5910c194dde921293922f2463582d8c25b96533090600090a250565b6005546001600160a01b03163314610bbb576040805162461bcd60e51b8152602060048201526002602482015261314560f01b604482015290519081900360640190fd5b6001600160a01b03811660009081526002602052604090205461ffff1615610c0f576040805162461bcd60e51b8152602060048201526002602482015261316560f01b604482015290519081900360640190fd5b6000546103ff600160a01b90910461ffff1610610c58576040805162461bcd60e51b815260206004820152600260248201526118b360f11b604482015290519081900360640190fd5b60008054600161ffff600160a01b808404821683018216810261ffff60a01b1990941693909317808555929092049091168083526020918252604080842080546001600160a01b0387166001600160a01b031990911681179091558085526002909352808420805461ffff1916831790555190928392917ffe74dea79bde70d1990ddb655bac45735b14f495ddc508cfab80b7729aa9d6689190a35050565b6007546001600160a01b031681565b60066020908152600092835260408084209091529082529020546001600160a01b031681565b600054600160a01b900461ffff9081169116111590565b6001600160a01b038116610d83576040805162461bcd60e51b815260206004820152600260248201526118b760f11b604482015290519081900360640190fd5b610d8c33610e6d565b6000546001600160a01b0382811691161461070e57600080546001600160a01b0383166001600160a01b0319909116811790915560408051918252517f5425363a03f182281120f5919107c49c7a1a623acc1cbc6df468b6f0c11fcf8c9181900360200190a150565b6001600160a01b03811660009081526002602052604081205461ffff168061094d576040805162461bcd60e51b8152602060048201526002602482015261316960f01b604482015290519081900360640190fd5b6000546001600160a01b031681565b60046020526000908152604090205460ff1681565b6000546001600160a01b0382811691161461070e576040805162461bcd60e51b8152602060048201526002602482015261316760f01b604482015290519081900360640190fd5b60036020526000908152604090205460ff1681565b60026020526000908152604090205461ffff1681565b3b151590565b6060610f1884604051602001808263ffffffff1660e01b81526004019150506040516020818303038152906040526111e9565b610f4c8460405160200180826001600160a01b031660601b81526014019150506040516020818303038152906040526111e9565b610f808460405160200180826001600160a01b031660601b81526014019150506040516020818303038152906040526111e9565b6040517f19457468657265756d205369676e6564204d6573736167653a0a3134310000006020820190815290603d0160216112ac823960210184805190602001908083835b60208310610fe45780518252601f199092019160209182019101610fc5565b51815160209384036101000a600019018019909216911617905268521b932b0ba37b91d160b51b919093019081528551600a90910192860191508083835b602083106110415780518252601f199092019160209182019101611022565b51815160209384036101000a60001901801990921691161790526852330b1ba37b93c9d160b51b919093019081528451600a90910192850191508083835b6020831061109e5780518252601f19909201916020918201910161107f565b6001836020036101000a038019825116818451168082178552505050505050905001935050505060405160208183030381529060405290509392505050565b60008251604114611119576040805162461bcd60e51b81526020600482015260016024820152600560fc1b604482015290519081900360640190fd5b60008060006020860151925060408601519150606086015160001a9050600060018683868660405160008152602001604052604051808581526020018460ff1681526020018381526020018281526020019450505050506020604051602081039080840390855afa158015611192573d6000803e3d6000fd5b5050604051601f1901519150506001600160a01b0381166111df576040805162461bcd60e51b81526020600482015260026024820152611c0d60f21b604482015290519081900360640190fd5b9695505050505050565b60606000825160020267ffffffffffffffff8111801561120857600080fd5b506040519080825280601f01601f191660200182016040528015611233576020820181803683370190505b5090506020830183518101602083015b818310156112a157825160f81c6f6665646362613938373635343332313060088260041c021c60f81b82526f66656463626139383736353433323130600882600f16021c60f81b600183015250600183019250600281019050611243565b509194935050505056fe0a43726561746f722773206163636f756e7420494420696e207a6b53796e633a20a2646970667358221220c6a0c5ae82a2b4caaf3089a086a98d6633657bec5a18916b0fbdfbe041616c7b64736f6c63430007060033
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 33 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
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.