10 changed files
script | ||
DeployStablecoin.s.sol | ||
src | ||
SettableERC2771ContextUpgradeable.sol + | ||
Stablecoin.sol | ||
test | ||
utils | ||
MockERC20.sol | ||
MockERC2771Upgradeable.sol + | ||
DeployStablecoin.t.sol | ||
SettableERC2771ContextUpgradeable.t.sol + | ||
Stablecoin.t.sol | ||
.gitignore | ||
README.md | ||
Add comment 10 contract DeployStablecoinScript is Script {
Add comment 11 string internal constant NAME = "$ Token";
Add comment 12 string internal constant SYMBOL = "$";
Add comment 13 Plus address internal constant TRUSTED_FORWARDER = address(0);
Add comment 14 Plus address internal constant BURNER = address(0);
Add comment 13 15
Add comment 14 16 function setUp() public {}
Add comment 15 17
Add comment 21 23 TransparentUpgradeableProxy proxy = new TransparentUpgradeableProxy(
Add comment 22 24 address(impl),
Add comment 23 25 address(proxyAdmin),
Add comment 24 Minus abi.encodeWithSignature("initialize(string,string)", NAME, SYMBOL)
Add comment 26 Plus abi.encodeWithSignature("initialize(string,string,address,address)", NAME, SYMBOL, TRUSTED_FORWARDER)
Add comment 25 27 );
Add comment 26 Minus impl.initialize(NAME, SYMBOL); // prevent uninitialized implementation
Add comment 28 Plus impl.initialize(NAME, SYMBOL, BURNER, TRUSTED_FORWARDER); // prevent uninitialized implementation
Add comment 27 29
Add comment 28 30 vm.stopBroadcast();
Add comment 29 31 }
SettableERC2771ContextUpgradeable.sol
/src/SettableERC2771ContextUpgradeable.sol+49/src/SettableERC2771ContextUpgradeable.sol
Add comment 1 Plus // SPDX-License-Identifier: MIT
Add comment 2 Plus
Add comment 3 Plus pragma solidity ^0.8.0;
Add comment 4 Plus
Add comment 5 Plus import "openzeppelin-contracts-upgradeable/contracts/metatx/ERC2771ContextUpgradeable.sol";
Add comment 6 Plus
Add comment 7 Plus abstract contract SettableERC2771ContextUpgradeable is ERC2771ContextUpgradeable {
Add comment 8 Plus address private _forwarder;
Add comment 9 Plus
Add comment 10 Plus event TrustForwarderUpdated(address indexed previousForwarder, address indexed newForwarder);
Add comment 11 Plus
Add comment 12 Plus constructor() ERC2771ContextUpgradeable(address(0)) {}
Add comment 13 Plus
Add comment 14 Plus /**
Add comment 15 Plus * @dev Sets the values for {forwarder}.
Add comment 16 Plus */
Add comment 17 Plus function __SettableERC2771Context_init(address forwarder_) internal onlyInitializing {
Add comment 18 Plus __SettableERC2771Context_init_unchained(forwarder_);
Add comment 19 Plus }
Add comment 20 Plus
Add comment 21 Plus function __SettableERC2771Context_init_unchained(address forwarder_) internal onlyInitializing {
Add comment 22 Plus _forwarder = forwarder_;
Add comment 23 Plus }
Add comment 24 Plus
Add comment 25 Plus /**
Add comment 26 Plus * @dev Returns the address of the trusted forwarder.
Add comment 27 Plus */
Add comment 28 Plus function trustedForwarder() public view virtual returns (address) {
Add comment 29 Plus return _forwarder;
Add comment 30 Plus }
Add comment 31 Plus
Add comment 32 Plus /**
Add comment 33 Plus * @dev Indicates whether any particular address is the trusted forwarder.
Add comment 34 Plus */
Add comment 35 Plus function isTrustedForwarder(address forwarder_) public view virtual override returns (bool) {
Add comment 36 Plus return forwarder_ == trustedForwarder();
Add comment 37 Plus }
Add comment 38 Plus
Add comment 39 Plus /**
Add comment 40 Plus * @dev Sets trusted forwarder.
Add comment 41 Plus * Internal function without access restriction.
Add comment 42 Plus */
Add comment 43 Plus function _setTrustForwarder(address forwarder_) internal virtual {
Add comment 44 Plus address prevForwarder = _forwarder;
Add comment 45 Plus _forwarder = forwarder_;
Add comment 46 Plus emit TrustForwarderUpdated(prevForwarder, forwarder_);
Add comment 47 Plus }
Add comment 48 Plus }
Add comment 49 Plus
Add comment 5 import "openzeppelin-contracts-upgradeable/contracts/token/ERC20/extensions/draft-ERC20PermitUpgradeable.sol";
Add comment 6 import "openzeppelin-contracts-upgradeable/contracts/access/Ownable2StepUpgradeable.sol";
Add comment 7 import "openzeppelin-contracts-upgradeable/contracts/security/PausableUpgradeable.sol";
Add comment 8 Plus import "./SettableERC2771ContextUpgradeable.sol";
Add comment 8 9
Add comment 9 Minus contract Stablecoin is ERC20PermitUpgradeable, Ownable2StepUpgradeable, PausableUpgradeable {
Add comment 10 Plus contract Stablecoin is ERC20PermitUpgradeable, Ownable2StepUpgradeable, PausableUpgradeable, SettableERC2771ContextUpgradeable {
Add comment 10 11
Add comment 12 Plus address public burner;
Add comment 11 13 mapping(address => bool) public frozen;
Add comment 12 14
Add comment 13 15 event Mint(address indexed caller, address indexed to, uint256 amount);
Add comment 14 16 event Burn(address indexed caller, address indexed from, uint256 amount);
Add comment 15 17 event Freeze(address indexed caller, address indexed account);
Add comment 16 18 event Unfreeze(address indexed caller, address indexed account);
Add comment 19 Plus event BurnerUpdated(address indexed previousBurner, address indexed newBurner);
Add comment 17 20
Add comment 18 Minus function initialize(string memory _name, string memory _symbol) public initializer {
Add comment 21 Plus function initialize(string memory _name, string memory _symbol, address _burner, address _forwarder) public initializer {
Add comment 19 22 __Context_init();
Add comment 20 23 __ERC20_init(_name, _symbol);
Add comment 21 24 __ERC20Permit_init(_name);
Add comment 22 25 __Ownable2Step_init();
Add comment 23 26 __Pausable_init();
Add comment 27 Plus __SettableERC2771Context_init(_forwarder);
Add comment 28 Plus burner = _burner;
Add comment 24 29 }
Add comment 25 30
Add comment 26 31 /**
Add comment 32 Plus * @dev Throws if called by any account other than the burner.
Add comment 33 Plus */
Add comment 34 Plus modifier onlyBurner() {
Add comment 35 Plus require(burner == _msgSender(), "Caller is not the burner");
Add comment 36 Plus _;
Add comment 37 Plus }
Add comment 38 Plus
Add comment 39 Plus /**
Add comment 27 40 * @dev Throws if account is frozen.
Add comment 28 41 */
Add comment 29 42 modifier notFrozen(address account) {
Add comment 33 46
Add comment 34 47 /**
Add comment 35 48 * @dev See {ERC20-_mint}.
Add comment 49 Plus * @param account Account address
Add comment 36 50 * @param amount Mint amount
Add comment 37 51 * @return True if successful
Add comment 38 52 * Can only be called by the current owner.
Add comment 39 53 */
Add comment 40 Minus function mint(uint256 amount) external onlyOwner returns (bool) {
Add comment 41 Minus _mint(_msgSender(), amount);
Add comment 42 Minus emit Mint(_msgSender(), _msgSender(), amount);
Add comment 54 Plus function mint(address account, uint256 amount) external onlyOwner returns (bool) {
Add comment 55 Plus _mint(account, amount);
Add comment 56 Plus emit Mint(_msgSender(), account, amount);
Add comment 43 57 return true;
Add comment 44 58 }
Add comment 45 59
Add comment 47 61 * @dev See {ERC20-_burn}.
Add comment 48 62 * @param amount Burn amount
Add comment 49 63 * @return True if successful
Add comment 50 Minus * Can only be called by the current owner.
Add comment 64 Plus * Can only be called by the burner.
Add comment 51 65 */
Add comment 52 Minus function burn(uint256 amount) external onlyOwner returns (bool) {
Add comment 66 Plus function burn(uint256 amount) external onlyBurner returns (bool) {
Add comment 53 67 _burn(_msgSender(), amount);
Add comment 54 68 emit Burn(_msgSender(), _msgSender(), amount);
Add comment 55 69 return true;
Add comment 90 104 }
Add comment 91 105
Add comment 92 106 /**
Add comment 107 Plus * @dev Sets trusted forwarder.
Add comment 108 Plus * Can only be called by the current owner.
Add comment 109 Plus */
Add comment 110 Plus function setTrustForwarder(address forwarder_) external onlyOwner {
Add comment 111 Plus super._setTrustForwarder(forwarder_);
Add comment 112 Plus }
Add comment 113 Plus
Add comment 114 Plus /**
Add comment 115 Plus * @dev Sets burner.
Add comment 116 Plus * Can only be called by the current owner.
Add comment 117 Plus */
Add comment 118 Plus function setBurner(address _burner) external onlyOwner {
Add comment 119 Plus address prevBurner = _burner;
Add comment 120 Plus burner = _burner;
Add comment 121 Plus emit BurnerUpdated(prevBurner, _burner);
Add comment 122 Plus }
Add comment 123 Plus
Add comment 124 Plus /**
Add comment 93 125 * @dev See {ERC20-_transfer}.
Add comment 94 126 * @param from Source address
Add comment 95 127 * @param to Destination address
Add comment 108 140 function _approve(address owner, address spender, uint256 amount) internal override whenNotPaused notFrozen(owner) notFrozen(spender) {
Add comment 109 141 super._approve(owner, spender, amount);
Add comment 110 142 }
Add comment 143 Plus
Add comment 144 Plus function _msgSender() internal view override(ContextUpgradeable, ERC2771ContextUpgradeable) returns (address) {
Add comment 145 Plus return super._msgSender();
Add comment 146 Plus }
Add comment 147 Plus
Add comment 148 Plus function _msgData() internal view override(ContextUpgradeable, ERC2771ContextUpgradeable) returns (bytes calldata) {
Add comment 149 Plus return super._msgData();
Add comment 150 Plus }
Add comment 111 151 }
Add comment 112 152
MockERC2771Upgradeable.sol
/test/utils/MockERC2771Upgradeable.sol/test/utils/MockERC2771Upgradeable.sol
SettableERC2771ContextUpgradeable.t.sol
/test/SettableERC2771ContextUpgradeable.t.sol/test/SettableERC2771ContextUpgradeable.t.sol