Skip to content

Commit

Permalink
PP-565: migrate the removeTokens script to use Hardhat and Ethers.js (#…
Browse files Browse the repository at this point in the history
…92)

* refactor: migrate the removeTokens script to use Hardhat and Ethers.js

* fix: fix the task in hardhat.config, update Readme and apply format

Co-authored-by: Antonio Morrone <antonio@iovlabs.org>
  • Loading branch information
AndresQuijano and antomor committed Nov 17, 2022
1 parent 9c2696d commit 36e0648
Show file tree
Hide file tree
Showing 5 changed files with 196 additions and 3 deletions.
9 changes: 6 additions & 3 deletions Readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ This project is part of the RIF Relay ecosystem. It contains all the smart contr
- [**Deployment**](#deployment)
- [**Addresses**](#addresses)
- [**System usage**](#system-usage)
- [**Allowing tokens**](#allowing-tokens)
- [**Managing tokens**](#managing-tokens)
- [**UtilToken Minting**](#UtilToken-minting)
- [**Library usage**](#library-usage)
- [**As a dependency**](#as-a-dependency)
Expand Down Expand Up @@ -104,14 +104,17 @@ This file also is being exported on the distributable version to provide the con

## System usage

### Allowing tokens
### Managing tokens

Once the smart contracts are deployed, tokens must be individually allowed to be able to work with the RIF Relay system. There are some helpful commands for this:
Once the smart contracts are deployed, tokens must be individually allowed to be able to work with the RIF Relay system. In the same way, tokens can be removed from the list of previously allowed tokens. There are some helpful commands for this:

1. To allow a specific token, run `npm run allow-tokens <NETWORK_NAME> <TOKEN_ADDRESSES>` where:
- `<TOKEN_ADDRESSES>` is a comma-separated list of the token addresses to be allowed on the available verifiers
- `<NETWORK_NAME>` is an optional parameter for the network name, taken from the `hardhat.config.ts` file (default value is `hardhat`) **important! This should be the same network name as the one used to deploy the contracts**
2. To query allowed tokens run `npm run allowed-tokens <NETWORK_NAME>`. This will display them on the console.
3. To remove a sepecific token, run `npm run remove-tokens <NETWORK_NAME> <TOKEN_ADDRESSES>` where:
- `<TOKEN_ADDRESSES>` is a comma-separated list of the token addresses to be removed on the available verifiers.
- `<NETWORK_NAME>` is an optional parameter for the network name, taken from the `hardhat.config.ts` file (default value is `hardhat`) **important! This should be the same network name as the one used to deploy the contracts**.

### UtilToken Minting

Expand Down
8 changes: 8 additions & 0 deletions hardhat.config.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import 'hardhat-docgen';
import 'hardhat-watcher';
import '@nomiclabs/hardhat-ethers';
import { allowTokens } from './scripts/allowTokens';
import { removeTokens } from './scripts/removeTokens';
import { deploy } from './scripts/deploy';
import { HardhatUserConfig, task } from 'hardhat/config';
import { getAllowedTokens } from './scripts/getAllowedTokens';
Expand Down Expand Up @@ -95,4 +96,11 @@ task('allowed-tokens', 'Retrieves a list of allowed tokens')
}
);

task('remove-tokens', 'Removes a list of tokens')
.addPositionalParam('tokenlist', 'list of tokens')
.setAction(async (taskArgs: {tokenlist: string}, hre) => {
await removeTokens(taskArgs, hre);
}
);

export default config;
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -76,6 +76,7 @@
"lint:sol": "solhint --fix 'contracts/**/*.sol'",
"lint:ts": "eslint test --ext .ts --fix",
"prepare": "./scripts/prepare.npm",
"remove-tokens": "hardhat remove-tokens --network",
"pretdd": "npm run build",
"tdd": "TEST=true REPORT_GAS=true hardhat watch tdd",
"test": "TEST=true REPORT_GAS=true hardhat test"
Expand Down
108 changes: 108 additions & 0 deletions scripts/removeTokens.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
import { ContractTransaction } from 'ethers';
import { HardhatRuntimeEnvironment } from 'hardhat/types';
import { getExistingConfig } from './deploy';

export const removeTokens = async (
taskArgs: { tokenlist: string },
hre: HardhatRuntimeEnvironment
) => {
const tokenAddresses = taskArgs.tokenlist.split(',');

const { ethers, network } = hre;

if (!network) {
throw new Error('Unknown Network');
}

const { chainId } = network.config;

if (!chainId) {
throw new Error('Unknown Chain Id');
}

const contractAddresses = getExistingConfig();

if (!contractAddresses) {
throw new Error('No contracts deployed');
}

const networkChainKey = `${network.name}.${chainId}`;
const contractAddressesDeployed = contractAddresses[networkChainKey];

if (!contractAddressesDeployed) {
throw new Error(`Contracts not deployed for chain ID ${chainId}`);
}

const deployVerifierAddress = contractAddressesDeployed.DeployVerifier;
const relayVerifierAddress = contractAddressesDeployed.RelayVerifier;
const customDeployVerifierAddress =
contractAddressesDeployed.CustomSmartWalletDeployVerifier;
const customRelayVerifierAddress =
contractAddressesDeployed.CustomSmartWalletRelayVerifier;

if (!deployVerifierAddress) {
throw new Error('Could not obtain deploy verifier address');
}

if (!relayVerifierAddress) {
throw new Error('Could not obtain relay verifier address');
}

if (!customDeployVerifierAddress) {
throw new Error('Could not obtain custom deploy verifier address');
}

if (!customRelayVerifierAddress) {
throw new Error('Could not obtain custom deploy verifier address');
}

const deployVerifier = await ethers.getContractAt(
'DeployVerifier',
deployVerifierAddress
);
const relayVerifier = await ethers.getContractAt(
'RelayVerifier',
relayVerifierAddress
);
const customDeployVerifier = await ethers.getContractAt(
'CustomSmartWalletDeployVerifier',
customDeployVerifierAddress
);
const customRelayVerifier = await ethers.getContractAt(
'RelayVerifier',
customRelayVerifierAddress
);

const verifierMap: Map<
string,
{
removeToken: (
tokenAddress: string,
index: number
) => Promise<ContractTransaction>;
getAcceptedTokens: () => Promise<string[]>;
}
> = new Map();

verifierMap.set('deployVerifier', deployVerifier);
verifierMap.set('relayVerifier', relayVerifier);
verifierMap.set('customDeployVerifier', customDeployVerifier);
verifierMap.set('customRelayVerifier', customRelayVerifier);

for (const tokenAddress of tokenAddresses) {
for (const [key, verifier] of verifierMap) {
try {
const index = (await verifier.getAcceptedTokens()).indexOf(
tokenAddress
);
await verifier.removeToken(tokenAddress, index);
} catch (error) {
console.error(
`Error removing token with address ${tokenAddress} from allowed tokens on ${key}`
);
throw error;
}
}
}
console.log('Tokens removed successfully!');
};
73 changes: 73 additions & 0 deletions test/scripts/removeTokens.test.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import { expect, use } from 'chai';
import chaiAsPromised from 'chai-as-promised';
import { Contract } from 'ethers';
import fs from 'fs';
import * as hre from 'hardhat';
import { ethers } from 'hardhat';
import sinon from 'sinon';
import {
removeTokens
} from '../../scripts/removeTokens';

use(chaiAsPromised);

describe('Remove Tokens Script', function () {
describe('removeTokens', function () {
const taskArgs = { tokenlist: '0x145845fd06c85B7EA1AA2d030E1a747B3d8d15D7' };

const contractAddresses = {
Penalizer: '0x145845fd06c85B7EA1AA2d030E1a747B3d8d15D7',
RelayHub: '0x145845fd06c85B7EA1AA2d030E1a747B3d8d15D7',
SmartWallet: '0x145845fd06c85B7EA1AA2d030E1a747B3d8d15D7',
SmartWalletFactory: '0x145845fd06c85B7EA1AA2d030E1a747B3d8d15D7',
DeployVerifier: '0x145845fd06c85B7EA1AA2d030E1a747B3d8d15D7',
RelayVerifier: '0x145845fd06c85B7EA1AA2d030E1a747B3d8d15D7',
CustomSmartWallet: '0x145845fd06c85B7EA1AA2d030E1a747B3d8d15D7',
CustomSmartWalletFactory: '0x145845fd06c85B7EA1AA2d030E1a747B3d8d15D7',
CustomSmartWalletDeployVerifier:
'0x145845fd06c85B7EA1AA2d030E1a747B3d8d15D7',
CustomSmartWalletRelayVerifier:
'0x145845fd06c85B7EA1AA2d030E1a747B3d8d15D7',
VersionRegistry: '0x145845fd06c85B7EA1AA2d030E1a747B3d8d15D7',
UtilToken: '0x145845fd06c85B7EA1AA2d030E1a747B3d8d15D7',
};

const chainContractAddresses = {
'hardhat.33': contractAddresses,
};

beforeEach(function () {
sinon.stub(fs, 'existsSync').returns(true);
sinon
.stub(fs, 'readFileSync')
.returns(JSON.stringify(chainContractAddresses));
hre.network.config.chainId = 33;
});

afterEach(function () {
sinon.restore();
});

it('should remove a list of tokens', async function () {
const stubContract = sinon.createStubInstance(Contract);
stubContract['removeToken'] = () => undefined;
stubContract['getAcceptedTokens'] = () => {
return [
'0x145845fd06c85B7EA1AA2d030E1a747B3d8d15D8',
'0x145845fd06c85B7EA1AA2d030E1a747B3d8d15D7'
];
};
sinon.stub(ethers, 'getContractAt').resolves(stubContract);
await expect(removeTokens(taskArgs, hre)).to.not.be.rejected;
});

it('should throw error and print it if token cannot be removed', async function () {
const stubContract = sinon.createStubInstance(Contract);
stubContract['removeToken'] = () => {
throw new Error();
};
sinon.stub(ethers, 'getContractAt').resolves(stubContract);
await expect(removeTokens(taskArgs, hre)).to.be.rejected;
});
});
});

0 comments on commit 36e0648

Please sign in to comment.