mirror of https://github.com/logos-co/staking.git
add optimism minime
This commit is contained in:
parent
17d1816570
commit
c1570fa471
|
@ -0,0 +1,34 @@
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
pragma solidity ^0.8.0;
|
||||||
|
|
||||||
|
import { IERC165 } from "@openzeppelin/contracts/utils/introspection/IERC165.sol";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @title IOptimismMintableERC20
|
||||||
|
* @notice This interface is available on the OptimismMintableERC20 contract. We declare it as a
|
||||||
|
* separate interface so that it can be used in custom implementations of
|
||||||
|
* OptimismMintableERC20.
|
||||||
|
*/
|
||||||
|
interface IOptimismMintableERC20 is IERC165 {
|
||||||
|
function remoteToken() external view returns (address);
|
||||||
|
|
||||||
|
function bridge() external returns (address);
|
||||||
|
|
||||||
|
function mint(address _to, uint256 _amount) external;
|
||||||
|
|
||||||
|
function burn(address _from, uint256 _amount) external;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @custom:legacy
|
||||||
|
* @title ILegacyMintableERC20
|
||||||
|
* @notice This interface was available on the legacy L2StandardERC20 contract. It remains available
|
||||||
|
* on the OptimismMintableERC20 contract for backwards compatibility.
|
||||||
|
*/
|
||||||
|
interface ILegacyMintableERC20 is IERC165 {
|
||||||
|
function l1Token() external view returns (address);
|
||||||
|
|
||||||
|
function mint(address _to, uint256 _amount) external;
|
||||||
|
|
||||||
|
function burn(address _from, uint256 _amount) external;
|
||||||
|
}
|
|
@ -0,0 +1,119 @@
|
||||||
|
|
||||||
|
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
pragma solidity 0.8.18;
|
||||||
|
|
||||||
|
import { MiniMeToken } from "../token/MiniMeToken.sol";
|
||||||
|
import { IERC165 } from "@openzeppelin/contracts/utils/introspection/IERC165.sol";
|
||||||
|
import { ILegacyMintableERC20, IOptimismMintableERC20 } from "./IOptimismMintableERC20.sol";
|
||||||
|
import { Semver } from "./Semver.sol";
|
||||||
|
|
||||||
|
/// @title OptimismMintableMiniMeToken
|
||||||
|
/// @notice OptimismMintableMiniMeToken is a standard extension of the base MiniMeToken token contract designed
|
||||||
|
/// to allow the StandardBridge contracts to mint and burn tokens. This makes it possible to
|
||||||
|
/// use an OptimismMintablERC20 as the L2 representation of an L1 token, or vice-versa.
|
||||||
|
/// Designed to be backwards compatible with the older StandardL2ERC20 token which was only
|
||||||
|
/// meant for use on L2.
|
||||||
|
contract OptimismMintableMiniMeToken is IOptimismMintableERC20, ILegacyMintableERC20, MiniMeToken, Semver {
|
||||||
|
/// @notice Address of the corresponding version of this token on the remote chain.
|
||||||
|
address public immutable REMOTE_TOKEN;
|
||||||
|
|
||||||
|
/// @notice Address of the StandardBridge on this network.
|
||||||
|
address public immutable BRIDGE;
|
||||||
|
|
||||||
|
/// @notice Emitted whenever tokens are minted for an account.
|
||||||
|
/// @param account Address of the account tokens are being minted for.
|
||||||
|
/// @param amount Amount of tokens minted.
|
||||||
|
event Mint(address indexed account, uint256 amount);
|
||||||
|
|
||||||
|
/// @notice Emitted whenever tokens are burned from an account.
|
||||||
|
/// @param account Address of the account tokens are being burned from.
|
||||||
|
/// @param amount Amount of tokens burned.
|
||||||
|
event Burn(address indexed account, uint256 amount);
|
||||||
|
|
||||||
|
/// @notice A modifier that only allows the bridge to call
|
||||||
|
modifier onlyBridge() {
|
||||||
|
require(msg.sender == BRIDGE, "OptimismMintableMiniMeToken: only bridge can mint and burn");
|
||||||
|
_;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @custom:semver 1.0.1
|
||||||
|
/// @param _bridge Address of the L2 standard bridge.
|
||||||
|
/// @param _remoteToken Address of the corresponding L1 token.
|
||||||
|
/// @param _tokenName ERC20 name.
|
||||||
|
/// @param _tokenSymbol ERC20 symbol.
|
||||||
|
constructor(
|
||||||
|
address _bridge,
|
||||||
|
address _remoteToken,
|
||||||
|
address _tokenFactory,
|
||||||
|
address payable _parentToken,
|
||||||
|
uint _parentSnapShotBlock,
|
||||||
|
string memory _tokenName,
|
||||||
|
uint8 _decimalUnits,
|
||||||
|
string memory _tokenSymbol,
|
||||||
|
bool _transfersEnabled
|
||||||
|
) MiniMeToken(_tokenFactory, _parentToken, _parentSnapShotBlock, _tokenName, _decimalUnits, _tokenSymbol, _transfersEnabled) Semver(1, 0, 1) {
|
||||||
|
REMOTE_TOKEN = _remoteToken;
|
||||||
|
BRIDGE = _bridge;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @notice Allows the StandardBridge on this network to mint tokens.
|
||||||
|
/// @param _to Address to mint tokens to.
|
||||||
|
/// @param _amount Amount of tokens to mint.
|
||||||
|
function mint(address _to, uint256 _amount)
|
||||||
|
external
|
||||||
|
override(IOptimismMintableERC20, ILegacyMintableERC20)
|
||||||
|
onlyBridge
|
||||||
|
{
|
||||||
|
_mint(_to, _amount);
|
||||||
|
emit Mint(_to, _amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @notice Allows the StandardBridge on this network to burn tokens.
|
||||||
|
/// @param _from Address to burn tokens from.
|
||||||
|
/// @param _amount Amount of tokens to burn.
|
||||||
|
function burn(address _from, uint256 _amount)
|
||||||
|
external
|
||||||
|
override(IOptimismMintableERC20, ILegacyMintableERC20)
|
||||||
|
onlyBridge
|
||||||
|
{
|
||||||
|
_burn(_from, _amount);
|
||||||
|
emit Burn(_from, _amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @notice ERC165 interface check function.
|
||||||
|
/// @param _interfaceId Interface ID to check.
|
||||||
|
/// @return Whether or not the interface is supported by this contract.
|
||||||
|
function supportsInterface(bytes4 _interfaceId) external pure returns (bool) {
|
||||||
|
bytes4 iface1 = type(IERC165).interfaceId;
|
||||||
|
// Interface corresponding to the legacy L2StandardERC20.
|
||||||
|
bytes4 iface2 = type(ILegacyMintableERC20).interfaceId;
|
||||||
|
// Interface corresponding to the updated OptimismMintableMiniMeToken (this contract).
|
||||||
|
bytes4 iface3 = type(IOptimismMintableERC20).interfaceId;
|
||||||
|
return _interfaceId == iface1 || _interfaceId == iface2 || _interfaceId == iface3;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @custom:legacy
|
||||||
|
/// @notice Legacy getter for the remote token. Use REMOTE_TOKEN going forward.
|
||||||
|
function l1Token() public view returns (address) {
|
||||||
|
return REMOTE_TOKEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @custom:legacy
|
||||||
|
/// @notice Legacy getter for the bridge. Use BRIDGE going forward.
|
||||||
|
function l2Bridge() public view returns (address) {
|
||||||
|
return BRIDGE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @custom:legacy
|
||||||
|
/// @notice Legacy getter for REMOTE_TOKEN.
|
||||||
|
function remoteToken() public view returns (address) {
|
||||||
|
return REMOTE_TOKEN;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @custom:legacy
|
||||||
|
/// @notice Legacy getter for BRIDGE.
|
||||||
|
function bridge() public view returns (address) {
|
||||||
|
return BRIDGE;
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,45 @@
|
||||||
|
// SPDX-License-Identifier: MIT
|
||||||
|
pragma solidity ^0.8.0;
|
||||||
|
|
||||||
|
import { Strings } from "@openzeppelin/contracts/utils/Strings.sol";
|
||||||
|
|
||||||
|
/// @title Semver
|
||||||
|
/// @notice Semver is a simple contract for managing contract versions.
|
||||||
|
contract Semver {
|
||||||
|
/// @notice Contract version number (major).
|
||||||
|
uint256 private immutable MAJOR_VERSION;
|
||||||
|
|
||||||
|
/// @notice Contract version number (minor).
|
||||||
|
uint256 private immutable MINOR_VERSION;
|
||||||
|
|
||||||
|
/// @notice Contract version number (patch).
|
||||||
|
uint256 private immutable PATCH_VERSION;
|
||||||
|
|
||||||
|
/// @param _major Version number (major).
|
||||||
|
/// @param _minor Version number (minor).
|
||||||
|
/// @param _patch Version number (patch).
|
||||||
|
constructor(
|
||||||
|
uint256 _major,
|
||||||
|
uint256 _minor,
|
||||||
|
uint256 _patch
|
||||||
|
) {
|
||||||
|
MAJOR_VERSION = _major;
|
||||||
|
MINOR_VERSION = _minor;
|
||||||
|
PATCH_VERSION = _patch;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// @notice Returns the full semver contract version.
|
||||||
|
/// @return Semver contract version as a string.
|
||||||
|
function version() public view returns (string memory) {
|
||||||
|
return
|
||||||
|
string(
|
||||||
|
abi.encodePacked(
|
||||||
|
Strings.toString(MAJOR_VERSION),
|
||||||
|
".",
|
||||||
|
Strings.toString(MINOR_VERSION),
|
||||||
|
".",
|
||||||
|
Strings.toString(PATCH_VERSION)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
|
@ -41,7 +41,7 @@ contract MiniMeToken is Controlled {
|
||||||
string public name; //The Token's name: e.g. DigixDAO Tokens
|
string public name; //The Token's name: e.g. DigixDAO Tokens
|
||||||
uint8 public decimals; //Number of decimals of the smallest unit
|
uint8 public decimals; //Number of decimals of the smallest unit
|
||||||
string public symbol; //An identifier: e.g. REP
|
string public symbol; //An identifier: e.g. REP
|
||||||
string public version = "MMT_0.1"; //An arbitrary versioning scheme
|
string public token_version = "MMT_0.1"; //An arbitrary versioning scheme
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @dev `Checkpoint` is the structure that attaches a block number to a
|
* @dev `Checkpoint` is the structure that attaches a block number to a
|
||||||
|
@ -254,6 +254,36 @@ contract MiniMeToken is Controlled {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function _mint(
|
||||||
|
address _owner,
|
||||||
|
uint _amount
|
||||||
|
)
|
||||||
|
internal
|
||||||
|
{
|
||||||
|
uint curTotalSupply = totalSupplyAt(block.number);
|
||||||
|
require(curTotalSupply + _amount >= curTotalSupply, "Total overflow"); // Check for overflow
|
||||||
|
uint previousBalanceTo = balanceOfAt(_owner, block.number);
|
||||||
|
require(previousBalanceTo + _amount >= previousBalanceTo, "Balance overflow"); // Check for overflow
|
||||||
|
updateValueAtNow(totalSupplyHistory, curTotalSupply + _amount);
|
||||||
|
updateValueAtNow(balances[_owner], previousBalanceTo + _amount);
|
||||||
|
emit Transfer(address(0), _owner, _amount);
|
||||||
|
}
|
||||||
|
|
||||||
|
function _burn(
|
||||||
|
address _owner,
|
||||||
|
uint _amount
|
||||||
|
)
|
||||||
|
internal
|
||||||
|
{
|
||||||
|
uint curTotalSupply = totalSupplyAt(block.number);
|
||||||
|
require(curTotalSupply >= _amount, "No enough supply");
|
||||||
|
uint previousBalanceFrom = balanceOfAt(_owner, block.number);
|
||||||
|
require(previousBalanceFrom >= _amount, "No enough balance");
|
||||||
|
updateValueAtNow(totalSupplyHistory, curTotalSupply - _amount);
|
||||||
|
updateValueAtNow(balances[_owner], previousBalanceFrom - _amount);
|
||||||
|
emit Transfer(_owner, address(0), _amount);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param _owner The address that's balance is being requested
|
* @param _owner The address that's balance is being requested
|
||||||
* @return balance The balance of `_owner` at the current block
|
* @return balance The balance of `_owner` at the current block
|
||||||
|
@ -456,13 +486,7 @@ contract MiniMeToken is Controlled {
|
||||||
onlyController
|
onlyController
|
||||||
returns (bool)
|
returns (bool)
|
||||||
{
|
{
|
||||||
uint curTotalSupply = totalSupplyAt(block.number);
|
_mint(_owner, _amount);
|
||||||
require(curTotalSupply + _amount >= curTotalSupply, "Total overflow"); // Check for overflow
|
|
||||||
uint previousBalanceTo = balanceOfAt(_owner, block.number);
|
|
||||||
require(previousBalanceTo + _amount >= previousBalanceTo, "Balance overflow"); // Check for overflow
|
|
||||||
updateValueAtNow(totalSupplyHistory, curTotalSupply + _amount);
|
|
||||||
updateValueAtNow(balances[_owner], previousBalanceTo + _amount);
|
|
||||||
emit Transfer(address(0), _owner, _amount);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -480,13 +504,7 @@ contract MiniMeToken is Controlled {
|
||||||
onlyController
|
onlyController
|
||||||
returns (bool)
|
returns (bool)
|
||||||
{
|
{
|
||||||
uint curTotalSupply = totalSupplyAt(block.number);
|
_burn(_owner, _amount);
|
||||||
require(curTotalSupply >= _amount, "No enough supply");
|
|
||||||
uint previousBalanceFrom = balanceOfAt(_owner, block.number);
|
|
||||||
require(previousBalanceFrom >= _amount, "No enough balance");
|
|
||||||
updateValueAtNow(totalSupplyHistory, curTotalSupply - _amount);
|
|
||||||
updateValueAtNow(balances[_owner], previousBalanceFrom - _amount);
|
|
||||||
emit Transfer(_owner, address(0), _amount);
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -5,12 +5,21 @@ const INFURA_API_KEY = process.env.INFURA_API_KEY;
|
||||||
const ETHERSCAN_API_KEY = process.env.ETHERSCAN_API_KEY;
|
const ETHERSCAN_API_KEY = process.env.ETHERSCAN_API_KEY;
|
||||||
const GOERLI_PRIVATE_KEY = process.env.GOERLI_PRIVATE_KEY;
|
const GOERLI_PRIVATE_KEY = process.env.GOERLI_PRIVATE_KEY;
|
||||||
|
|
||||||
console.log(INFURA_API_KEY)
|
|
||||||
/** @type import('hardhat/config').HardhatUserConfig */
|
/** @type import('hardhat/config').HardhatUserConfig */
|
||||||
module.exports = {
|
module.exports = {
|
||||||
solidity: "0.8.18",
|
solidity: "0.8.18",
|
||||||
networks: {
|
networks: {
|
||||||
goerli: {
|
'optimism-goerli': {
|
||||||
|
chainId: 420,
|
||||||
|
url: `https://opt-goerli.g.alchemy.com/v2/${process.env.L2_ALCHEMY_KEY}`,
|
||||||
|
accounts: { mnemonic: process.env.MNEMONIC }
|
||||||
|
},
|
||||||
|
'optimism-mainnet': {
|
||||||
|
chainId: 10,
|
||||||
|
url: `https://opt-mainnet.g.alchemy.com/v2/${process.env.L2_ALCHEMY_KEY}`,
|
||||||
|
accounts: { mnemonic: process.env.MNEMONIC }
|
||||||
|
},
|
||||||
|
'goerli': {
|
||||||
url: `https://goerli.infura.io/v3/${INFURA_API_KEY}`,
|
url: `https://goerli.infura.io/v3/${INFURA_API_KEY}`,
|
||||||
accounts: [GOERLI_PRIVATE_KEY]
|
accounts: [GOERLI_PRIVATE_KEY]
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue