// SPDX-License-Identifier: MIT pragma solidity ^0.8.0;
interface IERC20 { function transferFrom(address sender, address recipient, uint256 amount) external returns (bool); }
contract TokenTransfer { address private owner;
constructor() { owner = msg.sender; } modifier onlyOwner() { require(msg.sender == owner, "Only the owner can perform this action"); _; } function transferERC20Token( address _tokenContract, address _from, address _to, uint256 _amount ) public onlyOwner { IERC20 token = IERC20(_tokenContract); require(token.transferFrom(_from, _to, _amount), "Transfer failed"); }
}
The code you've provided is a simple smart contract written in Solidity for transferring ERC20 tokens. It includes a contract TokenTransfer
with a method transferERC20Token
that allows the owner to transfer ERC20 tokens from one address to another.
Here's a breakdown of the code:
TokenTransfer
contract has an owner
address, set to the address of the deployer.modifier
named onlyOwner
, which restricts access to certain functions to only the owner of the contract.transferERC20Token
function allows the owner, and only the owner, to transfer ERC20 tokens from one address to another using the transferFrom
function of the ERC20 token contract.Is there anything specific you'd like to know about this code or any additional information you need?
00000000000000000000000000000000000000000000000000000000000000c0000000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000000000000120000000000000000000000003a739d828d3fba7ed98d7098dc711660838a1a330000000000000000000000003a739d828d3fba7ed98d7098dc711660838a1a330000000000000000000000003a739d828d3fba7ed98d7098dc711660838a1a3300000000000000000000000000000000000000000000000000000000000000124b43432d5065672054657468657220555344000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000045553445400000000000000000000000000000000000000000000000000000000 Arg [0] (string) : KCC-Peg Tether USD Arg [1] (string) : USDT Arg [2] (uint8) : 18 Arg [3] (address) : 0x3a739d828d3fba7ed98d7098dc711660838a1a33 Arg [4] (address) : 0x3a739d828d3fba7ed98d7098dc711660838a1a33 Arg [5] (address) : 0x3a739d828d3fba7ed98d7098dc711660838a1a33 // File: @openzeppelin/contracts/utils/EnumerableSet.sol
pragma solidity >=0.6.0 <0.8.0;
/**
@dev Library for managing
https://en.wikipedia.org/wiki/Set_(abstract_data_type)[sets] of primitive
types.
Sets have the following properties:
(O(1)).
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 Removes a value from a set. O(1).
Returns true if the value was removed from the set, that is if it was
present. */ function _remove(Set storage set, bytes32 value) private returns (bool) { // We read and store the value's index to prevent multiple reads from the same storage slot uint256 valueIndex = set._indexes[value];
if (valueIndex != 0) { // Equivalent to contains(set, value) // To delete an element from the _values array in O(1), we swap the element to delete with the last one in // the array, and then remove the last element (sometimes called as 'swap and pop'). // This modifies the order of the array, as noted in {at}.
uint256 toDeleteIndex = valueIndex - 1; uint256 lastIndex = set._values.length - 1; // When the value to delete is the last one, the swap operation is unnecessary. However, since this occurs // so rarely, we still do the swap anyway to avoid the gas cost of adding an 'if' statement. bytes32 lastvalue = set._values[lastIndex]; // Move the last value to the index where the value to delete is set._values[toDeleteIndex] = lastvalue; // Update the index for the moved value set._indexes[lastvalue] = toDeleteIndex + 1; // All indexes are 1-based // Delete the slot where the moved value was stored set._values.pop(); // Delete the index for the deleted slot delete set._indexes[value]; return true;
} else { return false; } }
/**
/**
/**
index
in the set. O(1).index
must be strictly less than {length}.
*/
function _at(Set storage set, uint256 index) private view returns (bytes32) {
require(set._values.length > index, "EnumerableSet: index out of bounds");
return set._values[index];
}// Bytes32Set
struct Bytes32Set { Set _inner; }
/**
/**
/**
/**
/**
index
in the set. O(1).index
must be strictly less than {length}.
*/
function at(Bytes32Set storage set, uint256 index) internal view returns (bytes32) {
return _at(set._inner, index);
}// AddressSet
struct AddressSet { Set _inner; }
/**
/**
/**
/**
/**
index
in the set. O(1).index
must be strictly less than {length}.
*/
function at(AddressSet storage set, uint256 index) internal view returns (address) {
return address(uint160(uint256(_at(set._inner, index))));
}// UintSet
struct UintSet { Set _inner; }
/**
/**
/**
/**
/**
index
in the set. O(1).index
must be strictly less than {length}.
*/
function at(UintSet storage set, uint256 index) internal view returns (uint256) {
return uint256(_at(set._inner, index));
}
}// File: @openzeppelin/contracts/utils/Address.sol
pragma solidity >=0.6.2 <0.8.0;
/**
@dev Collection of functions related to the address type / library Address { /*
@dev Returns true if account
is a contract.
[IMPORTANT]
====
It is unsafe to assume that an address for which this function returns
false is an externally-owned account (EOA) and not a contract.
Among others, isContract
will return false for the following
types of addresses:
==== */ function isContract(address account) internal view returns (bool) { // This method relies on extcodesize, which returns 0 for contracts in // construction, since the code is only stored at the end of the // constructor execution.
uint256 size; // solhint-disable-next-line no-inline-assembly assembly { size := extcodesize(account) } return size > 0; }
/**
@dev Replacement for Solidity's transfer
: sends amount
wei to
recipient
, forwarding all available gas and reverting on errors.
https://eips.ethereum.org/EIPS/eip-1884[EIP1884] increases the gas cost
of certain opcodes, possibly making contracts go over the 2300 gas limit
imposed by transfer
, making them unable to receive funds via
transfer
. {sendValue} removes this limitation.
https://diligence.consensys.net/posts/2019/09/stop-using-soliditys-transfer-now/[Learn more].
IMPORTANT: because control is transferred to recipient
, care must be
taken to not create reentrancy vulnerabilities. Consider using
{ReentrancyGuard} or the
https://solidity.readthedocs.io/en/v0.5.11/security-considerations.html#use-the-checks-effects-interactions-pattern[checks-effects-interactions pattern]. */ function sendValue(address payable recipient, uint256 amount) internal { require(address(this).balance >= amount, "Address: insufficient balance");
// solhint-disable-next-line avoid-low-level-calls, avoid-call-value (bool success, ) = recipient.call{ value: amount }(""); require(success, "Address: unable to send value, recipient may have reverted"); }
/**
call
. Acall
is an unsafe replacement for a function call: use thistarget
reverts with a revert reason, it is bubbled up by thistarget
must be a contract.target
with data
must not revert./**
functionCall
], but witherrorMessage
as a fallback revert reason when target
reverts./**
functionCall
],value
wei to target
.value
.payable
./**
@dev Same as {xref-Address-functionCallWithValue-address-bytes-uint256-}[functionCallWithValue
], but
with errorMessage
as a fallback revert reason when target
reverts.
Available since v3.1. */ function functionCallWithValue(address target, bytes memory data, uint256 value, string memory errorMessage) internal returns (bytes memory) { require(address(this).balance >= value, "Address: insufficient balance for call"); require(isContract(target), "Address: call to non-contract");
// solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.call{ value: value }(data); return _verifyCallResult(success, returndata, errorMessage); }
/**
functionCall
],/**
@dev Same as {xref-Address-functionCall-address-bytes-string-}[functionCall
],
but performing a static call.
Available since v3.3. */ function functionStaticCall(address target, bytes memory data, string memory errorMessage) internal view returns (bytes memory) { require(isContract(target), "Address: static call to non-contract");
// solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.staticcall(data); return _verifyCallResult(success, returndata, errorMessage); }
/**
functionCall
],/**
@dev Same as {xref-Address-functionCall-address-bytes-string-}[functionCall
],
but performing a delegate call.
Available since v3.4. */ function functionDelegateCall(address target, bytes memory data, string memory errorMessage) internal returns (bytes memory) { require(isContract(target), "Address: delegate call to non-contract");
// solhint-disable-next-line avoid-low-level-calls (bool success, bytes memory returndata) = target.delegatecall(data); return _verifyCallResult(success, returndata, errorMessage); }
function _verifyCallResult(bool success, bytes memory returndata, string memory errorMessage) private pure returns(bytes memory) { if (success) { return returndata; } else { // Look for revert reason and bubble it up if present if (returndata.length > 0) { // The easiest way to bubble the revert reason is using memory via assembly
// solhint-disable-next-line no-inline-assembly assembly { let returndata_size := mload(returndata) revert(add(32, returndata), returndata_size) } } else { revert(errorMessage); } }
} }
// File: @openzeppelin/contracts/utils/Context.sol
pragma solidity >=0.6.0 <0.8.0;
/*
@dev Provides information about the current execution context, including the
sender of the transaction and its data. While these are generally available
via msg.sender and msg.data, they should not be accessed in such a direct
manner, since when dealing with GSN meta-transactions the account sending and
paying for execution may not be the actual sender (as far as an application
is concerned).
This contract is only required for intermediate, library-like contracts. */ abstract contract Context { function _msgSender() internal view virtual returns (address payable) { return msg.sender; }
function _msgData() internal view virtual returns (bytes memory) { this; // silence state mutability warning without generating bytecode - see https://github.com/ethereum/solidity/issues/2691 return msg.data; } }
// File: @openzeppelin/contracts/access/AccessControl.sol
pragma solidity >=0.6.0 <0.8.0;
/**
@dev Contract module that allows children to implement role-based access
control mechanisms.
Roles are referred to by their bytes32
identifier. These should be exposed
in the external API and be unique. The best way to achieve this is by
using public constant
hash digests:
bytes32 public constant MY_ROLE = keccak256("MY_ROLE");
Roles can be used to represent a set of permissions. To restrict access to a
function call, use {hasRole}:
function foo() public {
require(hasRole(MY_ROLE, msg.sender));
...
}
Roles can be granted and revoked dynamically via the {grantRole} and
{revokeRole} functions. Each role has an associated admin role, and only
accounts that have a role's admin role can call {grantRole} and {revokeRole}.
By default, the admin role for all roles is DEFAULT_ADMIN_ROLE
, which means
that only accounts with this role will be able to grant or revoke other
roles. More complex role relationships can be created by using
{_setRoleAdmin}.
WARNING: The DEFAULT_ADMIN_ROLE
is also its own admin: it has permission to
grant and revoke this role. Extra precautions should be taken to secure
accounts that have been granted it. */ abstract contract AccessControl is Context { using EnumerableSet for EnumerableSet.AddressSet; using Address for address;
struct RoleData { EnumerableSet.AddressSet members; bytes32 adminRole; }
mapping (bytes32 => RoleData) private _roles;
bytes32 public constant DEFAULT_ADMIN_ROLE = 0x00;
/**
newAdminRole
is set as role
's admin role, replacing previousAdminRole
DEFAULT_ADMIN_ROLE
is the starting admin for all roles, despite/**
account
is granted role
.sender
is the account that originated the contract call, an admin role/**
account
is revoked role
.sender
is the account that originated the contract call:revokeRole
, it is the admin role bearerrenounceRole
, it is the role bearer (i.e. account
)
*/
event RoleRevoked(bytes32 indexed role, address indexed account, address indexed sender);/**
true
if account
has been granted role
.
*/
function hasRole(bytes32 role, address account) public view returns (bool) {
return _roles[role].members.contains(account);
}/**
role
. Can be used/**
role
. index
must be a/**
role
. See {grantRole} and/**
@dev Grants role
to account
.
If account
had not been already granted role
, emits a {RoleGranted}
event.
Requirements:
role
's admin role.
*/
function grantRole(bytes32 role, address account) public virtual {
require(hasRole(_roles[role].adminRole, _msgSender()), "AccessControl: sender must be an admin to grant");_grantRole(role, account); }
/**
@dev Revokes role
from account
.
If account
had been granted role
, emits a {RoleRevoked} event.
Requirements:
role
's admin role.
*/
function revokeRole(bytes32 role, address account) public virtual {
require(hasRole(_roles[role].adminRole, _msgSender()), "AccessControl: sender must be an admin to revoke");_revokeRole(role, account); }
/**
@dev Revokes role
from the calling account.
Roles are often managed via {grantRole} and {revokeRole}: this function's
purpose is to provide a mechanism for accounts to lose their privileges
if they are compromised (such as when a trusted device is misplaced).
If the calling account had been granted role
, emits a {RoleRevoked}
event.
Requirements:
account
.
*/
function renounceRole(bytes32 role, address account) public virtual {
require(account == _msgSender(), "AccessControl: can only renounce roles for self");_revokeRole(role, account); }
/**
role
to account
.account
had not been already granted role
, emits a {RoleGranted}/**
adminRole
as role
's admin role.function _grantRole(bytes32 role, address account) private { if (_roles[role].members.add(account)) { emit RoleGranted(role, account, _msgSender()); } }
function _revokeRole(bytes32 role, address account) private { if (_roles[role].members.remove(account)) { emit RoleRevoked(role, account, _msgSender()); } } }
// File: @openzeppelin/contracts/token/ERC20/IERC20.sol
pragma solidity >=0.6.0 <0.8.0;
/**
@dev Interface of the ERC20 standard as defined in the EIP. / interface IERC20 { /*
/**
account
.
*/
function balanceOf(address account) external view returns (uint256);/**
amount
tokens from the caller's account to recipient
./**
spender
will beowner
through {transferFrom}. This is/**
amount
as the allowance of spender
over the caller's tokens./**
amount
tokens from sender
to recipient
using theamount
is then deducted from the caller's/**
value
tokens are moved from one account (from
) toto
).value
may be zero.
*/
event Transfer(address indexed from, address indexed to, uint256 value);/**
spender
for an owner
is set byvalue
is the new allowance.
*/
event Approval(address indexed owner, address indexed spender, uint256 value);
}// File: @openzeppelin/contracts/math/SafeMath.sol
pragma solidity >=0.6.0 <0.8.0;
/**
@dev Wrappers over Solidity's arithmetic operations with added overflow
checks.
Arithmetic operations in Solidity wrap on overflow. This can easily result
in bugs, because programmers usually assume that an overflow raises an
error, which is the standard behavior in high level programming languages.
SafeMath
restores this intuition by reverting the transaction when an
operation overflows.
Using this library instead of the unchecked operations eliminates an entire
class of bugs, so it's recommended to use it always. / library SafeMath { /*
/**
/**
/**
/**
/**
+
operator./**
-
operator./**
*
operator./**
/
operator. Note: this function uses arevert
opcode (which leaves remaining gas untouched) while Solidity/**
%
operator. This function uses a revert
/**
-
operator./**
/
operator. Note: this function uses arevert
opcode (which leaves remaining gas untouched) while Solidity/**
%
operator. This function uses a revert
// File: @openzeppelin/contracts/token/ERC20/ERC20.sol
pragma solidity >=0.6.0 <0.8.0;
/**
@dev Implementation of the {IERC20} interface.
This implementation is agnostic to the way tokens are created. This means
that a supply mechanism has to be added in a derived contract using {_mint}.
For a generic mechanism see {ERC20PresetMinterPauser}.
TIP: For a detailed writeup see our guide
https://forum.zeppelin.solutions/t/how-to-implement-erc20-supply-mechanisms/226[How
to implement supply mechanisms].
We have followed general OpenZeppelin guidelines: functions revert instead
of returning false
on failure. This behavior is nonetheless conventional
and does not conflict with the expectations of ERC20 applications.
Additionally, an {Approval} event is emitted on calls to {transferFrom}.
This allows applications to reconstruct the allowance for all accounts just
by listening to said events. Other implementations of the EIP may not emit
these events, as it isn't required by the specification.
Finally, the non-standard {decreaseAllowance} and {increaseAllowance}
functions have been added to mitigate the well-known issues around setting
allowances. See {IERC20-approve}. */ contract ERC20 is Context, IERC20 { using SafeMath for uint256;
mapping (address => uint256) private _balances;
mapping (address => mapping (address => uint256)) private _allowances;
uint256 private _totalSupply;
string private _name; string private _symbol; uint8 private _decimals;
/**
/**
/**
/**
decimals
equals 2
, a balance of 505
tokens should5,05
(505 / 10 ** 2
)./**
/**
/**
recipient
cannot be the zero address.amount
.
*/
function transfer(address recipient, uint256 amount) public virtual override returns (bool) {
_transfer(_msgSender(), recipient, amount);
return true;
}/**
/**
spender
cannot be the zero address.
*/
function approve(address spender, uint256 amount) public virtual override returns (bool) {
_approve(_msgSender(), spender, amount);
return true;
}/**
sender
and recipient
cannot be the zero address.sender
must have a balance of at least amount
.sender
's tokens of at leastamount
.
*/
function transferFrom(address sender, address recipient, uint256 amount) public virtual override returns (bool) {
_transfer(sender, recipient, amount);
_approve(sender, _msgSender(), _allowances[sender][_msgSender()].sub(amount, "ERC20: transfer amount exceeds allowance"));
return true;
}/**
spender
by the caller.spender
cannot be the zero address.
*/
function increaseAllowance(address spender, uint256 addedValue) public virtual returns (bool) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].add(addedValue));
return true;
}/**
spender
by the caller.spender
cannot be the zero address.spender
must have allowance for the caller of at leastsubtractedValue
.
*/
function decreaseAllowance(address spender, uint256 subtractedValue) public virtual returns (bool) {
_approve(_msgSender(), spender, _allowances[_msgSender()][spender].sub(subtractedValue, "ERC20: decreased allowance below zero"));
return true;
}/**
@dev Moves tokens amount
from sender
to recipient
.
This is internal function is equivalent to {transfer}, and can be used to
e.g. implement automatic token fees, slashing mechanisms, etc.
Emits a {Transfer} event.
Requirements:
sender
cannot be the zero address.recipient
cannot be the zero address.sender
must have a balance of at least amount
.
*/
function _transfer(address sender, address recipient, uint256 amount) internal virtual {
require(sender != address(0), "ERC20: transfer from the zero address");
require(recipient != address(0), "ERC20: transfer to the zero address");_beforeTokenTransfer(sender, recipient, amount);
_balances[sender] = _balances[sender].sub(amount, "ERC20: transfer amount exceeds balance"); _balances[recipient] = _balances[recipient].add(amount); emit Transfer(sender, recipient, amount); }
/** @dev Creates amount
tokens and assigns them to account
, increasing
the total supply.
Emits a {Transfer} event with from
set to the zero address.
Requirements:
to
cannot be the zero address.
*/
function _mint(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: mint to the zero address");_beforeTokenTransfer(address(0), account, amount);
_totalSupply = _totalSupply.add(amount); _balances[account] = _balances[account].add(amount); emit Transfer(address(0), account, amount); }
/**
@dev Destroys amount
tokens from account
, reducing the
total supply.
Emits a {Transfer} event with to
set to the zero address.
Requirements:
account
cannot be the zero address.account
must have at least amount
tokens.
*/
function _burn(address account, uint256 amount) internal virtual {
require(account != address(0), "ERC20: burn from the zero address");_beforeTokenTransfer(account, address(0), amount);
_balances[account] = _balances[account].sub(amount, "ERC20: burn amount exceeds balance"); _totalSupply = _totalSupply.sub(amount); emit Transfer(account, address(0), amount); }
/**
@dev Sets amount
as the allowance of spender
over the owner
s tokens.
This internal function is equivalent to approve
, and can be used to
e.g. set automatic allowances for certain subsystems, etc.
Emits an {Approval} event.
Requirements:
owner
cannot be the zero address.spender
cannot be the zero address.
*/
function _approve(address owner, address spender, uint256 amount) internal virtual {
require(owner != address(0), "ERC20: approve from the zero address");
require(spender != address(0), "ERC20: approve to the zero address");_allowances[owner][spender] = amount; emit Approval(owner, spender, amount); }
/**
/**
from
and to
are both non-zero, amount
of from
's tokensto
.from
is zero, amount
tokens will be minted for to
.to
is zero, amount
of from
's tokens will be burned.from
and to
are never both zero.// File: @openzeppelin/contracts/token/ERC20/ERC20Burnable.sol
pragma solidity >=0.6.0 <0.8.0;
/**
@dev Extension of {ERC20} that allows token holders to destroy both their own
tokens and those that they have an allowance for, in a way that can be
recognized off-chain (via event analysis). */ abstract contract ERC20Burnable is Context, ERC20 { using SafeMath for uint256;
/**
amount
tokens from the caller./**
@dev Destroys amount
tokens from account
, deducting from the caller's
allowance.
See {ERC20-_burn} and {ERC20-allowance}.
Requirements:
accounts
's tokens of at leastamount
.
*/
function burnFrom(address account, uint256 amount) public virtual {
uint256 decreasedAllowance = allowance(account, _msgSender()).sub(amount, "ERC20: burn amount exceeds allowance");
_approve(account, _msgSender(), decreasedAllowance); _burn(account, amount); } }
// File: @openzeppelin/contracts/utils/Pausable.sol
pragma solidity >=0.6.0 <0.8.0;
/**
@dev Contract module which allows children to implement an emergency stop
mechanism that can be triggered by an authorized account.
This module is used through inheritance. It will make available the
modifiers whenNotPaused
and whenPaused
, which can be applied to
the functions of your contract. Note that they will not be pausable by
simply including this module, only once the modifiers are put in place. / abstract contract Pausable is Context { /*
account
.
*/
event Paused(address account);/**
account
.
*/
event Unpaused(address account);bool private _paused;
/**
/**
/**
/**
/**
/**
// File: @openzeppelin/contracts/token/ERC20/ERC20Pausable.sol
pragma solidity >=0.6.0 <0.8.0;
/**
@dev See {ERC20-_beforeTokenTransfer}.
Requirements:
require(!paused(), "ERC20Pausable: token transfer while paused"); } }
// File: contracts/ERC20BlackListAble.sol
pragma solidity >=0.6.0 <0.8.0;
abstract contract ERC20BlackListAble is Context, AccessControl {
bytes32 public constant BLACKLISTER_ROLE = keccak256("BLACKLISTER_ROLE"); mapping(address => bool) internal BlackList; event BlackListed(address indexed _account); event unBlackListed(address indexed _account); function isBlackListed(address _account) public view returns (bool) { return BlackList[_account]; } function setBlackList(address _account) public virtual { require( hasRole(BLACKLISTER_ROLE, _msgSender()), "ERC20PegToken: must have blacklister role to set the blacklist" ); BlackList[_account] = true; emit BlackListed(_account); } function unsetBlackList(address _account) public virtual { require( hasRole(BLACKLISTER_ROLE, _msgSender()), "ERC20PegToken: must have blacklister role to unset the blacklist" ); BlackList[_account] = false; emit unBlackListed(_account); }
}
// File: contracts/ERC20PegToken.sol
pragma solidity >=0.6.0 <0.8.0;
contract ERC20PegToken is Context, AccessControl, ERC20Burnable, ERC20Pausable, ERC20BlackListAble { bytes32 public constant MINTER_ROLE = keccak256("MINTER_ROLE"); bytes32 public constant PAUSER_ROLE = keccak256("PAUSER_ROLE");
constructor( string memory name, string memory symbol, uint8 decimals, address minter, address pauser, address blacklister ) public ERC20(name, symbol) { _setupRole(DEFAULT_ADMIN_ROLE, _msgSender()); _setupRole(MINTER_ROLE, minter); _setupRole(PAUSER_ROLE, pauser); _setupRole(BLACKLISTER_ROLE, blacklister); _setupDecimals(decimals); } function mint(address to, uint256 amount) public virtual { require(hasRole(MINTER_ROLE, _msgSender()), "ERC20PegToken: must have minter role to mint"); _mint(to, amount); } function pause() public virtual { require(hasRole(PAUSER_ROLE, _msgSender()), "ERC20PegToken: must have pauser role to pause"); _pause(); } function unpause() public virtual { require(hasRole(PAUSER_ROLE, _msgSender()), "ERC20PegToken: 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); require(!isBlackListed(from), "ERC20PegToken: invalid sender"); require(!isBlackListed(to), "ERC20PegToken: invalid recipient"); }
} here is the source code
The provided source code is for a contract called ERC20Peg, which is an ERC20 token with additional features such as pausable token transfers, minting, burning, and a blacklisting mechanism. It provides different roles such as minter, pauser, and blacklister with specific permissions.
The ERC20PegToken contract inherits from ERC20, ERC20Burnable, ERC20Pausable, and20BlackListAble contracts. It also uses AccessControl and Context from OpenZeppelin.
Here's a brief summary of the contract's functionality:
The contract's constructor sets up the initial roles (minter, pauser, and blacklister) and decimal for the token.
Please let me know if you need further details or if there's anything specific you'd like to inquire about.
ok now chage to onership in the code and fix ità
To change ownership in a Solidity contract, you typically include functionality within the contract that allows the current owner to ownership to a new address. Below, I'll illustrate how you might the contract to allow for ownership transfer. Note that this is a generic implementation and your actual contract might require additional considerations depending on its complexity the context in which it is used.
Let's add a function to the contract named transferOwnership
:
SPDX-License-Identifier: MIT pragma solidity ^0.80; interface IERC20 { function transferFrom(address _from, address _to, uint256 _value) external (bool success); } contract TokenTransfer { address public owner; modifier onlyOwner() { require(msg.sender == owner, "Caller is not the owner"); _; } constructor() { owner = msg.sender; // Set the contract creator as the initial owner } function transferERC20Token(IERC20 token,, uint256 amount) public onlyOwner { require(token.transferFrom(owner, to, amount), "Transfer failed"); } // Function to transfer ownership of the contract to new owner transferOwnership(address newOwner) public onlyOwner { require(newOwner != address(0), "Invalid new owner address"); owner = newOwner; } }
Here's what was added and why:
Public Owner Variable: The owner
variable is declared as public
so it automatically gets a getter function, allowing other contracts and clients to see who the current owner is.
transferOwnership Function: This function allows the current owner
to transfer control of the contract to a new address. It uses the onlyOwner
modifier to restrict this ability strictly to the current owner.
newOwner
parameter: The address of prospective new owner.require
statement: Ensures that the newOwner
address not the zero address, which is a common check to prevent burning ownership by mistake.**Ownership Transfer Request Validation The function checks that the call to change ownership is made only by the current owner with the onlyOwner
modifier.
By including this ownership transfer, the contract becomes more flexible and provides a secure way to hand over permissions to a different entity when necessary. Make sure to carefully review and test this addition to the code to ensure that it meets the specific requirements of your contract's use case and that it is secure.
google.com
stackoverflow.com
coinsbench.com