From 0fab17085f716c4caa8dc35afb34cbea75e50536 Mon Sep 17 00:00:00 2001 From: Moon Date: Sat, 19 Aug 2023 21:36:58 -0400 Subject: [PATCH] I think Base side is implemented correctly. --- contracts/TenGransBaseToken.sol | 97 +++++++++++++++++++++++++++++++++ package-lock.json | 34 ++++++++++++ package.json | 1 + 3 files changed, 132 insertions(+) create mode 100644 contracts/TenGransBaseToken.sol diff --git a/contracts/TenGransBaseToken.sol b/contracts/TenGransBaseToken.sol new file mode 100644 index 0000000..5077329 --- /dev/null +++ b/contracts/TenGransBaseToken.sol @@ -0,0 +1,97 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.19; + +import "./TenGransAbstractToken.sol"; +import "@eth-optimism/contracts-bedrock/contracts/universal/IOptimismMintableERC20.sol"; + +contract TenGransBaseToken is AbstractGrans, IOptimismMintableERC20 { + /// @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 = 0x4200000000000000000000000000000000000010; + + /// @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(_msgSender() == BRIDGE, "OptimismMintableERC20: only bridge can mint and burn"); + _; + } + + constructor(address _remoteToken) AbstractGrans() { + REMOTE_TOKEN = _remoteToken; + } + + function balanceOf(address account) public view virtual override(AbstractGrans) returns (uint256) { + return AbstractGrans.balanceOf(account); + } + + function transferFrom(address sender, address recipient, uint256 amount) public virtual override(AbstractGrans) returns (bool) { + return AbstractGrans.transferFrom(sender, recipient, amount); + } + + /// @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 + virtual + override(IOptimismMintableERC20) + 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 + virtual + override(IOptimismMintableERC20) + 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) public pure virtual override(AbstractGrans, IERC165) returns (bool) { + bytes4 iface1 = type(IERC165).interfaceId; + // Interface corresponding to the updated OptimismMintableERC20 (this contract). + bytes4 iface2 = type(IOptimismMintableERC20).interfaceId; + return _interfaceId == iface1 || _interfaceId == iface2; + } + + /// @custom:legacy + /// @notice Legacy getter for REMOTE_TOKEN. + // Is this needed? + function remoteToken() public view virtual override(IOptimismMintableERC20) returns (address) { + return REMOTE_TOKEN; + } + + /// @custom:legacy + /// @notice Legacy getter for BRIDGE. + // Is this needed? + function bridge() public view virtual override(IOptimismMintableERC20) returns (address) { + return BRIDGE; + } +} diff --git a/package-lock.json b/package-lock.json index 0e640e1..e23e69f 100644 --- a/package-lock.json +++ b/package-lock.json @@ -9,6 +9,7 @@ "version": "1.0.0", "license": "MIT", "dependencies": { + "@eth-optimism/contracts-bedrock": "^0.16.0", "@openzeppelin/contracts": "^4.9.3", "erc-payable-token": "^4.9.3" }, @@ -76,6 +77,22 @@ "node": ">=12" } }, + "node_modules/@eth-optimism/contracts-bedrock": { + "version": "0.16.0", + "resolved": "https://registry.npmjs.org/@eth-optimism/contracts-bedrock/-/contracts-bedrock-0.16.0.tgz", + "integrity": "sha512-MfHJdeQ/BzHgkoHnA+NGb1hU8CH0OFsp4ylmFi0uwYh3xPJxcHt9qhy1g4MGGMUGAPIUmlBPaqhwbBlQkaeFrA==", + "dependencies": { + "@openzeppelin/contracts": "4.7.3", + "@openzeppelin/contracts-upgradeable": "4.7.3", + "@rari-capital/solmate": "github:transmissions11/solmate#8f9b23f8838670afda0fd8983f2c41e8037ae6bc", + "clones-with-immutable-args": "github:Saw-mon-and-Natalie/clones-with-immutable-args#105efee1b9127ed7f6fedf139e1fc796ce8791f2" + } + }, + "node_modules/@eth-optimism/contracts-bedrock/node_modules/@openzeppelin/contracts": { + "version": "4.7.3", + "resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-4.7.3.tgz", + "integrity": "sha512-dGRS0agJzu8ybo44pCIf3xBaPQN/65AIXNgK8+4gzKd5kbvlqyxryUYVLJv7fK98Seyd2hDZzVEHSWAh0Bt1Yw==" + }, "node_modules/@ethersproject/abi": { "version": "5.7.0", "resolved": "https://registry.npmjs.org/@ethersproject/abi/-/abi-5.7.0.tgz", @@ -1737,6 +1754,17 @@ "resolved": "https://registry.npmjs.org/@openzeppelin/contracts/-/contracts-4.9.3.tgz", "integrity": "sha512-He3LieZ1pP2TNt5JbkPA4PNT9WC3gOTOlDcFGJW4Le4QKqwmiNJCRt44APfxMxvq7OugU/cqYuPcSBzOw38DAg==" }, + "node_modules/@openzeppelin/contracts-upgradeable": { + "version": "4.7.3", + "resolved": "https://registry.npmjs.org/@openzeppelin/contracts-upgradeable/-/contracts-upgradeable-4.7.3.tgz", + "integrity": "sha512-+wuegAMaLcZnLCJIvrVUDzA9z/Wp93f0Dla/4jJvIhijRrPabjQbZe6fWiECLaJyfn5ci9fqf9vTw3xpQOad2A==" + }, + "node_modules/@rari-capital/solmate": { + "version": "7.0.0-alpha.3", + "resolved": "git+ssh://git@github.com/transmissions11/solmate.git#8f9b23f8838670afda0fd8983f2c41e8037ae6bc", + "integrity": "sha512-cW0PouqpoiEDhhkOxkqQKcjG4oMJ1Qb+kY6aiwBlgOjpfnhmXK7lkU5ZkHKC22ypQj6lvSc6CaHmXXaPywPsYg==", + "license": "MIT" + }, "node_modules/@scure/base": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.1.tgz", @@ -3007,6 +3035,12 @@ "wrap-ansi": "^7.0.0" } }, + "node_modules/clones-with-immutable-args": { + "version": "2.0.0", + "resolved": "git+ssh://git@github.com/Saw-mon-and-Natalie/clones-with-immutable-args.git#105efee1b9127ed7f6fedf139e1fc796ce8791f2", + "integrity": "sha512-k3pqgVlL6sTgySZG8eN+spNdokeM/J7kgBVn0xJeZIg+cv1vA1ert1jFDuHX1Vfz1uTTqfZbmWHhvCCdy0VpNA==", + "license": "BSD" + }, "node_modules/color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", diff --git a/package.json b/package.json index e3b35b5..47fca3a 100644 --- a/package.json +++ b/package.json @@ -27,6 +27,7 @@ "prettier-plugin-solidity": "^1.1.3" }, "dependencies": { + "@eth-optimism/contracts-bedrock": "^0.16.0", "@openzeppelin/contracts": "^4.9.3", "erc-payable-token": "^4.9.3" }