diff --git a/.gas-snapshot b/.gas-snapshot index e69de29..9eb7f8d 100644 --- a/.gas-snapshot +++ b/.gas-snapshot @@ -0,0 +1 @@ +OptmismMintableMiniMeTokenTest:testDeployment() (gas: 56870) \ No newline at end of file diff --git a/script/DeployBridge.s.sol b/script/DeployBridge.s.sol new file mode 100644 index 0000000..c69d1fa --- /dev/null +++ b/script/DeployBridge.s.sol @@ -0,0 +1,41 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity >=0.8.19 <=0.9.0; + +import { MiniMeBase } from "@vacp2p/minime/contracts/MiniMeBase.sol"; +import { BaseScript } from "./Base.s.sol"; +import { DeploymentConfig } from "./DeploymentConfig.s.sol"; +import { OptimismMintableMiniMeToken } from "../contracts/optimism/OptimismMintableMiniMeToken.sol"; +import { SNTPlaceHolder } from "../contracts/SNTPlaceHolder.sol"; + +contract DeployBridge is BaseScript { + function run() public returns (DeploymentConfig, OptimismMintableMiniMeToken, SNTPlaceHolder) { + DeploymentConfig deploymentConfig = new DeploymentConfig(broadcaster); + ( + address deployer, + address bridgeAddress, + address remoteTokenAddress, + address parentTokenAddress, + uint256 parentSnapShotBlock, + string memory tokenName, + uint8 decimals, + string memory tokenSymbol, + bool transferEnabled + ) = deploymentConfig.activeNetworkConfig(); + + vm.startBroadcast(deployer); + OptimismMintableMiniMeToken bridgeToken = new OptimismMintableMiniMeToken( + bridgeAddress, + remoteTokenAddress, + MiniMeBase(payable(parentTokenAddress)), + parentSnapShotBlock, + tokenName, + decimals, + tokenSymbol, + transferEnabled + ); + SNTPlaceHolder tokenController = new SNTPlaceHolder(payable(address(bridgeToken))); + bridgeToken.changeController(payable(address(tokenController))); + vm.stopBroadcast(); + return (deploymentConfig, bridgeToken, tokenController); + } +} diff --git a/script/DeploymentConfig.s.sol b/script/DeploymentConfig.s.sol new file mode 100644 index 0000000..cc0a257 --- /dev/null +++ b/script/DeploymentConfig.s.sol @@ -0,0 +1,99 @@ +//// SPDX-License-Identifier: UNLICENSED + +pragma solidity >=0.8.19 <=0.9.0; + +import { Script } from "forge-std/Script.sol"; + +contract DeploymentConfig is Script { + error DeploymentConfig_InvalidDeployerAddress(); + error DeploymentConfig_NoConfigForChain(uint256); + + struct NetworkConfig { + address deployer; + address bridgeAddress; + address remoteTokenAddress; + address parentTokenAddress; + uint256 parentSnapShotBlock; + string tokenName; + uint8 decimals; + string tokenSymbol; + bool transferEnabled; + } + + NetworkConfig public activeNetworkConfig; + + address private deployer; + + // solhint-disable-next-line var-name-mixedcase + address internal SNT_ADDRESS_MAINNET = 0x744d70FDBE2Ba4CF95131626614a1763DF805B9E; + // solhint-disable-next-line var-name-mixedcase + address internal SNT_ADDRESS_GOERLI = 0x3D6AFAA395C31FCd391fE3D562E75fe9E8ec7E6a; + // solhint-disable-next-line var-name-mixedcase + address internal STANDARD_BRIDGE_ADDRESS = 0x4200000000000000000000000000000000000010; + + constructor(address _broadcaster) { + if (_broadcaster == address(0)) revert DeploymentConfig_InvalidDeployerAddress(); + deployer = _broadcaster; + if (block.chainid == 31_337) { + activeNetworkConfig = getOrCreateAnvilEthConfig(); + } else if (block.chainid == 420) { + activeNetworkConfig = getOptimismGoerliConfig(); + } else if (block.chainid == 10) { + activeNetworkConfig = getOptimismConfig(); + } else { + revert DeploymentConfig_NoConfigForChain(block.chainid); + } + } + + function getOrCreateAnvilEthConfig() public returns (NetworkConfig memory) { + address mockBridgeAddress = makeAddr("mockBridgeAddress"); + address mockRemoteTokenAddress = makeAddr("mockRemoteTokenAddress"); + + return NetworkConfig({ + deployer: deployer, + bridgeAddress: mockBridgeAddress, + remoteTokenAddress: mockRemoteTokenAddress, + parentTokenAddress: address(0), + parentSnapShotBlock: 0, + tokenName: "Status Test Token", + decimals: 18, + tokenSymbol: "SNT", + transferEnabled: true + }); + } + + function getOptimismGoerliConfig() public view returns (NetworkConfig memory) { + return NetworkConfig({ + deployer: deployer, + bridgeAddress: STANDARD_BRIDGE_ADDRESS, + remoteTokenAddress: SNT_ADDRESS_GOERLI, + parentTokenAddress: address(0), + parentSnapShotBlock: 0, + tokenName: "Status Test Token", + decimals: 18, + tokenSymbol: "SNT", + transferEnabled: true + }); + } + + function getOptimismConfig() public view returns (NetworkConfig memory) { + return NetworkConfig({ + deployer: deployer, + bridgeAddress: STANDARD_BRIDGE_ADDRESS, + remoteTokenAddress: SNT_ADDRESS_MAINNET, + parentTokenAddress: address(0), + parentSnapShotBlock: 0, + tokenName: "Status Network Token", + decimals: 18, + tokenSymbol: "SNT", + transferEnabled: true + }); + } + + // This function is a hack to have it excluded by `forge coverage` until + // https://github.com/foundry-rs/foundry/issues/2988 is fixed. + // See: https://github.com/foundry-rs/foundry/issues/2988#issuecomment-1437784542 + // for more info. + // solhint-disable-next-line + function test() public { } +} diff --git a/test/OptimismMintableMiniMeToken.t.sol b/test/OptimismMintableMiniMeToken.t.sol new file mode 100644 index 0000000..ff946ff --- /dev/null +++ b/test/OptimismMintableMiniMeToken.t.sol @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: UNLICENSED +pragma solidity ^0.8.19; + +import { Test } from "forge-std/Test.sol"; +import { DeployBridge } from "../script/DeployBridge.s.sol"; +import { DeploymentConfig } from "../script/DeploymentConfig.s.sol"; + +import { OptimismMintableMiniMeToken } from "../contracts/optimism/OptimismMintableMiniMeToken.sol"; +import { SNTPlaceHolder } from "../contracts/SNTPlaceHolder.sol"; + +contract OptmismMintableMiniMeTokenTest is Test { + DeploymentConfig internal deploymentConfig; + SNTPlaceHolder internal tokenController; + OptimismMintableMiniMeToken internal bridgeToken; + + address internal deployer; + + function setUp() public virtual { + DeployBridge deployment = new DeployBridge(); + (deploymentConfig, bridgeToken, tokenController) = deployment.run(); + (deployer,,,,,,,,) = deploymentConfig.activeNetworkConfig(); + } + + function testDeployment() public { + ( + , + address _bridgeAddress, + address _remoteTokenAddress, + address _parentTokenAddress, + uint256 _parentSnapShotBlock, + string memory _tokenName, + uint8 _decimals, + string memory _tokenSymbol, + bool _transferEnabled + ) = deploymentConfig.activeNetworkConfig(); + + assertEq(bridgeToken.controller(), address(tokenController)); + assertEq(bridgeToken.l2Bridge(), _bridgeAddress); + assertEq(bridgeToken.bridge(), _bridgeAddress); + assertEq(bridgeToken.l1Token(), _remoteTokenAddress); + assertEq(bridgeToken.remoteToken(), _remoteTokenAddress); + + assertEq(address(bridgeToken.parentToken()), _parentTokenAddress); + assertEq(bridgeToken.parentSnapShotBlock(), _parentSnapShotBlock); + assertEq(bridgeToken.name(), _tokenName); + assertEq(bridgeToken.decimals(), _decimals); + assertEq(bridgeToken.symbol(), _tokenSymbol); + assertEq(bridgeToken.transfersEnabled(), _transferEnabled); + } +}