diff --git a/README.md b/README.md index 5ea5e59b8..d4cfcbcbe 100644 --- a/README.md +++ b/README.md @@ -31,17 +31,47 @@ TODO TODO -## Operational Transactions +## Contract Operations 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 Operations + +Gnosis safe will be implemented with both proposers and executors roles. Only the Timelock smart contract has the role (TIMELOCK_ADMIN_ROLE) to grant roles for now. If we want to grant new roles to new addresses, have to go through a round of scheduling and executing the grantRole functions through the Timelock contract. When revoking privileges, either the revokeRole() or renounceRole() functions must be used. + +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). +- 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 operation identifier again. + +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 operations + +### 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 these changes will happen instantly once executed. + +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. In case of ETH, address(0) will be used as an address. @@ -49,40 +79,44 @@ In case of ETH, address(0) will be used as an address. ### 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`. ### 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. + +### flushMultipleTokenFunds -### FlushFund +`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. -`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. +### 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`. `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`. 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`. -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. ### Change Token Cap -Only addresses with admin and Operational roles can change `tokenCap`. +Only address with admin role can change `tokenCap`. ### Modify admin and operational address @@ -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) @@ -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 @@ -141,16 +195,6 @@ Anyone can send funds to the bridge contract. Ideally, this should be done by li Admins can send ERC20 tokens via the `transfer(address _to, uint256 _amount)` function or utilizing wallets such as Metamask. -### Withdrawing funds - -ERC20 tokens can be withdrawn by the Admin address only via the `withdraw(address _tokenAddress, uint256 amount)` function. - -## Admin and Operational addresses - Gnosis safe - -Admin and Operational addresses will be Gnosis safes, ideally will be with at least 3 owners with a 2/3 quorum. - -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). - ## 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). diff --git a/packages/smartcontracts/src/tests/BridgeProxy.transactionFee.spec.ts b/packages/smartcontracts/src/tests/BridgeProxy.transactionFee.spec.ts index 4a52705f0..74d188aa2 100644 --- a/packages/smartcontracts/src/tests/BridgeProxy.transactionFee.spec.ts +++ b/packages/smartcontracts/src/tests/BridgeProxy.transactionFee.spec.ts @@ -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 () => { @@ -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); }); }); }); @@ -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); }); }); diff --git a/packages/smartcontracts/src/tests/testUtils/deployment.ts b/packages/smartcontracts/src/tests/testUtils/deployment.ts index b76f2b164..b0534f66c 100644 --- a/packages/smartcontracts/src/tests/testUtils/deployment.ts +++ b/packages/smartcontracts/src/tests/testUtils/deployment.ts @@ -23,8 +23,8 @@ export async function deployContracts(): Promise { accounts[0], // community wallet address accounts[4], - // 0.1% - 10, + // 0% + 0, // flushReceiveAddress accounts[3], ]);