Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

docs(ReadMe): Updated with correct addresses and user guide on new implementation #622

Merged
merged 14 commits into from
Mar 7, 2023
61 changes: 44 additions & 17 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -19,10 +19,6 @@ Users can get the GoerliETH via Goerli Faucet(https://goerlifaucet.com/)

The MUSDT and MUSDC contract have been deployed on Goerli for testing. Users will be able to mint tokens by calling the `mint()` function with the respective EOA (Externally Owned Account) or contract address and amount.

### When bridging to DeFiChain, what is the event that devs need to listen to, and what is the payload of that event?

On bridging to the DeFiChain, the event `BRIDGE_TO_DEFI_CHAIN(bytes defiAddress, address indexed tokenAddress, uint256 indexed amount , uint256 indexed timestamp);` will be emitted along with the user's defiAddress, the ERC20 token's address that is being bridged, the amount of the token being bridged, and the timestamp of the transaction.

### When bridging from DeFiChain, what is the expected signed message?

Expected message should be similar to `0x9a2618a0503cf675a85e4519fc97890fba5b851d15e02b8bc8f351d22b46580059c03992465695e89fc29e528797972d05de0b34768d5d3d7f772f2422eb9af01b == relayerAddress._signTypedData(domainData, eip712Types, eip712Data)`. This data is singed by the relayer address. Data that hasn't signed by the relayer address will revert with the error `FAKE_SIGNATURE`.
Expand All @@ -39,54 +35,79 @@ TODO

To change the state of any smart contract, users need to approve the smart contract of the respective token via the `approve()` function first. Once approved, user will be able to bridge the token over to DefiChain.

We are implementing a TimeLock contract that will work as an Admin address for ADMIN ONLY tx. There will be 3 days delay on every operational tx except when calling `Withdraw()` function.
cuongquangnam marked this conversation as resolved.
Show resolved Hide resolved

### TimeLock Contract Account Permission
cuongquangnam marked this conversation as resolved.
Show resolved Hide resolved

Gnosis safe will be implemented with both proposers and executors roles. Gnosis Safe has the authority to grant roles to addresses, as long as it holds the corresponding role itself. When revoking privileges, either the revokeRole() or renounceRole() functions must be used.
cuongquangnam marked this conversation as resolved.
Show resolved Hide resolved
cuongquangnam marked this conversation as resolved.
Show resolved Hide resolved

To execute only Admin transactions, the developer will need to follow these steps:

- First, create a transaction using Safe [guide](<(https://help.safe.global/en/articles/3738081-contract-interactions),>).
- After providing the contract address and ABI, the developer can select the contract method (in this case, we will try to change the transaction fee).
cuongquangnam marked this conversation as resolved.
Show resolved Hide resolved
- Select "Schedule". According to the Schedule() function, the following arguments need to be provided: address target, uint256 value, bytes calldata data, bytes32 predecessor, bytes32 salt, and uint256 delay.
- The target address is the Proxy Bridge. The value will usually be 0. The data is the encoded data of the function and arguments (BridgeV1Interface.encodeFunctionData('changeTxFee', [100])). Predecessor should almost always be 0x0 unless we have a prerequisite transaction, salt will be in incremented order (e.g., 0x0...1, 0x0...2, 0x0...3, and so on) and delay should be >= `getMinDelay()` which will be set to 3 days.

The reason behind choosing different salt is to avoid having the same transaction again.
cuongquangnam marked this conversation as resolved.
Show resolved Hide resolved

After scheduling the transaction using a timelock, the developer must call the execute() function with the provided arguments(same as above). If the execute() function is called before the specified `delay` time has passed, the transaction will revert with the error message "TimelockController: operation is not ready". This is because the timelock is designed to ensure that the specified delay time has elapsed before the transaction can be executed. Once the delay time has passed, the transaction can be executed normally.

### Bridge Contract Account Permission

There are only two roles: DEFAULT_ADMIN_ROLE and WITHDRAW_ROLE.

The TimeLock contract is assigned the DEFAULT_ADMIN_ROLE, while another Gnosis Safe is assigned the WITHDRAW_ROLE. The DEFAULT_ADMIN_ROLE has the ability to change both roles to other addresses, but this change will only take effect after three days.
cuongquangnam marked this conversation as resolved.
Show resolved Hide resolved

Finally, both addresses can renounce their own roles by calling the renounceRole() function.

### Bridge ERC20 tokens - to transfer ERC20 tokens from an EOA to the Bridge

Once approved, user will call the `bridgeToDeFiChain()` function with following arguments: `_defiAddress`- address on Defi Chain that receiving funds, `_tokenAddress` - ERC20 token's address and `_amount` amount to bridge over to Defi chain.

### Add supported token

Only addresses with the Admin and Operational roles can call the `addSupportedTokens()` function. This sets the `_tokenCap` for an ERC20 token and ETH identified by its `_tokenAddress`. All added tokens will be instantly supported by the bridge.
Only address with the Admin role can call the `addSupportedTokens()` function. This sets the `_tokenCap` for an ERC20 token and ETH identified by its `_tokenAddress`. All added tokens will be instantly supported by the bridge.
cuongquangnam marked this conversation as resolved.
Show resolved Hide resolved

In case of ETH, address(0) will be used as an address.

`_tokenCap` represent the maximum balance of tokens the contract can hold per `_tokenAddress`

### Remove supported token

Only addresses with the Admin and Operational role can call the `removeSupportedTokens()` function. This also sets the `_tokenCap` to `0`.
Only address with the Admin role can call the `removeSupportedTokens()` function. This also sets the `_tokenCap` to `0`.
cuongquangnam marked this conversation as resolved.
Show resolved Hide resolved

### Withdraw

`withdraw()` function when called will withdraw an ERC20 token and ETH (address == 0x0). Only the address with the Admin role can call this function.
`withdraw()` function when called will withdraw an ERC20 token and ETH (address == 0x0). Only the address with the WITHDRAW role can call this function.
cuongquangnam marked this conversation as resolved.
Show resolved Hide resolved

### FlushFund

`flushFund` function to flush the excess funds `(token.balanceOf(Bridge) - tokenCap)` across supported tokens to a hardcoded address (`flushReceiveAddress`) anyone can call this function. This applies to all tokens and ETH.
cuongquangnam marked this conversation as resolved.
Show resolved Hide resolved

### Change Flush Receive Address

Both the Admin and Operational addresses can change `flushReceiveAddress`.
Admin address can change `flushReceiveAddress`.
cuongquangnam marked this conversation as resolved.
Show resolved Hide resolved
`changeFlushReceiveAddress` function will reset the `flushReceiveAddress` to new address.

### Change relayer address

Both the Admin and Operational addresses can change `relayerAddress`.
Admin address can change `relayerAddress`.
cuongquangnam marked this conversation as resolved.
Show resolved Hide resolved

The relayer address will primarily be used for verifying the signature that is signed by the server. The server will need to sign with the corresponding private key of the relayer address.

### Transaction fee change

Only addresses with Admin and Operational roles can change `transactionFee`.
Only address with Admin role can change `transactionFee`.
cuongquangnam marked this conversation as resolved.
Show resolved Hide resolved

Initial fee will be set to 0.1%. This means that if the user bridges `X` tokens, 99.9% of X will be bridged. The other 0.1% will be taken as fees and sent to `communityWallet`.
Initial fee will be set to 0%. This means that if the user bridges `X` tokens, 100% of X will be bridged to defiChain. If in future, fee > 0, respected amount will be sent to `communityWallet`.

### Change Tx Fee Address

Only addresses with admin and Operational roles can change `communityWallet`. This is where the tx fees upon bridging will go.
Only address with admin role can change `communityWallet`. This is where the tx fees upon bridging will go.
cuongquangnam marked this conversation as resolved.
Show resolved Hide resolved

### Change Token Cap

Only addresses with admin and Operational roles can change `tokenCap`.
Only address with admin role can change `tokenCap`.
cuongquangnam marked this conversation as resolved.
Show resolved Hide resolved

### Modify admin and operational address

Expand Down Expand Up @@ -129,9 +150,13 @@ MUSDT Contract address: [0xA218A0EA9a888e3f6E2dfFdf4066885f596F07bF](https://goe

MUSDC Contract address: [0xB200af2b733B831Fbb3d98b13076BC33F605aD58](https://goerli.etherscan.io/address/0xB200af2b733B831Fbb3d98b13076BC33F605aD58)

### TimeLock

Time lock Contract address: [0x78B29c165d2faFc78b76A029F0014cAd89900DCa](https://goerli.etherscan.io/address/0x78B29c165d2faFc78b76A029F0014cAd89900DCa)

### BridgeV1

BridgeV1 Contract address: [0xB5AA3ba3F4bF825AAF96F1ee9Fa0D6b3702Dc8B6](https://goerli.etherscan.io/address/0xB5AA3ba3F4bF825AAF96F1ee9Fa0D6b3702Dc8B6)
BridgeV1 Contract address: [0x57762d794587EdF59f2087DCD6D99eB0105b1A8f](https://goerli.etherscan.io/address/0x57762d794587EdF59f2087DCD6D99eB0105b1A8f)

### BridgeProxy

Expand All @@ -147,14 +172,16 @@ Admins can send ERC20 tokens via the `transfer(address _to, uint256 _amount)` fu

### Withdrawing funds

ERC20 tokens can be withdrawn by the Admin address only via the `withdraw(address _tokenAddress, uint256 amount)` function.
ETH and ERC20 tokens can be withdrawn by the address with WITHDRAW_ROLE only via the `withdraw(address _tokenAddress, uint256 amount)` function.
cuongquangnam marked this conversation as resolved.
Show resolved Hide resolved

## Admin and Operational addresses - Gnosis safe
## Admin address - Gnosis safe

Admin and Operational addresses will be Gnosis safes, ideally will be with at least 3 owners with a 2/3 quorum.
Admin address will be Gnosis safe, ideally will be with at least 3 owners with a 2/3 quorum.
cuongquangnam marked this conversation as resolved.
Show resolved Hide resolved

More admins can be added later, for more info, refer to [Gnosis safe: adding owners](https://help.gnosis-safe.io/en/articles/3950657-add-owners).

Admin Gnosis address: [gor:0xdD42792d3F18bb693A669e5096f866cb96AEdA13](https://goerli.etherscan.io/address/0xdD42792d3F18bb693A669e5096f866cb96AEdA13)

## Workflow for generating Prisma Client and applying database migrations

After making changes to the database schema in schema.prisma, run `cd apps/server` in terminal (/bridge).
Expand Down
14 changes: 7 additions & 7 deletions packages/smartcontracts/src/scripts/deployTimelockController.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { ethers } from 'hardhat';
import { ethers, network } from 'hardhat';

import { TimelockController } from '../generated';

Expand All @@ -8,16 +8,16 @@ export async function deployTimelockController({
executors,
admin,
}: InputsForInitialization): Promise<TimelockController> {
// const { chainId } = network.config;
const { chainId } = network.config;
const timelockControllerFactory = await ethers.getContractFactory('TimelockController');
const timelockController = await timelockControllerFactory.deploy(minDelay, proposers, executors, admin);
await timelockController.deployed();
console.log('Timelock Controller Address: ', timelockController.address);
// if (chainId !== 1337) {
// console.log(
// `To verify on Etherscan: npx hardhat verify --network goerli --contract contracts/BridgeProxy.sol:BridgeProxy ${timelockController} ${bridgeV1Address} ${encodedData}`,
// );
// }
if (chainId !== 1337) {
console.log(
`To verify on Etherscan: npx hardhat verify --network goerli --contract contracts/TimelockController.sol:TimelockController ${timelockController.address} ${minDelay} ${proposers} ${executors} ${admin}`,
);
}

return timelockController;
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,10 @@ import { deployContracts } from './testUtils/deployment';
describe('Transaction fee tests', () => {
describe('Tx Fee tests', () => {
describe('DEFAULT_ADMIN_ROLE', () => {
it('Successfully implemented the 0.1% fee', async () => {
it('Successfully implemented the 0% fee', async () => {
const { proxyBridge } = await loadFixture(deployContracts);
// Checking if the implemented fee is 0.1%
expect(await proxyBridge.transactionFee()).to.equal(10);
// Checking if the implemented fee is 0%
expect(await proxyBridge.transactionFee()).to.equal(0);
});

it('Successfully changes the fee by Admin account', async () => {
Expand All @@ -26,7 +26,7 @@ describe('Transaction fee tests', () => {
// Event called TRANSACTION_FEE_CHANGED should be emitted on Successful withdrawal by the Admin only
await expect(proxyBridge.connect(defaultAdminSigner).changeTxFee(50))
.to.emit(proxyBridge, 'TRANSACTION_FEE_CHANGED')
.withArgs(10, 50);
.withArgs(0, 50);
});
});
});
Expand All @@ -44,8 +44,8 @@ describe('Transaction fee tests', () => {
const { proxyBridge } = await loadFixture(deployContracts);
// Admin should not be able to change the tx fees to more than 100%
await expect(proxyBridge.changeTxFee(10100)).to.be.revertedWithCustomError(proxyBridge, 'MORE_THAN_MAX_FEE');
// Fee should be 0.1%
expect(await proxyBridge.transactionFee()).to.equal(10);
// Fee should be 0%
expect(await proxyBridge.transactionFee()).to.equal(0);
});
});

Expand Down
4 changes: 2 additions & 2 deletions packages/smartcontracts/src/tests/testUtils/deployment.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,8 +23,8 @@ export async function deployContracts(): Promise<BridgeDeploymentResult> {
accounts[0],
// community wallet address
accounts[4],
// 0.1%
10,
// 0%
0,
// flushReceiveAddress
accounts[3],
]);
Expand Down