From 7931bee829726b6c857367eac12f11313e08f9fa Mon Sep 17 00:00:00 2001 From: Abhishek Date: Thu, 2 Mar 2023 16:30:14 +1300 Subject: [PATCH 01/13] Updated read me with correct addresses --- README.md | 30 +++++++++++-------- .../test/reinitialize/BridgeV2TestNet.sol | 10 ++++++- .../smartcontracts/src/scripts/arguments.ts | 6 ++++ .../src/scripts/deployTimelockController.ts | 14 ++++----- 4 files changed, 40 insertions(+), 20 deletions(-) create mode 100644 packages/smartcontracts/src/scripts/arguments.ts diff --git a/README.md b/README.md index 63cb3e1a5..a3f854c1b 100644 --- a/README.md +++ b/README.md @@ -45,7 +45,7 @@ Once approved, user will call the `bridgeToDeFiChain()` function with following ### 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 addresses 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. @@ -53,11 +53,11 @@ 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 addresses 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. ### FlushFund @@ -65,28 +65,28 @@ Only addresses with the Admin and Operational role can call the `removeSupported ### 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 addresses with admin role can change `tokenCap`. ### Modify admin and operational address @@ -129,9 +129,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 @@ -149,12 +153,14 @@ Admins can send ERC20 tokens via the `transfer(address _to, uint256 _amount)` fu 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 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. 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). diff --git a/packages/smartcontracts/src/contracts/test/reinitialize/BridgeV2TestNet.sol b/packages/smartcontracts/src/contracts/test/reinitialize/BridgeV2TestNet.sol index 58088af96..bbc4ad288 100644 --- a/packages/smartcontracts/src/contracts/test/reinitialize/BridgeV2TestNet.sol +++ b/packages/smartcontracts/src/contracts/test/reinitialize/BridgeV2TestNet.sol @@ -218,8 +218,16 @@ contract BridgeV2TestNet is UUPSUpgradeable, EIP712Upgradeable, AccessControlUpg * @notice To initialize the proxy state * @param _version Contract's version */ - function initialize(uint8 _version) external reinitializer(_version) { + function initialize( + address _timelockContract, + address _initialWithdraw, + uint256 _fee, + uint8 _version + ) external reinitializer(_version) { __EIP712_init(NAME, StringsUpgradeable.toString(_version)); + _grantRole(DEFAULT_ADMIN_ROLE, _timelockContract); + _grantRole(WITHDRAW_ROLE, _initialWithdraw); + transactionFee = _fee; } /** diff --git a/packages/smartcontracts/src/scripts/arguments.ts b/packages/smartcontracts/src/scripts/arguments.ts new file mode 100644 index 000000000..59951dc47 --- /dev/null +++ b/packages/smartcontracts/src/scripts/arguments.ts @@ -0,0 +1,6 @@ +export = [ + 900, + ['0xdD42792d3F18bb693A669e5096f866cb96AEdA13'], + ['0xdD42792d3F18bb693A669e5096f866cb96AEdA13'], + '0x0000000000000000000000000000000000000000', +]; diff --git a/packages/smartcontracts/src/scripts/deployTimelockController.ts b/packages/smartcontracts/src/scripts/deployTimelockController.ts index 6dfab1e27..2fd4bd790 100644 --- a/packages/smartcontracts/src/scripts/deployTimelockController.ts +++ b/packages/smartcontracts/src/scripts/deployTimelockController.ts @@ -1,4 +1,4 @@ -import { ethers } from 'hardhat'; +import { ethers, network } from 'hardhat'; import { TimelockController } from '../generated'; @@ -8,16 +8,16 @@ export async function deployTimelockController({ executors, admin, }: InputsForInitialization): Promise { - // 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; } From 8ee4836a38e6f93a0f703080db7a6948a35c918f Mon Sep 17 00:00:00 2001 From: Abhishek Date: Thu, 2 Mar 2023 18:44:05 +1300 Subject: [PATCH 02/13] Updated read me --- README.md | 22 +++++++++++++++---- .../test/reinitialize/BridgeV2TestNet.sol | 10 +-------- .../smartcontracts/src/scripts/arguments.ts | 6 ----- 3 files changed, 19 insertions(+), 19 deletions(-) delete mode 100644 packages/smartcontracts/src/scripts/arguments.ts diff --git a/README.md b/README.md index a3f854c1b..5887907cd 100644 --- a/README.md +++ b/README.md @@ -39,13 +39,27 @@ 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. + +#### TimeLock Contract Account Permission + +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. + +#### 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. + +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 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. +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. @@ -53,7 +67,7 @@ In case of ETH, address(0) will be used as an address. ### Remove supported token -Only addresses with the Admin 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 @@ -86,7 +100,7 @@ Only address with admin role can change `communityWallet`. This is where the tx ### Change Token Cap -Only addresses with admin role can change `tokenCap`. +Only address with admin role can change `tokenCap`. ### Modify admin and operational address @@ -151,7 +165,7 @@ 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. ## Admin address - Gnosis safe diff --git a/packages/smartcontracts/src/contracts/test/reinitialize/BridgeV2TestNet.sol b/packages/smartcontracts/src/contracts/test/reinitialize/BridgeV2TestNet.sol index bbc4ad288..58088af96 100644 --- a/packages/smartcontracts/src/contracts/test/reinitialize/BridgeV2TestNet.sol +++ b/packages/smartcontracts/src/contracts/test/reinitialize/BridgeV2TestNet.sol @@ -218,16 +218,8 @@ contract BridgeV2TestNet is UUPSUpgradeable, EIP712Upgradeable, AccessControlUpg * @notice To initialize the proxy state * @param _version Contract's version */ - function initialize( - address _timelockContract, - address _initialWithdraw, - uint256 _fee, - uint8 _version - ) external reinitializer(_version) { + function initialize(uint8 _version) external reinitializer(_version) { __EIP712_init(NAME, StringsUpgradeable.toString(_version)); - _grantRole(DEFAULT_ADMIN_ROLE, _timelockContract); - _grantRole(WITHDRAW_ROLE, _initialWithdraw); - transactionFee = _fee; } /** diff --git a/packages/smartcontracts/src/scripts/arguments.ts b/packages/smartcontracts/src/scripts/arguments.ts deleted file mode 100644 index 59951dc47..000000000 --- a/packages/smartcontracts/src/scripts/arguments.ts +++ /dev/null @@ -1,6 +0,0 @@ -export = [ - 900, - ['0xdD42792d3F18bb693A669e5096f866cb96AEdA13'], - ['0xdD42792d3F18bb693A669e5096f866cb96AEdA13'], - '0x0000000000000000000000000000000000000000', -]; From 96069c409d01641b3b0fa5f899035f6e1cc24625 Mon Sep 17 00:00:00 2001 From: Abhishek Date: Thu, 2 Mar 2023 19:57:36 +1300 Subject: [PATCH 03/13] Fixes #624 --- .../src/tests/BridgeProxy.transactionFee.spec.ts | 12 ++++++------ .../src/tests/TimelockController.spec.ts | 15 +++++++++++++++ .../src/tests/testUtils/deployment.ts | 4 ++-- 3 files changed, 23 insertions(+), 8 deletions(-) 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/TimelockController.spec.ts b/packages/smartcontracts/src/tests/TimelockController.spec.ts index 339c817d4..513d5cd94 100644 --- a/packages/smartcontracts/src/tests/TimelockController.spec.ts +++ b/packages/smartcontracts/src/tests/TimelockController.spec.ts @@ -101,5 +101,20 @@ describe('Sanity tests for Timelock Controller', () => { ), ).to.revertedWith('TimelockController: operation already scheduled'); }); + + it('Changing tx time', async () => { + console.log('data: ', BridgeV1Interface.encodeFunctionData('changeTxFee', [0])); + console.log('predecessor: ', ZERO_BYTES32); + console.log('salt: ', '0x1'); + console.log( + await timelockController.hashOperation( + '0x96E5E1d6377ffA08B9c08B066f430e33e3c4C9ef', + 0, + '0x610103d90000000000000000000000000000000000000000000000000000000000000000', + '0x0000000000000000000000000000000000000000000000000000000000000000', + '0x0000000000000000000000000000000000000000000000000000000000000001', + ), + ); + }); }); }); 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], ]); From 0a84617d9a6b78c6938b852f8adbcdb77d26e2ba Mon Sep 17 00:00:00 2001 From: Abhishek Date: Thu, 2 Mar 2023 23:09:21 +1300 Subject: [PATCH 04/13] Added user guide --- README.md | 13 +++++++++++-- .../src/tests/TimelockController.spec.ts | 17 +---------------- 2 files changed, 12 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 5887907cd..1acd86e6c 100644 --- a/README.md +++ b/README.md @@ -41,11 +41,20 @@ To change the state of any smart contract, users need to approve the smart contr 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 Account Permission +### TimeLock Contract Account Permission 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. -#### Bridge Contract Account Permission +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])). The predecessor is ZERO_BYTES32, and the salt will be in incremented order (e.g., 0x0...1, 0x0...2, 0x0...3, and so on). + +The reason behind choosing this way is to avoid having the same transaction multiple times. + +### Bridge Contract Account Permission There are only two roles: DEFAULT_ADMIN_ROLE and WITHDRAW_ROLE. diff --git a/packages/smartcontracts/src/tests/TimelockController.spec.ts b/packages/smartcontracts/src/tests/TimelockController.spec.ts index 513d5cd94..62714cf69 100644 --- a/packages/smartcontracts/src/tests/TimelockController.spec.ts +++ b/packages/smartcontracts/src/tests/TimelockController.spec.ts @@ -27,7 +27,7 @@ describe('Sanity tests for Timelock Controller', () => { const callDataForChangeTxFee = BridgeV1Interface.encodeFunctionData('changeTxFee', [1000]); it('Schedule successfully', async () => { - ({ proxyBridge, defaultAdminSigner } = await loadFixture(deployContracts)); + ({ proxyBridge, defaultAdminSigner, arbitrarySigner } = await loadFixture(deployContracts)); const TimelockControllerFactory = await ethers.getContractFactory('TimelockController'); timelockController = await TimelockControllerFactory.deploy( // minDelay @@ -101,20 +101,5 @@ describe('Sanity tests for Timelock Controller', () => { ), ).to.revertedWith('TimelockController: operation already scheduled'); }); - - it('Changing tx time', async () => { - console.log('data: ', BridgeV1Interface.encodeFunctionData('changeTxFee', [0])); - console.log('predecessor: ', ZERO_BYTES32); - console.log('salt: ', '0x1'); - console.log( - await timelockController.hashOperation( - '0x96E5E1d6377ffA08B9c08B066f430e33e3c4C9ef', - 0, - '0x610103d90000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000000', - '0x0000000000000000000000000000000000000000000000000000000000000001', - ), - ); - }); }); }); From b672d7f6b133cb336602fa3012e06cb3fcc825d4 Mon Sep 17 00:00:00 2001 From: Abhishek Date: Thu, 2 Mar 2023 23:13:14 +1300 Subject: [PATCH 05/13] Fix SMs CL test --- packages/smartcontracts/src/tests/TimelockController.spec.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/smartcontracts/src/tests/TimelockController.spec.ts b/packages/smartcontracts/src/tests/TimelockController.spec.ts index 62714cf69..339c817d4 100644 --- a/packages/smartcontracts/src/tests/TimelockController.spec.ts +++ b/packages/smartcontracts/src/tests/TimelockController.spec.ts @@ -27,7 +27,7 @@ describe('Sanity tests for Timelock Controller', () => { const callDataForChangeTxFee = BridgeV1Interface.encodeFunctionData('changeTxFee', [1000]); it('Schedule successfully', async () => { - ({ proxyBridge, defaultAdminSigner, arbitrarySigner } = await loadFixture(deployContracts)); + ({ proxyBridge, defaultAdminSigner } = await loadFixture(deployContracts)); const TimelockControllerFactory = await ethers.getContractFactory('TimelockController'); timelockController = await TimelockControllerFactory.deploy( // minDelay From 43099d528c203507f1a24124f1f7d97de8b53f52 Mon Sep 17 00:00:00 2001 From: Abhishek Date: Fri, 3 Mar 2023 15:32:22 +1300 Subject: [PATCH 06/13] Updat on execute fn --- README.md | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 1acd86e6c..d108274de 100644 --- a/README.md +++ b/README.md @@ -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`. @@ -50,9 +46,11 @@ To execute only Admin transactions, the developer will need to follow these step - 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])). The predecessor is ZERO_BYTES32, and the salt will be in incremented order (e.g., 0x0...1, 0x0...2, 0x0...3, and so on). +- 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. -The reason behind choosing this way is to avoid having the same transaction multiple times. +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 From a25b52bbc7527e6dc4b706216c64cc08ad4565c0 Mon Sep 17 00:00:00 2001 From: Abhishek Date: Fri, 3 Mar 2023 16:03:51 +1300 Subject: [PATCH 07/13] Minor changes --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index d108274de..2dfecd160 100644 --- a/README.md +++ b/README.md @@ -46,7 +46,7 @@ To execute only Admin transactions, the developer will need to follow these step - 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 should be >= `getMinDelay()` which will be set to 3 days. +- 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. The reason behind choosing different salt is to avoid having the same transaction again. From 35920ab5340a29b4c1208b0b5e18b984cad730f5 Mon Sep 17 00:00:00 2001 From: Abhishek Date: Fri, 3 Mar 2023 16:13:50 +1300 Subject: [PATCH 08/13] Minor changes- forgot to save before. --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 2dfecd160..9cf61d350 100644 --- a/README.md +++ b/README.md @@ -48,6 +48,9 @@ To execute only Admin transactions, the developer will need to follow these step - 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. 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. From bb6795d9f10a8f538f9fbc4f5df13d923088e949 Mon Sep 17 00:00:00 2001 From: Abhishek Date: Fri, 3 Mar 2023 22:08:21 +1300 Subject: [PATCH 09/13] Changes as requested --- README.md | 16 +++++++++++----- 1 file changed, 11 insertions(+), 5 deletions(-) diff --git a/README.md b/README.md index 9cf61d350..09f08eb9c 100644 --- a/README.md +++ b/README.md @@ -31,11 +31,11 @@ TODO TODO -## Operational Transactions +#### 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. +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 @@ -55,11 +55,13 @@ The reason behind choosing different salt is to avoid having the same transactio 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 + ### 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. +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. Finally, both addresses can renounce their own roles by calling the renounceRole() function. @@ -83,9 +85,13 @@ Only address with the Admin role can call the `removeSupportedTokens()` 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. -### FlushFund +### flushMultipleTokenFunds + +`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 -`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(address _tokenAddress)` is doing same as above function, however doing on token basis instead of from and to indexes. ### Change Flush Receive Address From e8f48d10a87d0f92e3112cb1b1ab8afede6e98a8 Mon Sep 17 00:00:00 2001 From: Abhishek Date: Mon, 6 Mar 2023 12:47:48 +1300 Subject: [PATCH 10/13] Updated with mainnet address --- README.md | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/README.md b/README.md index 09f08eb9c..f9f50b602 100644 --- a/README.md +++ b/README.md @@ -147,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) From 3ebe72f596390d9a9d015d47da594340a2214a57 Mon Sep 17 00:00:00 2001 From: Abhishek Date: Mon, 6 Mar 2023 20:27:18 +1300 Subject: [PATCH 11/13] Changes as requested --- README.md | 22 +++++----------------- 1 file changed, 5 insertions(+), 17 deletions(-) diff --git a/README.md b/README.md index f9f50b602..fd1e3a3ac 100644 --- a/README.md +++ b/README.md @@ -37,9 +37,9 @@ To change the state of any smart contract, users need to approve the smart contr 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 +### TimeLock Contract Operations -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. +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: @@ -51,17 +51,17 @@ To execute only Admin transactions, the developer will need to follow these step 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. +The reason behind choosing different salt is to avoid having he 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. -## Operational Transactions +## 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 this change will only take effect after three days. +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 changes will happen instantly once executed. Finally, both addresses can renounce their own roles by calling the renounceRole() function. @@ -195,18 +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 - -ETH and ERC20 tokens can be withdrawn by the address with WITHDRAW_ROLE only via the `withdraw(address _tokenAddress, uint256 amount)` function. - -## Admin address - Gnosis safe - -Admin address will be Gnosis safe, 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). - -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). From a593acdd6bf84a97e98f15b0a8b7c6901ebc88f5 Mon Sep 17 00:00:00 2001 From: Abhishek Date: Tue, 7 Mar 2023 19:10:39 +1300 Subject: [PATCH 12/13] Added minor changes --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index fd1e3a3ac..db6e31b42 100644 --- a/README.md +++ b/README.md @@ -37,7 +37,7 @@ To change the state of any smart contract, users need to approve the smart contr 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 +## 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. @@ -51,7 +51,7 @@ To execute only Admin transactions, the developer will need to follow these step Salt can be `0x0000000000000000000000000000000000000000000000000000000000000000` for 1st transaction, `0x0000000000000000000000000000000000000000000000000000000000000001` for 2nd transaction and so on. -The reason behind choosing different salt is to avoid having he same operation identifier again. +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. @@ -61,7 +61,7 @@ After scheduling the transaction using a timelock, the developer must call the e 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 changes will happen instantly once executed. +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. From bcdcd265cfcdda692cd4dad80fd6816e3a5aca1b Mon Sep 17 00:00:00 2001 From: Lee Wei Yuan <35588002+weiyuan95@users.noreply.github.com> Date: Tue, 7 Mar 2023 16:00:49 +0800 Subject: [PATCH 13/13] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index db6e31b42..d4cfcbcbe 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ TODO TODO -#### +## 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.