Skip to content

Commit

Permalink
Add deploy script for MockERC1271 wallet
Browse files Browse the repository at this point in the history
* Create script to deploy MockERC1271Wallet

* Modify config.js

* Update documentation for testing sample ERC1271 wallet

* Update v2.2 doc
  • Loading branch information
yvonnezhangc authored and circle-aloychan committed Oct 19, 2023
1 parent e70c672 commit f2cdf23
Show file tree
Hide file tree
Showing 7 changed files with 148 additions and 18 deletions.
11 changes: 11 additions & 0 deletions config.js.example
Original file line number Diff line number Diff line change
Expand Up @@ -17,4 +17,15 @@ module.exports = {
PROXY_CONTRACT_ADDRESS: "",
// LostAndFound - tokens that were locked in the contract are sent to this
LOST_AND_FOUND_ADDRESS: "",
// MockERC1271WalletOwner - can deploy and send transactions from a sample ERC1271 wallet
MOCK_ERC1271_WALLET_OWNER_ADDRESS: "",

// TokenName - ERC20 name of the token e.g. "USD Coin"
TOKEN_NAME: "USD Coin",
// TokenSymbol - Symbol of the token e.g. "USDC"
TOKEN_SYMBOL: "USDC",
// TokenCurrency - Currency of the token e.g. "USD"
TOKEN_CURRENCY: "USD",
// TokenDecimals - Number of decimals for the token e.g. 6
TOKEN_DECIMALS: 6,
};
54 changes: 54 additions & 0 deletions doc/v2.2_upgrade.md
Original file line number Diff line number Diff line change
Expand Up @@ -125,3 +125,57 @@
function call will be reverted.
- Call `abortUpgrade()` (`0xd8f6a8f6`) method on the `V2_2Upgrader` contract to
tear it down.

### Optional - Testing support for ERC-1271 compatible wallets

FiatToken version 2.2 supports signature validation on the
[ERC-2612](https://eips.ethereum.org/EIPS/eip-2612) and
[ERC-3009](https://eips.ethereum.org/EIPS/eip-3009) features for
[ERC-1271](https://eips.ethereum.org/EIPS/eip-1271) compatible wallets. You may
test this with a sample ERC-1271 wallet to the network.

#### Preparation

1. Prepare a FiatToken version 2.2 contract for testing. If a FiatToken contract
has never been deployed to the network, follow the steps in the
[deployment doc](./deployment.md) to deploy the contract to the network.
Otherwise, follow the [steps](#steps) above to upgrade your FiatToken
contract to version 2.2.
2. Prepare an address A (Wallet Owner Address) that you own the private key to.
This address does not require any chain-native token (e.g. ETH) for gas
usage.
3. Prepare an address B (Relayer Address) that you own the private key to. Add
some chain-native token (e.g. ETH) to this address to pay for gas.

#### Instructions

1. Look for the `deploy_erc1271_wallet` scripts in
[`./migrations/`](../migrations/). Set the `MIGRATION_START` and
`MIGRATION_END` variables based off the migration numbers of these scripts.

```sh
$ MIGRATION_START=<first_migration_number>
$ MIGRATION_END=<last_migration_number>
```

2. Set the `MOCK_ERC1271_WALLET_OWNER_ADDRESS` in your `config.js` file to
address A.
3. Run Truffle migrations using the Deployer Key, and get the address of the
newly deployed `MockERC1271Wallet` contract.
```sh
$ yarn migrate --network ${NETWORK} --f ${MIGRATION_START} --to ${MIGRATION_END}
...
...
Dry-run successful. Do you want to proceed with real deployment? >> (y/n): y
...
...
>>>>>>> Deployed MockERC1271Wallet at 0x12345678 <<<<<<<
```
4. Generate a `permit` transaction signature using address A. This transaction
signature would update the allowance of a designated spender to pull funds
from the deployed smart contract wallet (MockERC1271Wallet).
5. Broadcast the signed transaction using address B. You may rely on public
tools ([example for ETH mainnet](https://etherscan.io/pushTx)) to complete
this step.
6. The transaction should succeed and the allowance should also be updated. You
may validate these using a block explorer.
File renamed without changes.
42 changes: 31 additions & 11 deletions migrations/2_deploy_v1.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ let ownerAddress = "";
let masterMinterAddress = "";
let pauserAddress = "";
let blacklisterAddress = "";
let tokenName = "";
let tokenSymbol = "";
let tokenCurrency = "";
let tokenDecimals = 0;

// Read config file if it exists
if (fs.existsSync(path.join(__dirname, "..", "config.js"))) {
Expand All @@ -21,6 +25,10 @@ if (fs.existsSync(path.join(__dirname, "..", "config.js"))) {
MASTERMINTER_ADDRESS: masterMinterAddress,
PAUSER_ADDRESS: pauserAddress,
BLACKLISTER_ADDRESS: blacklisterAddress,
TOKEN_NAME: tokenName,
TOKEN_SYMBOL: tokenSymbol,
TOKEN_CURRENCY: tokenCurrency,
TOKEN_DECIMALS: tokenDecimals,
} = require("../config.js"));
}

Expand All @@ -34,23 +42,35 @@ module.exports = async (deployer, network) => {
masterMinterAddress = "0x3E5e9111Ae8eB78Fe1CC3bb8915d5D461F3Ef9A9";
pauserAddress = "0xACa94ef8bD5ffEE41947b4585a84BdA5a3d3DA6E";
blacklisterAddress = "0xd03ea8624C8C5987235048901fB614fDcA89b117";
tokenName = "USD//C";
tokenSymbol = "USDC";
tokenCurrency = "USD";
tokenDecimals = 6;
}

console.log(`Proxy Admin: ${proxyAdminAddress}`);
console.log(`Owner: ${ownerAddress}`);
console.log(`Master Minter: ${masterMinterAddress}`);
console.log(`Pauser: ${pauserAddress}`);
console.log(`Blacklister: ${blacklisterAddress}`);
console.log(`Proxy Admin: ${proxyAdminAddress}`);
console.log(`Owner: ${ownerAddress}`);
console.log(`Master Minter: ${masterMinterAddress}`);
console.log(`Pauser: ${pauserAddress}`);
console.log(`Blacklister: ${blacklisterAddress}`);
console.log(`Token Name: ${tokenName}`);
console.log(`Token Symbol: ${tokenSymbol}`);
console.log(`Token Currency: ${tokenCurrency}`);
console.log(`Token Decimals: ${tokenDecimals}`);

if (
!proxyAdminAddress ||
!ownerAddress ||
!masterMinterAddress ||
!pauserAddress ||
!blacklisterAddress
!blacklisterAddress ||
!tokenName ||
!tokenSymbol ||
!tokenCurrency ||
!tokenDecimals
) {
throw new Error(
"PROXY_ADMIN_ADDRESS, OWNER_ADDRESS, MASTERMINTER_ADDRESS, PAUSER_ADDRESS, and BLACKLISTER_ADDRESS must be provided in config.js"
"PROXY_ADMIN_ADDRESS, OWNER_ADDRESS, MASTERMINTER_ADDRESS, PAUSER_ADDRESS, BLACKLISTER_ADDRESS, TOKEN_NAME, TOKEN_SYMBOL, TOKEN_CURRENCY, and TOKEN_DECIMALS must be provided in config.js"
);
}

Expand Down Expand Up @@ -86,10 +106,10 @@ module.exports = async (deployer, network) => {
// proxy will forward all the calls to the FiatTokenV1 impl
const proxyAsV1 = await FiatTokenV1.at(FiatTokenProxy.address);
await proxyAsV1.initialize(
"USD//C",
"USDC",
"USD",
6,
tokenName,
tokenSymbol,
tokenCurrency,
tokenDecimals,
masterMinterAddress,
pauserAddress,
blacklisterAddress,
Expand Down
11 changes: 8 additions & 3 deletions migrations/4_deploy_v2_upgrader.js
Original file line number Diff line number Diff line change
Expand Up @@ -8,12 +8,14 @@ const V2Upgrader = artifacts.require("V2Upgrader");

let proxyAdminAddress = "";
let proxyContractAddress = "";
let tokenName = "";

// Read config file if it exists
if (fs.existsSync(path.join(__dirname, "..", "config.js"))) {
({
PROXY_ADMIN_ADDRESS: proxyAdminAddress,
PROXY_CONTRACT_ADDRESS: proxyContractAddress,
TOKEN_NAME: tokenName,
} = require("../config.js"));
}

Expand All @@ -31,9 +33,12 @@ module.exports = async (deployer, network) => {
console.log(`Proxy Admin: ${proxyAdminAddress}`);
console.log(`FiatTokenProxy: ${proxyContractAddress}`);
console.log(`FiatTokenV2: ${fiatTokenV2.address}`);
console.log(`Token Name: ${tokenName}`);

if (!proxyAdminAddress) {
throw new Error("PROXY_ADMIN_ADDRESS must be provided in config.js");
if (!proxyContractAddress || !proxyAdminAddress || !tokenName) {
throw new Error(
"PROXY_CONTRACT_ADDRESS, PROXY_ADMIN_ADDRESS, and TOKEN_NAME must be provided in config.js"
);
}

console.log("Deploying V2Upgrader contract...");
Expand All @@ -43,7 +48,7 @@ module.exports = async (deployer, network) => {
proxyContractAddress,
fiatTokenV2.address,
proxyAdminAddress,
"USD Coin"
tokenName
);

console.log(`>>>>>>> Deployed V2Upgrader at ${v2Upgrader.address} <<<<<<<`);
Expand Down
11 changes: 7 additions & 4 deletions migrations/8_deploy_v2_2_upgrader.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,14 @@ const V2_2Upgrader = artifacts.require("V2_2Upgrader");

let proxyAdminAddress = "";
let proxyContractAddress = "";
let newTokenSymbol = "";

// Read config file if it exists
if (fs.existsSync(path.join(__dirname, "..", "config.js"))) {
({
PROXY_ADMIN_ADDRESS: proxyAdminAddress,
PROXY_CONTRACT_ADDRESS: proxyContractAddress,
TOKEN_SYMBOL: newTokenSymbol,
} = require("../config.js"));
}

Expand Down Expand Up @@ -46,9 +48,10 @@ module.exports = async (deployer, network) => {

const fiatTokenV2_2 = await FiatTokenV2_2.deployed();

console.log(`Proxy Admin: ${proxyAdminAddress}`);
console.log(`FiatTokenProxy: ${proxyContractAddress}`);
console.log(`FiatTokenV2_2: ${fiatTokenV2_2.address}`);
console.log(`Proxy Admin: ${proxyAdminAddress}`);
console.log(`FiatTokenProxy: ${proxyContractAddress}`);
console.log(`FiatTokenV2_2: ${fiatTokenV2_2.address}`);
console.log(`New Token Symbol: ${newTokenSymbol}`);

console.log("Deploying V2_2Upgrader contract...");

Expand All @@ -58,7 +61,7 @@ module.exports = async (deployer, network) => {
fiatTokenV2_2.address,
proxyAdminAddress,
accountsToBlacklist,
"USDC"
newTokenSymbol
);

console.log(
Expand Down
37 changes: 37 additions & 0 deletions migrations/9_deploy_erc1271_wallet.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
const fs = require("fs");
const path = require("path");
const some = require("lodash/some");

const MockERC1271Wallet = artifacts.require("MockERC1271Wallet");

let mockERC1271WalletOwnerAddress = "";

// Read config file if it exists
if (fs.existsSync(path.join(__dirname, "..", "config.js"))) {
({
MOCK_ERC1271_WALLET_OWNER_ADDRESS: mockERC1271WalletOwnerAddress,
} = require("../config.js"));
}

module.exports = async (deployer, network, accounts) => {
const isTestEnvironment = some(["development", "coverage"], (v) =>
network.includes(v)
);

if (isTestEnvironment) {
mockERC1271WalletOwnerAddress = accounts[0];
}

if (!mockERC1271WalletOwnerAddress) {
throw new Error(
"MOCK_ERC1271_WALLET_OWNER_ADDRESS must be provided in config.js"
);
}

console.log("Deploying MockERC1271Wallet contract...");

await deployer.deploy(MockERC1271Wallet, mockERC1271WalletOwnerAddress);
const walletAddress = (await MockERC1271Wallet.deployed()).address;

console.log(`>>>>>>> Deployed MockERC1271Wallet at ${walletAddress} <<<<<<<`);
};

0 comments on commit f2cdf23

Please sign in to comment.