diff --git a/.prettierrc b/.prettierrc index a5c35f86b..1444ed799 100644 --- a/.prettierrc +++ b/.prettierrc @@ -25,6 +25,12 @@ "options": { "proseWrap": "always" } + }, + { + "files": ".github/pull_request_template.md", + "options": { + "proseWrap": "never" + } } ] } diff --git a/README.md b/README.md index 76407b430..edc015547 100644 --- a/README.md +++ b/README.md @@ -39,7 +39,7 @@ Requirements: - Node 16.14.0 - Yarn 1.22.19 -- [Foundry@2cf84d9](https://github.com/foundry-rs/foundry/releases/tag/nightly-2cf84d9f3ba7b6f4a9296299e7036ecc24cfa1da) +- [Foundry@f625d0f](https://github.com/foundry-rs/foundry/releases/tag/nightly-f625d0fa7c51e65b4bf1e8f7931cd1c6e2e285e9) ```sh $ git clone git@github.com:circlefin/stablecoin-evm.git diff --git a/contracts/v2/upgrader/V2Upgrader.sol b/contracts/v2/upgrader/V2Upgrader.sol index 1cfdf04d2..ca9ef9405 100644 --- a/contracts/v2/upgrader/V2Upgrader.sol +++ b/contracts/v2/upgrader/V2Upgrader.sol @@ -42,7 +42,7 @@ contract V2Upgrader is AbstractV2Upgrader { * @param proxy FiatTokenProxy contract * @param implementation FiatTokenV2 implementation contract * @param newProxyAdmin Grantee of proxy admin role after upgrade - * @param newName New ERC20 name (e.g. "USD//C" -> "USD Coin") + * @param newName New ERC20 name (e.g. "USD//C" -> "USDC") */ constructor( FiatTokenProxy proxy, diff --git a/foundry.toml b/foundry.toml index d80a8a9f0..1a939362c 100644 --- a/foundry.toml +++ b/foundry.toml @@ -32,6 +32,10 @@ fs_permissions = [ { access = "read-write", path = "blacklist.remote.json"}, { access = "read-write", path = "test.blacklist.remote.json"} ] # https://book.getfoundry.sh/cheatcodes/fs +extra-output-files = [ + "bin", + "metadata" +] [rpc_endpoints] testnet = "${TESTNET_RPC_URL}" diff --git a/package.json b/package.json index 435457790..6968449e3 100644 --- a/package.json +++ b/package.json @@ -11,7 +11,8 @@ "coverage": "hardhat coverage", "forge:simulate": "forge script -vv --gas-estimate-multiplier $(dotenv -p GAS_MULTIPLIER)", "forge:broadcast": "yarn forge:simulate --broadcast", - "forge:verify": "yarn forge:simulate --verify --resume --etherscan-api-key $(dotenv -p ETHERSCAN_KEY)", + "forge:broadcastAndVerify": "yarn forge:broadcast --verify --etherscan-api-key $(dotenv -p ETHERSCAN_KEY)", + "forge:verify": "yarn forge:simulate --verify --resume --etherscan-api-key $(dotenv -p ETHERSCAN_KEY) --private-key $(dotenv -p DEPLOYER_PRIVATE_KEY)", "fmt:base": "prettier './**/*.sol' './**/*.js' './**/*.ts' './**/*.json' './**/*.md'", "fmt:check": "yarn fmt:base --check", "fmt": "yarn fmt:base --write", @@ -35,7 +36,6 @@ "url": "https://github.com/circlefin/stablecoin-evm/issues" }, "homepage": "https://github.com/circlefin/stablecoin-evm#readme", - "dependencies": {}, "devDependencies": { "@nomicfoundation/hardhat-chai-matchers": "2.0.2", "@nomicfoundation/hardhat-ethers": "3.0.4", diff --git a/scripts/deploy/deploy-fiat-token.s.sol b/scripts/deploy/deploy-fiat-token.s.sol index 24d1fbded..bd97c9f81 100644 --- a/scripts/deploy/deploy-fiat-token.s.sol +++ b/scripts/deploy/deploy-fiat-token.s.sol @@ -40,7 +40,6 @@ contract DeployFiatToken is Script, DeployImpl { address private owner; address private pauser; address private blacklister; - address private lostAndFound; string private tokenName; string private tokenSymbol; @@ -63,10 +62,9 @@ contract DeployFiatToken is Script, DeployImpl { masterMinterOwner = vm.envAddress("MASTER_MINTER_OWNER_ADDRESS"); owner = vm.envAddress("OWNER_ADDRESS"); - // Pauser, blacklister, and lost and found addresses can default to owner address + // Pauser and blacklister addresses can default to owner address pauser = vm.envOr("PAUSER_ADDRESS", owner); blacklister = vm.envOr("BLACKLISTER_ADDRESS", owner); - lostAndFound = vm.envOr("LOST_AND_FOUND_ADDRESS", owner); deployerPrivateKey = vm.envUint("DEPLOYER_PRIVATE_KEY"); @@ -80,7 +78,6 @@ contract DeployFiatToken is Script, DeployImpl { console.log("OWNER_ADDRESS: '%s'", owner); console.log("PAUSER_ADDRESS: '%s'", pauser); console.log("BLACKLISTER_ADDRESS: '%s'", blacklister); - console.log("LOST_AND_FOUND_ADDRESS: '%s'", lostAndFound); } /** @@ -134,7 +131,7 @@ contract DeployFiatToken is Script, DeployImpl { proxyAsV2_2.initializeV2(tokenName); // Do the V2_1 initialization - proxyAsV2_2.initializeV2_1(lostAndFound); + proxyAsV2_2.initializeV2_1(owner); // Do the V2_2 initialization proxyAsV2_2.initializeV2_2(new address[](0), tokenSymbol); diff --git a/setup.sh b/setup.sh index 2d43d21c0..ab98bd0bd 100755 --- a/setup.sh +++ b/setup.sh @@ -19,7 +19,7 @@ set -e # Refer to https://github.com/foundry-rs/foundry/tags for the list of Foundry versions. -FOUNDRY_VERSION=nightly-2cf84d9f3ba7b6f4a9296299e7036ecc24cfa1da +FOUNDRY_VERSION=nightly-f625d0fa7c51e65b4bf1e8f7931cd1c6e2e285e9 if [[ "$CI" == "true" ]] then @@ -38,11 +38,13 @@ then export PATH="$FOUNDRY_BIN_DIR:$PATH" fi -if ! command -v forge &> /dev/null || [ ! "$(forge -V | grep -Eo '\b\w{7}\b')" = "2cf84d9" ] +if ! command -v forge &> /dev/null || [ ! "$(forge -V | grep -Eo '\b\w{7}\b')" = $(echo $FOUNDRY_VERSION | cut -c '9-15') ] then echo "Installing foundry at $FOUNDRY_VERSION..." foundryup --version $FOUNDRY_VERSION fi +npm install -g dotenv-cli@7.3.0 + echo "Updating git submodules..." git submodule update --init --recursive diff --git a/test/helpers/index.ts b/test/helpers/index.ts index 9e9029087..abf1c1e59 100644 --- a/test/helpers/index.ts +++ b/test/helpers/index.ts @@ -150,7 +150,7 @@ export async function initializeToVersion( ): Promise { const proxyAsV1 = await FiatTokenV1.at(proxyOrImplementation.address); await proxyAsV1.initialize( - "USD Coin", + "USDC", "USDC", "USD", 6, @@ -162,7 +162,7 @@ export async function initializeToVersion( if (version >= "2") { const proxyAsV2 = await FiatTokenV2.at(proxyOrImplementation.address); - await proxyAsV2.initializeV2("USD Coin", { + await proxyAsV2.initializeV2("USDC", { from: fiatTokenOwner, }); } diff --git a/test/helpers/storageSlots.behavior.ts b/test/helpers/storageSlots.behavior.ts index 6f36d765a..88b882b50 100644 --- a/test/helpers/storageSlots.behavior.ts +++ b/test/helpers/storageSlots.behavior.ts @@ -42,7 +42,7 @@ export function usesOriginalStorageSlotPositions< version: 1 | 1.1 | 2 | 2.1 | 2.2; }): void { describe("uses original storage slot positions", () => { - const [name, symbol, currency, decimals] = ["USD Coin", "USDC", "USD", 6]; + const [name, symbol, currency, decimals] = ["USDC", "USDC", "USD", 6]; const [mintAllowance, minted, transferred, allowance] = [ 1000e6, 100e6, diff --git a/test/scripts/deploy/TestUtils.sol b/test/scripts/deploy/TestUtils.sol index 8b5e69122..6dc6ed936 100644 --- a/test/scripts/deploy/TestUtils.sol +++ b/test/scripts/deploy/TestUtils.sol @@ -22,7 +22,7 @@ pragma experimental ABIEncoderV2; // needed for compiling older solc versions: h import "forge-std/Test.sol"; // solhint-disable no-global-import import { MasterMinter } from "../../../contracts/minting/MasterMinter.sol"; import { FiatTokenProxy } from "../../../contracts/v1/FiatTokenProxy.sol"; -import { FiatTokenV1 } from "../../../contracts/v1/FiatTokenV1.sol"; +import { FiatTokenV2_2 } from "../../../contracts/v2/FiatTokenV2_2.sol"; import { AbstractV2Upgrader } from "../../../contracts/v2/upgrader/AbstractV2Upgrader.sol"; @@ -37,7 +37,6 @@ contract TestUtils is Test { uint256 internal ownerPrivateKey = 4; uint256 internal pauserPrivateKey = 5; uint256 internal blacklisterPrivateKey = 6; - uint256 internal lostAndFoundPrivateKey = 7; address internal deployer = vm.addr(deployerPrivateKey); address internal proxyAdmin = vm.addr(proxyAdminPrivateKey); @@ -45,7 +44,6 @@ contract TestUtils is Test { address internal owner = vm.addr(ownerPrivateKey); address internal pauser = vm.addr(pauserPrivateKey); address internal blacklister = vm.addr(blacklisterPrivateKey); - address internal lostAndFound = vm.addr(lostAndFoundPrivateKey); uint8 internal decimals = 6; string internal tokenName = "USDC"; @@ -73,13 +71,33 @@ contract TestUtils is Test { vm.setEnv("OWNER_ADDRESS", vm.toString(owner)); vm.setEnv("PAUSER_ADDRESS", vm.toString(pauser)); vm.setEnv("BLACKLISTER_ADDRESS", vm.toString(blacklister)); - vm.setEnv("LOST_AND_FOUND_ADDRESS", vm.toString(lostAndFound)); // Deploy an instance of proxy contract to configure contract address in env + vm.prank(deployer); + FiatTokenV2_2 v2_2 = new FiatTokenV2_2(); + + vm.prank(proxyAdmin); + FiatTokenProxy proxy = new FiatTokenProxy(address(v2_2)); + vm.startPrank(deployer); - FiatTokenV1 v1 = new FiatTokenV1(); - FiatTokenProxy proxy = new FiatTokenProxy(address(v1)); - vm.stopPrank(); + MasterMinter masterMinter = new MasterMinter(address(proxy)); + masterMinter.transferOwnership(masterMinterOwner); + + FiatTokenV2_2 proxyAsV2_2 = FiatTokenV2_2(address(proxy)); + + proxyAsV2_2.initialize( + tokenName, + tokenSymbol, + "USD", + decimals, + address(masterMinter), + pauser, + blacklister, + vm.addr(ownerPrivateKey) + ); + proxyAsV2_2.initializeV2(tokenName); + proxyAsV2_2.initializeV2_1(owner); + proxyAsV2_2.initializeV2_2(new address[](0), tokenSymbol); vm.setEnv("FIAT_TOKEN_PROXY_ADDRESS", vm.toString(address(proxy))); vm.setEnv("BLACKLIST_FILE_NAME", blacklistFileName); @@ -108,7 +126,7 @@ contract TestUtils is Test { owner ); proxyAsV2_2.initializeV2(tokenName); - proxyAsV2_2.initializeV2_1(lostAndFound); + proxyAsV2_2.initializeV2_1(owner); proxyAsV2_2.initializeV2_2(new address[](0), tokenSymbol); vm.stopPrank(); @@ -117,7 +135,7 @@ contract TestUtils is Test { vm.setEnv("FEE_ADAPTER_DECIMALS", "18"); } - function validateImpl(FiatTokenV1 impl) internal { + function validateImpl(FiatTokenV2_2 impl) internal { assertEq(impl.name(), ""); assertEq(impl.symbol(), ""); assertEq(impl.currency(), ""); diff --git a/test/util/MessageHashUtils.test.ts b/test/util/MessageHashUtils.test.ts index 303712aab..21ea103df 100644 --- a/test/util/MessageHashUtils.test.ts +++ b/test/util/MessageHashUtils.test.ts @@ -31,7 +31,7 @@ describe("MessageHashUtils", function () { const messageHashUtils: MessageHashUtilsTestInstance = await MessageHashUtils.new(); const structhash: string = web3.utils.randomHex(32); const domainSeparator: string = makeDomainSeparator( - "USD Coin", + "USDC", "2", 1, messageHashUtils.address diff --git a/test/v1.1/FiatTokenV1_1.test.ts b/test/v1.1/FiatTokenV1_1.test.ts index e25c75642..e33314a85 100644 --- a/test/v1.1/FiatTokenV1_1.test.ts +++ b/test/v1.1/FiatTokenV1_1.test.ts @@ -34,7 +34,7 @@ describe("FiatTokenV1_1", () => { beforeEach(async () => { fiatToken = await FiatTokenV1_1.new(); await fiatToken.initialize( - "USD Coin", + "USDC", "USDC", "USD", 6, diff --git a/test/v2/FiatTokenV2.test.ts b/test/v2/FiatTokenV2.test.ts index 42c5f49b8..d6cf500c4 100644 --- a/test/v2/FiatTokenV2.test.ts +++ b/test/v2/FiatTokenV2.test.ts @@ -35,7 +35,7 @@ describe("FiatTokenV2", () => { beforeEach(async () => { fiatToken = await FiatTokenV2.new(); await fiatToken.initialize( - "USD Coin", + "USDC", "USDC", "USD", 6, @@ -44,7 +44,7 @@ describe("FiatTokenV2", () => { fiatTokenOwner, fiatTokenOwner ); - await fiatToken.initializeV2("USD Coin", { from: fiatTokenOwner }); + await fiatToken.initializeV2("USDC", { from: fiatTokenOwner }); }); behavesLikeFiatTokenV2(2, () => fiatToken); diff --git a/test/v2/FiatTokenV2_1.test.ts b/test/v2/FiatTokenV2_1.test.ts index 8fd120aca..1bb78f4f1 100644 --- a/test/v2/FiatTokenV2_1.test.ts +++ b/test/v2/FiatTokenV2_1.test.ts @@ -36,7 +36,7 @@ describe("FiatTokenV2_1", () => { beforeEach(async () => { fiatToken = await FiatTokenV2_1.new(); await fiatToken.initialize( - "USD Coin", + "USDC", "USDC", "USD", 6, @@ -45,7 +45,7 @@ describe("FiatTokenV2_1", () => { fiatTokenOwner, fiatTokenOwner ); - await fiatToken.initializeV2("USD Coin", { from: fiatTokenOwner }); + await fiatToken.initializeV2("USDC", { from: fiatTokenOwner }); }); behavesLikeFiatTokenV2(2.1, () => fiatToken); diff --git a/test/v2/MockFiatTokenWithEditableChainId.test.ts b/test/v2/MockFiatTokenWithEditableChainId.test.ts index ca0995388..8593c3f24 100644 --- a/test/v2/MockFiatTokenWithEditableChainId.test.ts +++ b/test/v2/MockFiatTokenWithEditableChainId.test.ts @@ -25,7 +25,7 @@ const MockFiatTokenWithEditableChainId = artifacts.require( ); describe("MockFiatTokenWithEditableChainId", () => { - const name = "USD Coin"; + const name = "USDC"; const version = "2"; const [, , lostAndFound] = HARDHAT_ACCOUNTS; const fiatTokenOwner = HARDHAT_ACCOUNTS[9]; @@ -46,7 +46,7 @@ describe("MockFiatTokenWithEditableChainId", () => { fiatTokenOwner, fiatTokenOwner ); - await fiatToken.initializeV2("USD Coin", { from: fiatTokenOwner }); + await fiatToken.initializeV2("USDC", { from: fiatTokenOwner }); await fiatToken.initializeV2_1(lostAndFound); await fiatToken.initializeV2_2([], "USDCUSDC"); }); diff --git a/test/v2/V2Upgrader.test.ts b/test/v2/V2Upgrader.test.ts index e519324cc..91938cd82 100644 --- a/test/v2/V2Upgrader.test.ts +++ b/test/v2/V2Upgrader.test.ts @@ -92,7 +92,7 @@ describe("V2Upgrader", () => { fiatTokenProxy.address, v2Implementation.address, await fiatTokenProxy.admin(), - "USD Coin" + "USDC" ); const upgraderOwner = await upgrader.owner(); @@ -102,7 +102,7 @@ describe("V2Upgrader", () => { ); expect(await upgrader.helper()).not.to.be.empty; expect(await upgrader.newProxyAdmin()).to.equal(originalProxyAdmin); - expect(await upgrader.newName()).to.equal("USD Coin"); + expect(await upgrader.newName()).to.equal("USDC"); // Transfer 0.2 FiatToken to the contract await proxyAsV1.transfer(upgrader.address, 2e5, { from: minter }); @@ -124,7 +124,7 @@ describe("V2Upgrader", () => { ); // Test that things work as expected - expect(await proxyAsV2.name()).to.equal("USD Coin"); + expect(await proxyAsV2.name()).to.equal("USDC"); expect((await proxyAsV2.balanceOf(upgrader.address)).toNumber()).to.equal( 0 ); @@ -210,7 +210,7 @@ describe("V2Upgrader", () => { fiatTokenProxy.address, fiatTokenV1_1.address, // provide V1.1 implementation instead of V2 originalProxyAdmin, - "USD Coin", + "USDC", { from: upgraderOwner } ); @@ -245,7 +245,7 @@ describe("V2Upgrader", () => { fiatTokenProxy.address, v2Implementation.address, originalProxyAdmin, - "USD Coin", + "USDC", { from: upgraderOwner } ); diff --git a/test/v2/V2_1Upgrader.test.ts b/test/v2/V2_1Upgrader.test.ts index 031ba3deb..21ae256c2 100644 --- a/test/v2/V2_1Upgrader.test.ts +++ b/test/v2/V2_1Upgrader.test.ts @@ -76,7 +76,7 @@ describe("V2_1Upgrader", () => { await fiatTokenProxy.upgradeToAndCall( v2Implementation.address, web3.eth.abi.encodeFunctionSignature("initializeV2(string)") + - strip0x(web3.eth.abi.encodeParameters(["string"], ["USD Coin"])), + strip0x(web3.eth.abi.encodeParameters(["string"], ["USDC"])), { from: originalProxyAdmin } ); }); diff --git a/test/v2/V2_2Upgrader.test.ts b/test/v2/V2_2Upgrader.test.ts index b1324d006..7d6da986f 100644 --- a/test/v2/V2_2Upgrader.test.ts +++ b/test/v2/V2_2Upgrader.test.ts @@ -96,7 +96,7 @@ describe("V2_2Upgrader", () => { await fiatTokenProxy.upgradeTo(v2_1Implementation.address, { from: originalProxyAdmin, }); - await proxyAsV2_1.initializeV2("USD Coin"); + await proxyAsV2_1.initializeV2("USDC"); await proxyAsV2_1.initializeV2_1(lostAndFound); // Initially blacklist all these accounts. diff --git a/test/v2/v2.behavior.ts b/test/v2/v2.behavior.ts index bce4d41c5..3f2f2ce7b 100644 --- a/test/v2/v2.behavior.ts +++ b/test/v2/v2.behavior.ts @@ -49,7 +49,7 @@ export function behavesLikeFiatTokenV2( fiatTokenOwner = await getFiatToken().owner(); domainSeparator = makeDomainSeparator( - "USD Coin", + "USDC", "2", await web3.eth.getChainId(), getFiatToken().address @@ -80,7 +80,7 @@ export function behavesLikeFiatTokenV2( it("disallows calling initializeV2 twice", async () => { // It was called once in beforeEach. Try to call again. await expectRevert( - getFiatToken().initializeV2("Not USD Coin", { from: fiatTokenOwner }) + getFiatToken().initializeV2("Not USDC", { from: fiatTokenOwner }) ); }); } diff --git a/test/v2/v2_2.behavior.ts b/test/v2/v2_2.behavior.ts index a4185a57c..8e4f4e80c 100644 --- a/test/v2/v2_2.behavior.ts +++ b/test/v2/v2_2.behavior.ts @@ -56,7 +56,7 @@ export function behavesLikeFiatTokenV22( beforeEach(async () => { fiatToken = getFiatToken() as FiatTokenV2_2InstanceExtended; domainSeparator = makeDomainSeparator( - "USD Coin", + "USDC", "2", await web3.eth.getChainId(), fiatToken.address