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
88 changes: 72 additions & 16 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,58 +31,92 @@ TODO

TODO

## Operational Transactions
####
weiyuan95 marked this conversation as resolved.
Show resolved Hide resolved

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, TimeLock contract is not able to call this function.

### 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 (in seconds) should be >= `getMinDelay()` which will be set to 3 days.

Salt can be `0x0000000000000000000000000000000000000000000000000000000000000000` for 1st transaction,
`0x0000000000000000000000000000000000000000000000000000000000000001` for 2nd transaction and so on.

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.

## Operational Transactions
cuongquangnam marked this conversation as resolved.
Show resolved Hide resolved

### 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 grant 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
### flushMultipleTokenFunds

`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.
`flushMultipleTokenFunds(uint256 _fromIndex, uint256 _toIndex)` function to flush the excess funds `(token.balanceOf(Bridge) - tokenCap)` across supported tokens to a hardcoded address (`flushReceiveAddress`) anyone can call this function. For example, calling flushMultipleTokenFunds(0,3), only the tokens at index 0, 1 and 2 will be flushed. This applies to all tokens and ETH.

### flushFundPerToken

`flushFundPerToken(address _tokenAddress)` is doing same as above function, however doing on token basis instead of from and to indexes.

### 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 @@ -113,6 +147,22 @@ Before running the above command, following `vars` need to be addressed:

To Mint the test tokens and Approve the Bridge Contract devs will have to run a command `npx hardhat run --network goerli ./scripts/mintTestToken.ts` in smartContract directory. Script will mint `100_000` tokens.

## Mainnet Addresses

### TimeLock

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

### BridgeV1

BridgeV1 Contract address: [0x7bdbd5675bad2653cba9bc0e09564dd8d7b53957](https://etherscan.io/address/0x7bdbd5675bad2653cba9bc0e09564dd8d7b53957)

### BridgeProxy

BridgeProxy Contract address: [0x54346d39976629b65ba54eac1c9ef0af3be1921b](https://etherscan.io/address/0x54346d39976629b65ba54eac1c9ef0af3be1921b)

## Testnet Addresses

### MWBTC

MWBTC Contract address: [0xD723D679d1A3b23d0Aafe4C0812f61DDA84fc043](https://goerli.etherscan.io/address/0xd723d679d1a3b23d0aafe4c0812f61dda84fc043)
Expand All @@ -125,9 +175,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 @@ -143,14 +197,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
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