From 3ccbe6ae0f5a36efc84c007e8a05e2a6344aaa82 Mon Sep 17 00:00:00 2001 From: ororopickpocket Date: Thu, 20 May 2021 18:26:50 +0000 Subject: [PATCH 01/24] removed lending integration and added require --- .../contracts/RBTCWrapperProxy.sol | 45 +- .../contracts/interfaces/ILoanToken.sol | 28 -- .../contracts/mockups/LoanToken.sol | 94 ---- .../migrations/2_deploy_RBTCWrapperProxy.js | 7 +- rbtcwrapperproxy/test/testRBTCWrapperProxy.js | 454 ------------------ 5 files changed, 3 insertions(+), 625 deletions(-) delete mode 100644 rbtcwrapperproxy/contracts/interfaces/ILoanToken.sol delete mode 100644 rbtcwrapperproxy/contracts/mockups/LoanToken.sol diff --git a/rbtcwrapperproxy/contracts/RBTCWrapperProxy.sol b/rbtcwrapperproxy/contracts/RBTCWrapperProxy.sol index 83ce4bb..17ec75c 100644 --- a/rbtcwrapperproxy/contracts/RBTCWrapperProxy.sol +++ b/rbtcwrapperproxy/contracts/RBTCWrapperProxy.sol @@ -12,7 +12,6 @@ import "./interfaces/ISovrynSwapFormula.sol"; import "./interfaces/IContractRegistry.sol"; import "./ContractRegistryClient.sol"; import "./mockups/LiquidityMining.sol"; -import "./interfaces/ILoanToken.sol"; contract RBTCWrapperProxy is ContractRegistryClient { @@ -181,7 +180,7 @@ contract RBTCWrapperProxy is ContractRegistryClient { IWrbtcERC20(wrbtcTokenAddress).deposit.value(_amount)(); } else{ - reserveToken.transferFrom(msg.sender, address(this), _amount); + require(reserveToken.transferFrom(msg.sender, address(this), _amount)); } require(reserveToken.approve(_liquidityPoolConverterAddress, _amount), "token approval failed"); @@ -455,46 +454,4 @@ contract RBTCWrapperProxy is ContractRegistryClient { } } - /** - * @notice provides funds to a lending pool and deposits the pool tokens into the liquidity mining contract. - * @param loanTokenAddress the address of the loan token (aka lending pool) - * @param depositAmount he amount of underlying tokens to deposit - */ - function addToLendingPool(address loanTokenAddress, uint256 depositAmount) public{ - LoanToken loanToken = LoanToken(loanTokenAddress); - IERC20Token underlyingAsset = IERC20Token(loanToken.loanTokenAddress()); - - //retrieve the underlying asset from the user - require(underlyingAsset.transferFrom(msg.sender, address(this), depositAmount), "Failed to transfer tokens to the wrapper proxy"); - - //add the tokens to the lending pool - underlyingAsset.approve(loanTokenAddress, depositAmount); - uint256 minted = loanToken.mint(address(this), depositAmount); - - //deposit the pool tokens in the liquidity mining contract on the sender's behalf - loanToken.approve(address(liquidityMiningContract), minted); - liquidityMiningContract.deposit(loanTokenAddress, minted, msg.sender); - - emit LoanTokensMinted(msg.sender, minted, depositAmount); - } - - /** - * @notice removes funds from the liquidity mining contract, burns them on the lending pool and - * provides the underlying asset to the user - * @param loanTokenAddress the address of the loan token (aka lending pool) - * @param burnAmount the amount of pool tokens to withdraw from the lending pool and burn - */ - function removeFromLendingPool(address loanTokenAddress, uint256 burnAmount) public{ - LoanToken loanToken = LoanToken(loanTokenAddress); - - //withdraw always transfers the pool tokens to the caller and the reward tokens to the passed address - liquidityMiningContract.withdraw(loanTokenAddress, burnAmount, msg.sender); - - //burn pool token and directly send underlying tokens to the receiver - loanToken.approve(address(liquidityMiningContract), burnAmount); - uint256 redeemed = loanToken.burn(msg.sender, burnAmount); - - emit LoanTokensBurnt(msg.sender, burnAmount, redeemed); - } - } \ No newline at end of file diff --git a/rbtcwrapperproxy/contracts/interfaces/ILoanToken.sol b/rbtcwrapperproxy/contracts/interfaces/ILoanToken.sol deleted file mode 100644 index e1fbcff..0000000 --- a/rbtcwrapperproxy/contracts/interfaces/ILoanToken.sol +++ /dev/null @@ -1,28 +0,0 @@ -pragma solidity 0.5.16; - -import "./IERC20Token.sol"; - -/** -This is just a mockup for the Loan Token contract in the Sovryn-smart-contracts repository - */ -contract LoanToken is IERC20Token{ - address public loanTokenAddress; - - /** - * @notice lend to the pool - * @param _amount the amount of underlying tokens - * @param _user the address of user, tokens will be deposited to it or to msg.sender - */ - function mint(address _user, uint256 _amount) public returns (uint256 mintAmount){ - - } - - /** - * @notice burns pool tokens and transfers underlying tokens - * @param _user the address of the receiver - * @param _amount the amount of pool tokens - */ - function burn(address _user, uint256 _amount) public returns (uint256 redeemedAmount){ - - } -} \ No newline at end of file diff --git a/rbtcwrapperproxy/contracts/mockups/LoanToken.sol b/rbtcwrapperproxy/contracts/mockups/LoanToken.sol deleted file mode 100644 index 14bd3ea..0000000 --- a/rbtcwrapperproxy/contracts/mockups/LoanToken.sol +++ /dev/null @@ -1,94 +0,0 @@ -pragma solidity 0.5.16; - -import "../interfaces/IERC20Token.sol"; - -/** -This is just a mockup for the Loan Token contract in the Sovryn-smart-contracts repository - */ -contract LoanToken{ - address public loanTokenAddress; - - mapping( address => uint) public balanceOf; - mapping( address => mapping( address => uint)) public allowance; - - constructor(address loanToken) public{ - loanTokenAddress = loanToken; - } - /** - * @notice lend to the pool - * @param _amount the amount of underlying tokens - * @param _user the address of user, tokens will be deposited to it or to msg.sender - */ - function mint(address _user, uint256 _amount) public returns (uint256 mintAmount){ - IERC20Token(loanTokenAddress).transferFrom(address(msg.sender), address(this), _amount); - balanceOf[_user] += _amount; - return _amount; - } - - /** - * @notice burns pool tokens and transfers underlying tokens - * @param _receiver the address of the receiver - * @param _amount the amount of pool tokens - */ - function burn(address _receiver, uint256 _amount) public returns (uint256 redeemedAmount){ - require(balanceOf[msg.sender] >= _amount, "insufficient balance"); - balanceOf[msg.sender] -= _amount; - IERC20Token(loanTokenAddress).transfer(address(_receiver), _amount); - return _amount; - } - - /** - * @dev allows another account/contract to transfers tokens on behalf of the caller - * throws on any error rather then return a false flag to minimize user errors - * - * also, to minimize the risk of the approve/transferFrom attack vector - * (see https://docs.google.com/document/d/1YLPtQxZu1UAvO9cZ1O2RPXBbT0mooh4DYKjA_jp-RLM/), approve has to be called twice - * in 2 separate transactions - once to change the allowance to 0 and secondly to change it to the new allowance value - * - * @param _spender approved address - * @param _value allowance amount - * - * @return true if the approval was successful, false if it wasn't - */ - function approve(address _spender, uint256 _value) public returns (bool success) { - allowance[msg.sender][_spender] = _value; - return true; - } - - /** - * @dev transfers tokens to a given address on behalf of another address - * throws on any error rather then return a false flag to minimize user errors - * - * @param _from source address - * @param _to target address - * @param _value transfer amount - * - * @return true if the transfer was successful, false if it wasn't - */ - function transferFrom( - address _from, - address _to, - uint256 _value - ) public returns (bool success) { - require(allowance[_from][msg.sender] >= _value); - allowance[_from][msg.sender] = allowance[_from][msg.sender] - _value; - balanceOf[_from] = balanceOf[_from] - _value; - balanceOf[_to] = balanceOf[_to] + _value; - return true; - } - - /** - * @dev transfers tokens to a given address - * throws on any error rather then return a false flag to minimize user errors - * - * @param _to target address - * @param _value transfer amount - * - * @return true if the transfer was successful, false if it wasn't - */ - function transfer(address _to, uint256 _value) public returns (bool success) { - balanceOf[msg.sender] = balanceOf[msg.sender] - _value; - balanceOf[_to] = balanceOf[_to] + _value; - return true; - } -} \ No newline at end of file diff --git a/rbtcwrapperproxy/migrations/2_deploy_RBTCWrapperProxy.js b/rbtcwrapperproxy/migrations/2_deploy_RBTCWrapperProxy.js index 340c0c7..3cb0116 100644 --- a/rbtcwrapperproxy/migrations/2_deploy_RBTCWrapperProxy.js +++ b/rbtcwrapperproxy/migrations/2_deploy_RBTCWrapperProxy.js @@ -2,7 +2,6 @@ const fs = require("fs"); const RBTCWrapperProxy = artifacts.require("RBTCWrapperProxy"); const LiquidityMining = artifacts.require("LiquidityMining"); -const LoanToken = artifacts.require("LoanToken"); const getConfig = () => { return JSON.parse(fs.readFileSync("../solidity/utils/config_rsk.json", { encoding: "utf8" })); @@ -14,10 +13,8 @@ const getSOVConfig = () => { module.exports = function (deployer, network) { if(network == "development"){ console.log(getConfig()["SUSD"].addr) - return deployer.deploy(LoanToken, getConfig()["SUSD"].addr).then(function() { - return deployer.deploy(LiquidityMining, getSOVConfig()["SOV"].addr).then(function() { - return deployer.deploy(RBTCWrapperProxy, getConfig()["RBTC"].addr, getConfig()["sovrynSwapNetwork"].addr, getConfig()["contractRegistry"].addr, LiquidityMining.address); - }); + return deployer.deploy(LiquidityMining, getSOVConfig()["SOV"].addr).then(function() { + return deployer.deploy(RBTCWrapperProxy, getConfig()["RBTC"].addr, getConfig()["sovrynSwapNetwork"].addr, getConfig()["contractRegistry"].addr, LiquidityMining.address); }); } diff --git a/rbtcwrapperproxy/test/testRBTCWrapperProxy.js b/rbtcwrapperproxy/test/testRBTCWrapperProxy.js index 631d148..81ed0b5 100644 --- a/rbtcwrapperproxy/test/testRBTCWrapperProxy.js +++ b/rbtcwrapperproxy/test/testRBTCWrapperProxy.js @@ -50,7 +50,6 @@ contract("RBTCWrapperProxy", async (accounts) => { usdToken = await IERC20Token.at(usdTokenAddress); sovrynSwapNetwork = await ISovrynSwapNetwork.at(sovrynSwapNetworkAddress); liquidityMining = await LiquidityMining.deployed(); - usdLoanToken = await LoanToken.deployed(); await sovToken.transfer(liquidityMining.address, web3.utils.toWei("100","Ether")); }); @@ -400,457 +399,4 @@ contract("RBTCWrapperProxy", async (accounts) => { ); }); - it("should add to the lending pool and provide the pool tokens to the LM contract", async() => { - const amount = web3.utils.toBN(10e18); - const usdBefore = await usdToken.balanceOf(accounts[0]); - await usdToken.approve(rbtcWrapperProxy.address, amount); - await rbtcWrapperProxy.addToLendingPool(usdLoanToken.address, amount); - const usdAfter = await usdToken.balanceOf(accounts[0]); - assert.equal(amount.add(usdAfter).toString(), usdBefore.toString(), "incorrect account token balance"); - assert.equal(amount.toString(), (await usdToken.balanceOf(usdLoanToken.address)).toString(), "incorrect underlying balance on loan token"); - assert.equal(amount.toString(), (await usdLoanToken.balanceOf(liquidityMining.address)).toString(), "incorrect pool token balance on LM contract"); - }); - - require("@openzeppelin/test-helpers/configure")({ - provider: web3.currentProvider, - singletons: { - abstraction: "truffle", - }, -}); -const fs = require("fs"); - -const assert = require("chai").assert; -const { expectRevert, expectEvent, BN } = require("@openzeppelin/test-helpers"); - -const RBTCWrapperProxy = artifacts.require("../RBTCWrapperProxy.sol"); -const IERC20Token = artifacts.require("../interfaces/IERC20Token.sol"); -const ISmartToken = artifacts.require("../interfaces/ISmartToken.sol"); -const ISovrynSwapNetwork = artifacts.require("../interfaces/ISovrynSwapNetwork.sol"); -const ILiquidityPoolV1Converter = artifacts.require("../interfaces/ILiquidityPoolV1Converter.sol"); -const ILiquidityPoolV2Converter = artifacts.require("../interfaces/ILiquidityPoolV2Converter.sol"); -const LiquidityMining = artifacts.require("../mockups/LiquidityMining.sol"); -const LoanToken = artifacts.require("../mockups/LoanToken.sol"); - -const getConfig = () => { - return JSON.parse(fs.readFileSync("../solidity/utils/config_rsk.json", { encoding: "utf8" })); -}; - -const getConfigFromSOV = () => { - return JSON.parse(fs.readFileSync("../solidity/utils/addSOV.json", { encoding: "utf8" })); -}; - -const liquidityPoolV1ConverterAddress = getConfigFromSOV()["newLiquidityPoolV1Converter"].addr; -const liquidityPoolV2ConverterAddress = getConfig()["newLiquidityPoolV2Converter"].addr; -const sovrynSwapNetworkAddress = getConfig()["sovrynSwapNetwork"].addr; -const wrbtcAddress = getConfig()["RBTC"].addr; -const sovTokenAddress = getConfigFromSOV()["SOV"].addr; -const usdTokenAddress = getConfig()["SUSD"].addr; - -contract("RBTCWrapperProxy", async (accounts) => { - let rbtcWrapperProxy, liquidityPoolV1Converter, liquidityPoolV2Converter, poolTokenV1Address, wrbtcPoolTokenV2Address, poolTokenV1, wrbtcPoolTokenV2, sovToken, usdToken, sovrynSwapNetwork; - - before(async () => { - rbtcWrapperProxy = await RBTCWrapperProxy.deployed(); - liquidityPoolV1Converter = await ILiquidityPoolV1Converter.at(liquidityPoolV1ConverterAddress); - liquidityPoolV2Converter = await ILiquidityPoolV2Converter.at(liquidityPoolV2ConverterAddress); - poolTokenV1Address = await liquidityPoolV1Converter.token(); - poolTokenV1 = await ISmartToken.at(poolTokenV1Address); - wrbtcPoolTokenV2Address = await liquidityPoolV2Converter.poolToken(wrbtcAddress); - wrbtcPoolTokenV2 = await ISmartToken.at(wrbtcPoolTokenV2Address); - usdPoolTokenV2Address = await liquidityPoolV2Converter.poolToken(usdTokenAddress); - usdPoolTokenV2 = await ISmartToken.at(usdPoolTokenV2Address); - sovToken = await IERC20Token.at(sovTokenAddress); - usdToken = await IERC20Token.at(usdTokenAddress); - sovrynSwapNetwork = await ISovrynSwapNetwork.at(sovrynSwapNetworkAddress); - liquidityMining = await LiquidityMining.deployed(); - usdLoanToken = await LoanToken.deployed(); - await sovToken.transfer(liquidityMining.address, web3.utils.toWei("100","Ether")); - }); - - it("verifies that users could send RBTC and SOV, and then add liquidity to get pool token 1", async () => { - var sovAmountBefore = await sovToken.balanceOf(accounts[0]); - var poolTokenV1AmountBefore = await poolTokenV1.balanceOf(accounts[0]); - - var rbtcAmount = web3.utils.toBN(getConfigFromSOV()["converters"][0]["reserves"][0]["balance"] * 1e14); - var sovAmount = web3.utils.toBN(getConfigFromSOV()["converters"][0]["reserves"][1]["balance"] * 1e14); - - await sovToken.approve(RBTCWrapperProxy.address, web3.utils.toBN(sovAmount * 4), { from: accounts[0] }); - - var result = await rbtcWrapperProxy.addLiquidityToV1( - liquidityPoolV1ConverterAddress, - [wrbtcAddress,sovTokenAddress], - [rbtcAmount, sovAmount], - 1, - { - from: accounts[0], - to: RBTCWrapperProxy.address, - value: rbtcAmount - }); - - var addedPoolTokenV1Amount = new BN(result.logs[0].args._poolTokenAmount); - - var expectedBalance = new BN(sovAmountBefore.toString()).sub(sovAmount) - assert.equal( - await sovToken.balanceOf(accounts[0]), - expectedBalance.toString(), - "Wrong SOV balance" - ); - - assert.equal( - (await liquidityMining.userLPBalance(accounts[0], poolTokenV1Address)).toString(), - addedPoolTokenV1Amount.toString(), - "Wrong pool token balance on LM contract" - ); - - await expectEvent(result.receipt, "LiquidityAddedToV1", { - _provider: accounts[0], - _reserveTokens: [wrbtcAddress, sovTokenAddress], - _reserveAmounts: [rbtcAmount, sovAmount], - _poolTokenAmount: addedPoolTokenV1Amount, - }); - - var sovAmountAfter = await sovToken.balanceOf(accounts[0]); - - // Send 2x SOV, User should get 1x SOV back - var result = await rbtcWrapperProxy.addLiquidityToV1( - liquidityPoolV1ConverterAddress, - [wrbtcAddress,sovTokenAddress], - [rbtcAmount, web3.utils.toBN(sovAmount * 2)], - 1, - { - from: accounts[0], - to: RBTCWrapperProxy.address, - value: rbtcAmount - }); - - addedPoolTokenV1Amount = addedPoolTokenV1Amount.add(new BN(result.logs[0].args._poolTokenAmount)); - expectedBalance = new BN(sovAmountAfter.toString()).sub(sovAmount); - - assert.equal( - await sovToken.balanceOf(accounts[0]), - expectedBalance.toString(), - "Wrong SOV balance" - ); - - assert.equal( - (await liquidityMining.userLPBalance(accounts[0], poolTokenV1Address)).toString(), - addedPoolTokenV1Amount.toString(), - "Wrong pool token balance on LM contract" - ); - - await expectEvent(result.receipt, "LiquidityAddedToV1", { - _provider: accounts[0], - _reserveTokens: [wrbtcAddress, sovTokenAddress], - _reserveAmounts: [rbtcAmount, web3.utils.toBN(sovAmount * 2)] - }); - }); - - it("verifies that users could remove liquidity to burn pool token 1 and then get RBTC and SOV", async () => { - poolTokenBalance = await liquidityMining.userLPBalance(accounts[0], poolTokenV1Address); - assert(poolTokenBalance > 0, "incorrect test setup"); - - rbtcAmountBefore = await web3.eth.getBalance(accounts[0]); - sovAmountBefore = await sovToken.balanceOf(accounts[0]); - - var result = await rbtcWrapperProxy.removeLiquidityFromV1(liquidityPoolV1ConverterAddress, poolTokenBalance, [wrbtcAddress, sovTokenAddress], [1, 1]); - - var gasCost = new BN(result.receipt.gasUsed).mul( new BN((await web3.eth.getGasPrice()).toString())); - var addedRBTCAmount = result.logs[0].args._reserveAmounts[0]; - var addedSOVAmount = result.logs[0].args._reserveAmounts[1]; - - await expectEvent(result.receipt, "LiquidityRemovedFromV1", { - _provider: accounts[0], - _reserveTokens: [wrbtcAddress, sovTokenAddress], - _reserveAmounts: [addedRBTCAmount, addedSOVAmount] - }); - - expectedBalance = new BN(rbtcAmountBefore).add(new BN(addedRBTCAmount)).sub(gasCost); - assert.equal( - await web3.eth.getBalance(accounts[0]), - expectedBalance.toString(), - "Wrong RBTC balance" - ); - - //adding the pool token balance because of the reward being paid out - expectedBalance = new BN(sovAmountBefore).add(addedSOVAmount).add(poolTokenBalance); - assert.equal( - (await sovToken.balanceOf(accounts[0])).toString(), - expectedBalance.toString(), - "Wrong SOV balance" - ); - }); - - it("verifies that users could send RBTC and then add liquidity to get pool token 2", async () => { - var rbtcAmountBefore = await web3.eth.getBalance(accounts[0]); - var wrbtcPoolTokenV2AmountBefore = await wrbtcPoolTokenV2.balanceOf(accounts[0]); - - var result = await rbtcWrapperProxy.addLiquidityToV2(liquidityPoolV2ConverterAddress, wrbtcAddress, web3.utils.toBN(1e16), 1, { - from: accounts[0], - to: RBTCWrapperProxy.address, - value: 1e16, - }); - - var gasCost = new BN(result.receipt.gasUsed).mul( new BN((await web3.eth.getGasPrice()).toString())); - var addedWrbtcPoolTokenV2Amount = new BN(result.logs[0].args._poolTokenAmount); - var expectedBalance = new BN(rbtcAmountBefore.toString()).sub(gasCost).sub(new BN((10**16).toString())); - - assert.equal(await web3.eth.getBalance(accounts[0]), expectedBalance, "Wrong RBTC balance"); - - assert.equal( - (await liquidityMining.userLPBalance(accounts[0], wrbtcPoolTokenV2Address)).toString(), - addedWrbtcPoolTokenV2Amount.toString(), - "Wrong pool token balance on LM contract" - ); - await expectEvent(result.receipt, "LiquidityAdded", { - _provider: accounts[0], - _reserveAmount: web3.utils.toBN(1e16), - _poolTokenAmount: addedWrbtcPoolTokenV2Amount, - }); - }); - - it("verifies that users could add USD liquidity to the v2 pool", async () => { - var usdAmountBefore = await usdToken.balanceOf(accounts[0]); - - await usdToken.approve(RBTCWrapperProxy.address, web3.utils.toBN(1e16), { from: accounts[0] }); - - var result = await rbtcWrapperProxy.addLiquidityToV2(liquidityPoolV2ConverterAddress, usdTokenAddress, web3.utils.toBN(1e16), 1); - - var addedUsdPoolTokenV2Amount = new BN(result.logs[0].args._poolTokenAmount); - var expectedBalance = usdAmountBefore.sub(new BN((10**16).toString())); - - assert.equal((await usdToken.balanceOf(accounts[0])).toString(), expectedBalance.toString(), "Wrong USD balance"); - - assert.equal( - (await liquidityMining.userLPBalance(accounts[0], usdPoolTokenV2Address)).toString(), - addedUsdPoolTokenV2Amount.toString(), - "Wrong pool token balance" - ); - await expectEvent(result.receipt, "LiquidityAdded", { - _provider: accounts[0], - _reserveAmount: web3.utils.toBN(1e16), - _poolTokenAmount: addedUsdPoolTokenV2Amount, - }); - }); - - it("verifies that users could remove liquidity to burn pool token 2 and then get RBTC", async () => { - poolTokenBalance = await liquidityMining.userLPBalance(accounts[0], wrbtcPoolTokenV2Address); - assert(poolTokenBalance > 0, "incorrect test setup"); - - var sovAmountBefore = await sovToken.balanceOf(accounts[0]); - - var rbtcAmountBefore = await web3.eth.getBalance(accounts[0]); - var result = await rbtcWrapperProxy.removeLiquidityFromV2(liquidityPoolV2ConverterAddress, wrbtcAddress, poolTokenBalance, 1, { - from: accounts[0], - to: RBTCWrapperProxy.address, - }); - - var gasCost = new BN(result.receipt.gasUsed).mul( new BN((await web3.eth.getGasPrice()).toString())); - var addedRBTCAmount = web3.utils.BN(result.logs[0].args._reserveAmount); - var expectedBalance = new BN(rbtcAmountBefore).add(addedRBTCAmount).sub(gasCost); - - assert.equal( - await web3.eth.getBalance(accounts[0]), - expectedBalance.toString(), - "Wrong RBTC balance" - ); - - //checking if the LM reward being paid out - expectedBalance = new BN(sovAmountBefore).add(poolTokenBalance); - assert.equal( - (await sovToken.balanceOf(accounts[0])).toString(), - expectedBalance.toString(), - "Wrong SOV balance" - ); - - await expectEvent(result.receipt, "LiquidityRemoved", { - _provider: accounts[0], - _reserveAmount: addedRBTCAmount, - _poolTokenAmount: poolTokenBalance, - }); - }); - - it("verifies that users could remove liquidity to burn pool token 2 and then get RBTC", async () => { - poolTokenBalance = await liquidityMining.userLPBalance(accounts[0], usdPoolTokenV2Address); - assert(poolTokenBalance > 0, "incorrect test setup"); - - var sovAmountBefore = await sovToken.balanceOf(accounts[0]); - - var usdAmountBefore = await usdToken.balanceOf(accounts[0]); - var result = await rbtcWrapperProxy.removeLiquidityFromV2(liquidityPoolV2ConverterAddress, usdTokenAddress, poolTokenBalance, 1, { - from: accounts[0], - to: RBTCWrapperProxy.address, - }); - - var addedUSDAmount = web3.utils.BN(result.logs[0].args._reserveAmount); - var expectedBalance = usdAmountBefore.add(addedUSDAmount); - - assert.equal( - await usdToken.balanceOf(accounts[0]), - expectedBalance.toString(), - "Wrong USD balance" - ); - - //checking if the LM reward being paid out - expectedBalance = new BN(sovAmountBefore).add(poolTokenBalance); - assert.equal( - (await sovToken.balanceOf(accounts[0])).toString(), - expectedBalance.toString(), - "Wrong SOV balance" - ); - - await expectEvent(result.receipt, "LiquidityRemoved", { - _provider: accounts[0], - _reserveAmount: addedUSDAmount, - _poolTokenAmount: poolTokenBalance, - }); - }); - - it("verifies that users could send RBTC and then swap it to DoC", async () => { - var rbtcAmountBefore = await web3.eth.getBalance(accounts[0]); - var usdTokenAmountBefore = await usdToken.balanceOf(accounts[0]); - - var pathWRBTCToDoC = await sovrynSwapNetwork.conversionPath(wrbtcAddress, usdTokenAddress); - var result = await rbtcWrapperProxy.convertByPath(pathWRBTCToDoC, web3.utils.toBN(1e16), 1, { - from: accounts[0], - to: RBTCWrapperProxy.address, - value: 1e16 - }); - - var gasCost = new BN(result.receipt.gasUsed).mul(new BN((await web3.eth.getGasPrice()).toString())); - var addedDoCTokenAmount = web3.utils.BN(result.logs[0].args._targetTokenAmount); - var expectedBalance = new BN(rbtcAmountBefore).sub(gasCost).sub(new BN((10**16).toString())); - assert.equal(await web3.eth.getBalance(accounts[0]), expectedBalance.toString(), "Wrong RBTC balance"); - expectedBalance = new BN(usdTokenAmountBefore).add(addedDoCTokenAmount); - assert.equal( - await usdToken.balanceOf(accounts[0]), - expectedBalance.toString(), - "Wrong DoC token balance" - ); - await expectEvent(result.receipt, "TokenConverted", { - _beneficiary: accounts[0], - _sourceTokenAmount: web3.utils.toBN(1e16), - _targetTokenAmount: addedDoCTokenAmount, - _path: pathWRBTCToDoC, - }); - }); - - it("verifies that users could send DoC and then swap it to RBTC", async () => { - var rbtcAmountBefore = await web3.eth.getBalance(accounts[0]); - var usdTokenAmountBefore = await usdToken.balanceOf(accounts[0]); - - await usdToken.approve(RBTCWrapperProxy.address, web3.utils.toBN(1e20), { from: accounts[0] }); - - var pathDoCToWRBTC = await sovrynSwapNetwork.conversionPath(usdTokenAddress, wrbtcAddress); - var rbtcAmountBefore = await web3.eth.getBalance(accounts[0]); - - var result = await rbtcWrapperProxy.convertByPath(pathDoCToWRBTC, web3.utils.toBN(1e20), 1, { - from: accounts[0], - to: RBTCWrapperProxy.address, - }); - - var gasCost = new BN(result.receipt.gasUsed).mul( new BN((await web3.eth.getGasPrice()).toString()));; - var addedRBTCAmount = new BN(result.logs[0].args._targetTokenAmount); - var expectedBalance = new BN(rbtcAmountBefore).add(addedRBTCAmount).sub(gasCost); - assert.equal( - await web3.eth.getBalance(accounts[0]), - expectedBalance.toString(), - "Wrong RBTC balance" - ); - - expectedBalance = new BN(usdTokenAmountBefore).sub(web3.utils.toBN(1e20)); - assert.equal( - web3.utils.BN(await usdToken.balanceOf(accounts[0])).toString(), - expectedBalance.toString(), - "Wrong DoC token balance" - ); - await expectEvent(result.receipt, "TokenConverted", { - _beneficiary: accounts[0], - _sourceTokenAmount: web3.utils.toBN(1e20), - _targetTokenAmount: addedRBTCAmount, - _path: pathDoCToWRBTC, - }); - }); - - it("should revert when sending rBTC to this smart contract from user directly", async () => { - await expectRevert.unspecified(rbtcWrapperProxy.send(web3.utils.toBN(1e16))); - }); - - it("should revert when calling the addLIquidity() without sending RBTC", async () => { - await expectRevert.unspecified( - rbtcWrapperProxy.addLiquidityToV2(liquidityPoolV2ConverterAddress, wrbtcAddress, web3.utils.toBN(1e16), 1, { - from: accounts[0], - to: RBTCWrapperProxy.address, - }), - "No RBTC" - ); - }); - - it("should revert when amount param not identical to msg.value to call addLiquidityToV2()", async () => { - await expectRevert.unspecified( - rbtcWrapperProxy.addLiquidityToV2(liquidityPoolV2ConverterAddress, wrbtcAddress, web3.utils.toBN(1e16), 1, { - from: accounts[0], - to: RBTCWrapperProxy.address, - value: 1e8, - }), - "The provided amount not identical to msg.value" - ); - }); - - it("should revert when passing wrong path param to convertByPath()", async () => { - var pathWRBTCToDoC = await sovrynSwapNetwork.conversionPath(wrbtcAddress, usdTokenAddress); - var pathDoCToWRBTC = await sovrynSwapNetwork.conversionPath(usdTokenAddress, wrbtcAddress); - await expectRevert.unspecified( - rbtcWrapperProxy.convertByPath(pathDoCToWRBTC, web3.utils.toBN(1e16), 1, { - from: accounts[0], - to: RBTCWrapperProxy.address, - value: 1e16, - }), - "Wrong path param" - ); - await expectRevert.unspecified( - rbtcWrapperProxy.convertByPath(pathWRBTCToDoC, web3.utils.toBN(1e20), 1, { from: accounts[0], to: RBTCWrapperProxy.address }), - "Wrong path param" - ); - }); - - it("should add to the lending pool and provide the pool tokens to the LM contract", async() => { - const amount = web3.utils.toBN(10e18); - const usdBefore = await usdToken.balanceOf(accounts[0]); - await usdToken.approve(rbtcWrapperProxy.address, amount); - const result = await rbtcWrapperProxy.addToLendingPool(usdLoanToken.address, amount); - const usdAfter = await usdToken.balanceOf(accounts[0]); - assert.equal(amount.add(usdAfter).toString(), usdBefore.toString(), "incorrect account token balance"); - assert.equal(amount.toString(), (await usdToken.balanceOf(usdLoanToken.address)).toString(), "incorrect underlying balance on loan token"); - assert.equal(amount.toString(), (await usdLoanToken.balanceOf(liquidityMining.address)).toString(), "incorrect pool token balance on LM contract"); - - expectEvent(result.receipt, "LoanTokensMinted", { - user: accounts[0], - poolTokenAmount: amount, - assetAmount: amount - }); - }); - - it("should withdraw from the lending pool and withdraw the rewrads from the LM contract", async() => { - const amount = await liquidityMining.userLPBalance(accounts[0], usdLoanToken.address); - assert(amount > 0, "incorrect test setup. account needs to have a balance on the LM contract"); - - const usdBefore = await usdToken.balanceOf(accounts[0]); - const sovBefore = await sovToken.balanceOf(accounts[0]); - const result = await rbtcWrapperProxy.removeFromLendingPool(usdLoanToken.address, amount); - - assert.equal(amount.add(usdBefore).toString(), (await usdToken.balanceOf(accounts[0])).toString(), "incorrect account token balance"); - assert.equal(amount.add(sovBefore).toString(), (await sovToken.balanceOf(accounts[0])).toString(), "incorrect account token balance"); - - expectEvent(result.receipt, "LoanTokensBurnt", { - user: accounts[0], - poolTokenAmount: amount, - assetAmount: amount - }); - }); - - -}); - - - }); From 0665b23213c765f939c152cc633da01093d1ddf7 Mon Sep 17 00:00:00 2001 From: ororopickpocket Date: Thu, 27 May 2021 10:36:23 +0000 Subject: [PATCH 02/24] updates wrapper proxy migration script --- .../migrations/2_deploy_RBTCWrapperProxy.js | 18 +++++++++++++----- 1 file changed, 13 insertions(+), 5 deletions(-) diff --git a/rbtcwrapperproxy/migrations/2_deploy_RBTCWrapperProxy.js b/rbtcwrapperproxy/migrations/2_deploy_RBTCWrapperProxy.js index 3cb0116..40a7027 100644 --- a/rbtcwrapperproxy/migrations/2_deploy_RBTCWrapperProxy.js +++ b/rbtcwrapperproxy/migrations/2_deploy_RBTCWrapperProxy.js @@ -18,13 +18,21 @@ module.exports = function (deployer, network) { }); } - else{ - liquidityMiningAddress = '0xe28aEbA913c34EC8F10DF0D9C92D2Aa27545870e'; - wrbtcAddress = '0x69FE5cEC81D5eF92600c1A0dB1F11986AB3758Ab'; - swapNetworkAddress = '0x61172B53423E205a399640e5283e51FE60EC2256'; - contractRegistry = '0x0E7CcF6A67e614B507Aa524572F72C7e5Dec23CB'; + else{//mainnet + liquidityMiningAddress = '0xf730af26e87D9F55E46A6C447ED2235C385E55e0'; + wrbtcAddress = '0x542fDA317318eBF1d3DEAf76E0b632741A7e677d'; + swapNetworkAddress = '0x98aCE08D2b759a265ae326F010496bcD63C15afc'; + contractRegistry = '0x46EBC03EF2277308BdB106a73d11c65109C4B89B'; return deployer.deploy(RBTCWrapperProxy, wrbtcAddress, swapNetworkAddress, contractRegistry, liquidityMiningAddress); } + //testnet + /** + liquidityMiningAddress = '0xe28aEbA913c34EC8F10DF0D9C92D2Aa27545870e'; + wrbtcAddress = '0x69FE5cEC81D5eF92600c1A0dB1F11986AB3758Ab'; + swapNetworkAddress = '0x61172B53423E205a399640e5283e51FE60EC2256'; + contractRegistry = '0x0E7CcF6A67e614B507Aa524572F72C7e5Dec23CB'; + */ + }; From a0d29041eed5e6d99fc3b3e2c29ce632490f6a3c Mon Sep 17 00:00:00 2001 From: ororopickpocket Date: Fri, 27 Aug 2021 07:33:33 +0000 Subject: [PATCH 03/24] prepared addConverter script to also deploy oracle. --- solidity/utils/addConverter.js | 12 ++++- solidity/utils/addFish_testnet.json | 36 +++++++++++++ solidity/utils/upgrade_config.json | 81 ++++++++++++----------------- 3 files changed, 79 insertions(+), 50 deletions(-) create mode 100644 solidity/utils/addFish_testnet.json diff --git a/solidity/utils/addConverter.js b/solidity/utils/addConverter.js index 5ec4f05..6e76fd8 100644 --- a/solidity/utils/addConverter.js +++ b/solidity/utils/addConverter.js @@ -232,7 +232,7 @@ const addConverter = async (tokenOracleName, oracleMockName, oracleMockValue, or await execute(converterRegistry.methods.newConverter(type, name, symbol, decimals, "1000000", tokens, weights)); await execute(converterRegistry.methods.setupConverter(type, tokens, weights, newConverter)); - const oracle = await web3Func(deploy, "oracle", "Oracle", [newConverter]); + console.log("New Converter is ", newConverter); setConfig({ [`newLiquidityPoolV${type}Converter`]: { name: `LiquidityPoolV${type}Converter`, addr: newConverter, args: "" } }); @@ -252,9 +252,19 @@ const addConverter = async (tokenOracleName, oracleMockName, oracleMockValue, or console.log("Done with conversion fee"); if (type === 1) { + console.log("Deploying Oracle"); + const oracle = await web3Func(deploy, "Oracle", "Oracle", [converterBase._address, getConfig().btcAddress]); + + console.log("Setting k", getConfig().k); + await execute(oracle.methods.setK(getConfig().k)); + + console.log("Setting oracle in converter", oracle._address); const liquidityV1PoolConverter = deployed(web3, "LiquidityPoolV1Converter", converterBase._address); await execute(liquidityV1PoolConverter.methods.setOracle(oracle._address)); console.log("Done with adding oracle"); + + console.log("Updating oracle ownership"); + await execute(oracle.methods.transferOwnership(multiSigWallet._address)); } //adding the liquidity and thereby seeting the price diff --git a/solidity/utils/addFish_testnet.json b/solidity/utils/addFish_testnet.json new file mode 100644 index 0000000..a16feac --- /dev/null +++ b/solidity/utils/addFish_testnet.json @@ -0,0 +1,36 @@ +{ + "reserves": [ + { + "symbol": "(WR)BTC", + "decimals": 18, + "address": "0x69FE5cEC81D5eF92600c1A0dB1F11986AB3758Ab" + }, + { + "symbol": "FISH", + "decimals": 18, + "address": "" + } + ], + "converters": [ + { + "type": 1, + "symbol": "(WR)BTC/FISH", + "decimals": 18, + "fee": "0.3%", + "reserves": [ + { + "symbol": "(WR)BTC", + "weight": "50%", + "balance": "0" + }, + { + "symbol": "FISH", + "weight": "50%", + "balance": "0" + } + ] + } + ], + "k": 6779, + "btcAddress": "0x69FE5cEC81D5eF92600c1A0dB1F11986AB3758Ab" +} \ No newline at end of file diff --git a/solidity/utils/upgrade_config.json b/solidity/utils/upgrade_config.json index 015deef..20ec4fe 100644 --- a/solidity/utils/upgrade_config.json +++ b/solidity/utils/upgrade_config.json @@ -1,62 +1,45 @@ { "privateKey": "0x", - "nodeURL": "http://127.0.0.1:8545/", + "nodeURL": "https://mainnet.sovryn.app/rpc", "type": 1, - "reserves": [ - { - "symbol": "RBTC", - "decimals": 18, - "addr": "" - }, - { - "symbol": "SUSD", - "decimals": 18, - "addr": "" - } - ], - "converters": [ - { - "type": 1, - "symbol": "", - "decimals": 18, - "fee": "0.1%", - "reserves": [ - { - "symbol": "RBTC", - "weight": "50%", - "balance": "10" - }, - { - "symbol": "SUSD", - "weight": "50%", - "balance": "10" - } - ] - } - ], + "btcAddress": "0x542fDA317318eBF1d3DEAf76E0b632741A7e677d", + "k": 6779, + "block": 3550895, "converterFactory": { - "name": "ConverterFactory", - "addr": "", - "args": "" + "name": "ConverterFactory", + "addr": "0xcF46f24423B8da97E2c06B41df28163D55e80935", + "args": "" }, "converterUpgrader": { - "name": "ConverterUpgrader", - "addr": "", - "args": "" + "name": "ConverterUpgrader", + "addr": "0x40346f7Ce14B3a10bAB22F6a0A444902CF0Bc598", + "args": "" }, "converterRegistry": { - "name": "ConverterRegistry", - "addr": "", - "args": "" + "name": "ConverterRegistry", + "addr": "0x31A0F8400c75d52FdB413372233F28E3bdFB1c06", + "args": "" + }, + "multiSigWallet": { + "name": "MultiSigWallet", + "addr": "0x924f5ad34698Fd20c90Fe5D5A8A0abd3b42dc711", + "args": "" }, "converterContract": { - "name": "LiquidityPoolV1Converter", - "addr": "", - "args": "" + "name": "LiquidityPoolV1Converter", + "addr": [ + "0x9996E5F902d2d804E9eD0DdB1B628D1EBf6Bb6fE" + ], + "args": "" }, - "multiSigWallet": { - "name": "MultiSigWallet", - "addr": "", - "args": "" + "liquidityPoolV1ConverterFactory": { + "name": "LiquidityPoolV1ConverterFactory", + "addr": "0x1E7428B34Af8FA6Dc40d7A38769efA948E065669", + "args": "" + }, + "Oracle0": { + "name": "Oracle", + "addr": "0x345f2eC520431db542e33eD31a8f687E8eC705BB", + "args": "00000000000000000000000034031d1cd14e2c80b0268b47eff49643375afaeb000000000000000000000000542fda317318ebf1d3deaf76e0b632741a7e677d" } } \ No newline at end of file From 4c7e6acfe05c85c83b3727b974000d2eada3ed6a Mon Sep 17 00:00:00 2001 From: ororopickpocket Date: Fri, 27 Aug 2021 07:37:08 +0000 Subject: [PATCH 04/24] prepared mainnet fish config --- solidity/utils/addFish_mainnet.json | 36 +++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 solidity/utils/addFish_mainnet.json diff --git a/solidity/utils/addFish_mainnet.json b/solidity/utils/addFish_mainnet.json new file mode 100644 index 0000000..a8a1ee5 --- /dev/null +++ b/solidity/utils/addFish_mainnet.json @@ -0,0 +1,36 @@ +{ + "reserves": [ + { + "symbol": "(WR)BTC", + "decimals": 18, + "address": "0x542fDA317318eBF1d3DEAf76E0b632741A7e677d" + }, + { + "symbol": "FISH", + "decimals": 18, + "address": "" + } + ], + "converters": [ + { + "type": 1, + "symbol": "(WR)BTC/FISH", + "decimals": 18, + "fee": "0.3%", + "reserves": [ + { + "symbol": "(WR)BTC", + "weight": "50%", + "balance": "0" + }, + { + "symbol": "FISH", + "weight": "50%", + "balance": "0" + } + ] + } + ], + "k": 6779, + "btcAddress": "0x542fDA317318eBF1d3DEAf76E0b632741A7e677d" +} \ No newline at end of file From 4768f0a499630f19d153b79f89c532b5bbcd5bff Mon Sep 17 00:00:00 2001 From: Tyrone Johnson Date: Fri, 27 Aug 2021 11:31:08 +0300 Subject: [PATCH 05/24] upd/.gitignore *.code-workspace --- .gitignore | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.gitignore b/.gitignore index 0e3640e..93aaa5b 100644 --- a/.gitignore +++ b/.gitignore @@ -32,6 +32,6 @@ solidity/build/Test* /rbtcwrapperproxy/private-key /rbtcwrapperproxy/build -workspace.code-workspace +*.code-workspace .env yarn.lock From ceb95b005bf2f84b828a2731a88a15fe9407dc9b Mon Sep 17 00:00:00 2001 From: Tyrone Johnson Date: Fri, 27 Aug 2021 13:50:12 +0300 Subject: [PATCH 06/24] fix/addConverter.js & upd addFish configs --- solidity/utils/addConverter.js | 75 +++--- solidity/utils/addConverter_previous.js | 337 ++++++++++++++++++++++++ solidity/utils/addFish_mainnet.json | 2 +- solidity/utils/addFish_testnet.json | 18 +- 4 files changed, 395 insertions(+), 37 deletions(-) create mode 100644 solidity/utils/addConverter_previous.js diff --git a/solidity/utils/addConverter.js b/solidity/utils/addConverter.js index 6e76fd8..11a7e9b 100644 --- a/solidity/utils/addConverter.js +++ b/solidity/utils/addConverter.js @@ -3,15 +3,15 @@ const path = require("path"); const Web3 = require("web3"); const TOKEN_NAME = process.argv[2]; -const NETWORK = process.argv[3]; +const TOKEN_CONFIG_FILENAME = process.argv[3]; +const DATA_FILENAME = process.argv[4]; const NODE_ADDRESS = process.argv[5]; const PRIVATE_KEY = process.argv[6]; const ARTIFACTS_DIR = path.resolve(__dirname, "../build"); const MIN_GAS_LIMIT = 100000; -const TOKEN_CONFIG_FILENAME = `config_${NETWORK}_${TOKEN_NAME}.json`; -const DATA_FILENAME = `add_${TOKEN_NAME}.json`; + String.prototype.replaceAll = function (exp, newStr) { return this.replace(new RegExp(exp, "gm"), newStr); }; @@ -35,25 +35,19 @@ String.prototype.format = function (args) { return result; }; -let web3; -let gasPrice; -let account; -let phase = 0; - -const initialiseWeb3 = async () => { - const nodeURL = NODE_ADDRESS; - const privateKey = PRIVATE_KEY; - web3 = new Web3(nodeURL); - account = await web3.eth.accounts.privateKeyToAccount(privateKey); - gasPrice = await getGasPrice(web3); -} - const getConfig = () => { + //return JSON.parse(fs.readFileSync(path.join(__dirname, "add{token}.json".format({ token: TOKEN_NAME })), { encoding: "utf8" })); return JSON.parse(fs.readFileSync(path.join(__dirname, TOKEN_CONFIG_FILENAME), { encoding: "utf8" })); }; +const getData = () => { + //TODO read the config according to the network; temporarily moved to input params + //return JSON.parse(fs.readFileSync("./config_rsk_testnet.json", { encoding: "utf8" })); + return JSON.parse(fs.readFileSync(DATA_FILENAME, { encoding: "utf8" })); +}; + const setConfig = (record) => { - fs.writeFileSync(path.join(__dirname, DATA_FILENAME), JSON.stringify({ ...getConfig(), ...record }, null, 4)); + fs.writeFileSync(path.join(__dirname, TOKEN_CONFIG_FILENAME), JSON.stringify({ ...getConfig(), ...record }, null, 4)); }; const scan = async (message) => { @@ -126,9 +120,10 @@ const send = async (web3, account, gasPrice, transaction, value = 0) => { const deploy = async (web3, account, gasPrice, contractId, contractName, contractArgs) => { if (getConfig()[contractId] === undefined) { - const buildFile = JSON.parse(fs.readFileSync(path.join(ARTIFACTS_DIR, contractName + ".json"), { encoding: "utf8" })); - const contract = new web3.eth.Contract(abi); - const options = { data: bin, arguments: contractArgs }; + const abi = fs.readFileSync(path.join(ARTIFACTS_DIR, contractName + ".abi"), { encoding: "utf8" }); + const bin = fs.readFileSync(path.join(ARTIFACTS_DIR, contractName + ".bin"), { encoding: "utf8" }); + const contract = new web3.eth.Contract(JSON.parse(abi)); + const options = { data: "0x" + bin, arguments: contractArgs }; const transaction = contract.deploy(options); const receipt = await send(web3, account, gasPrice, transaction); const args = transaction.encodeABI().slice(options.data.length); @@ -139,8 +134,8 @@ const deploy = async (web3, account, gasPrice, contractId, contractName, contrac }; const deployed = (web3, contractName, contractAddr) => { - const buildFile = JSON.parse(fs.readFileSync(path.join(ARTIFACTS_DIR, contractName + ".json"), { encoding: "utf8" })); - return new web3.eth.Contract(buildFile.abi, contractAddr); + const abi = fs.readFileSync(path.join(ARTIFACTS_DIR, contractName + ".abi"), { encoding: "utf8" }); + return new web3.eth.Contract(JSON.parse(abi), contractAddr); }; const decimalToInteger = (value, decimals) => { @@ -152,19 +147,32 @@ const percentageToPPM = (value) => { return decimalToInteger(value.replace("%", ""), 4); }; -const web3Func = (func, ...args) => func(web3, account, gasPrice, ...args); -const addresses = { ETH: Web3.utils.toChecksumAddress("0x".padEnd(42, "e")) }; -const tokenDecimals = { ETH: 18 }; - const addConverter = async (tokenOracleName, oracleMockName, oracleMockValue, oracleMockHas) => { - await initialiseWeb3(); + const web3 = new Web3(NODE_ADDRESS); + const gasPrice = await getGasPrice(web3); + const account = web3.eth.accounts.privateKeyToAccount(PRIVATE_KEY); + console.log("account: ", account); + const web3Func = (func, ...args) => func(web3, account, gasPrice, ...args); + + const addresses = { ETH: Web3.utils.toChecksumAddress("0x".padEnd(42, "e")) }; + const tokenDecimals = { ETH: 18 }; + + let phase = 0; if (getConfig().phase === undefined) { setConfig({ phase }); } - const converterRegistry = await deployed(web3, "ConverterRegistry", getConfig().converterRegistry.addr); - const oracleWhitelist = await deployed(web3, "Whitelist", getConfig().oracleWhitelist.addr); + const execute = async (transaction, ...args) => { + if (getConfig().phase === phase++) { + await web3Func(send, transaction, ...args); + console.log(`phase ${phase} executed`); + setConfig({ phase }); + } + }; + + const converterRegistry = await deployed(web3, "ConverterRegistry", getData().converterRegistry.addr); + const oracleWhitelist = await deployed(web3, "Whitelist", getData().oracleWhitelist.addr); //this block is just relevant for v2 pools let underlyingOracleAddress = []; @@ -232,7 +240,6 @@ const addConverter = async (tokenOracleName, oracleMockName, oracleMockValue, or await execute(converterRegistry.methods.newConverter(type, name, symbol, decimals, "1000000", tokens, weights)); await execute(converterRegistry.methods.setupConverter(type, tokens, weights, newConverter)); - console.log("New Converter is ", newConverter); setConfig({ [`newLiquidityPoolV${type}Converter`]: { name: `LiquidityPoolV${type}Converter`, addr: newConverter, args: "" } }); @@ -241,7 +248,8 @@ const addConverter = async (tokenOracleName, oracleMockName, oracleMockValue, or const anchor = deployed(web3, "IConverterAnchor", (await converterRegistry.methods.getAnchors().call()).slice(-1)[0]); - console.log("Anchor Taken: ", anchor._address) + // TODO: Remove next line, just here for checking which address is received from anchor. The last address shown from above anchor list should be shown. + console.log("Anchor Taken: ", anchor); const converterBase = deployed(web3, "ConverterBase", newConverter); @@ -264,9 +272,8 @@ const addConverter = async (tokenOracleName, oracleMockName, oracleMockValue, or console.log("Done with adding oracle"); console.log("Updating oracle ownership"); - await execute(oracle.methods.transferOwnership(multiSigWallet._address)); + await execute(oracle.methods.transferOwnership(multiSigWallet._address)); } - //adding the liquidity and thereby seeting the price if (type !== 0 && amounts.every((amount) => amount > 0)) { for (let i = 0; i < converter.reserves.length; i++) { @@ -283,7 +290,7 @@ const addConverter = async (tokenOracleName, oracleMockName, oracleMockValue, or const oracleName = reserve.symbol === "RBTC" ? "MocBTCToUSDOracle" : tokenOracleName; //mocMedianizerMockUSDtoBTC is actually returning BTCtoUSD const mocOracleArgs = - oracleName === "MocBTCToUSDOracle" ? [getConfig().mocMedianizerMockUSDtoBTC.addr] : [underlyingOracleAddress]; + oracleName === "MocBTCToUSDOracle" ? [getData().mocMedianizerMockUSDtoBTC.addr] : [underlyingOracleAddress]; const mocPriceOracle = await web3Func( deploy, "mocPriceOracle" + converter.symbol + reserve.symbol, diff --git a/solidity/utils/addConverter_previous.js b/solidity/utils/addConverter_previous.js new file mode 100644 index 0000000..6e76fd8 --- /dev/null +++ b/solidity/utils/addConverter_previous.js @@ -0,0 +1,337 @@ +const fs = require("fs"); +const path = require("path"); +const Web3 = require("web3"); + +const TOKEN_NAME = process.argv[2]; +const NETWORK = process.argv[3]; +const NODE_ADDRESS = process.argv[5]; +const PRIVATE_KEY = process.argv[6]; + +const ARTIFACTS_DIR = path.resolve(__dirname, "../build"); + +const MIN_GAS_LIMIT = 100000; +const TOKEN_CONFIG_FILENAME = `config_${NETWORK}_${TOKEN_NAME}.json`; +const DATA_FILENAME = `add_${TOKEN_NAME}.json`; +String.prototype.replaceAll = function (exp, newStr) { + return this.replace(new RegExp(exp, "gm"), newStr); +}; + +String.prototype.format = function (args) { + var result = this; + if (arguments.length < 1) { + return result; + } + + var data = arguments; + if (arguments.length == 1 && typeof args == "object") { + data = args; + } + for (var key in data) { + var value = data[key]; + if (undefined != value) { + result = result.replaceAll("\\{" + key + "\\}", value); + } + } + return result; +}; + +let web3; +let gasPrice; +let account; +let phase = 0; + +const initialiseWeb3 = async () => { + const nodeURL = NODE_ADDRESS; + const privateKey = PRIVATE_KEY; + web3 = new Web3(nodeURL); + account = await web3.eth.accounts.privateKeyToAccount(privateKey); + gasPrice = await getGasPrice(web3); +} + +const getConfig = () => { + return JSON.parse(fs.readFileSync(path.join(__dirname, TOKEN_CONFIG_FILENAME), { encoding: "utf8" })); +}; + +const setConfig = (record) => { + fs.writeFileSync(path.join(__dirname, DATA_FILENAME), JSON.stringify({ ...getConfig(), ...record }, null, 4)); +}; + +const scan = async (message) => { + process.stdout.write(message); + return await new Promise((resolve, reject) => { + process.stdin.resume(); + process.stdin.once("data", (data) => { + process.stdin.pause(); + resolve(data.toString().trim()); + }); + }); +}; + +const getGasPrice = async (web3) => { + while (true) { + const nodeGasPrice = await web3.eth.getGasPrice(); + const userGasPrice = await scan(`Enter gas-price or leave empty to use ${nodeGasPrice}: `); + if (/^\d+$/.test(userGasPrice)) { + return userGasPrice; + } + if (userGasPrice === "") { + return nodeGasPrice; + } + console.log("Illegal gas-price"); + } +}; + +const getTransactionReceipt = async (web3) => { + while (true) { + const hash = await scan("Enter transaction-hash or leave empty to retry: "); + if (/^0x([0-9A-Fa-f]{64})$/.test(hash)) { + const receipt = await web3.eth.getTransactionReceipt(hash); + if (receipt) { + return receipt; + } + console.log("Invalid transaction-hash"); + } else if (hash) { + console.log("Illegal transaction-hash"); + } else { + return null; + } + } +}; + +const send = async (web3, account, gasPrice, transaction, value = 0) => { + while (true) { + try { + const gasEstimate = await transaction.estimateGas({ from: account.address, value: value }); + console.log("gasEstimate: " + gasEstimate, " - value - ", value); + const tx = { + to: transaction._parent._address, + data: transaction.encodeABI(), + gas: Math.max(await transaction.estimateGas({ from: account.address, value: value }), MIN_GAS_LIMIT), + gasPrice: gasPrice || (await getGasPrice(web3)), + chainId: await web3.eth.net.getId(), + value: value, + }; + const signed = await web3.eth.accounts.signTransaction(tx, account.privateKey); + const receipt = await web3.eth.sendSignedTransaction(signed.rawTransaction); + return receipt; + } catch (error) { + console.log(error.message); + const receipt = await getTransactionReceipt(web3); + if (receipt) { + return receipt; + } + } + } +}; + +const deploy = async (web3, account, gasPrice, contractId, contractName, contractArgs) => { + if (getConfig()[contractId] === undefined) { + const buildFile = JSON.parse(fs.readFileSync(path.join(ARTIFACTS_DIR, contractName + ".json"), { encoding: "utf8" })); + const contract = new web3.eth.Contract(abi); + const options = { data: bin, arguments: contractArgs }; + const transaction = contract.deploy(options); + const receipt = await send(web3, account, gasPrice, transaction); + const args = transaction.encodeABI().slice(options.data.length); + console.log(`${contractId} deployed at ${receipt.contractAddress}`); + setConfig({ [contractId]: { name: contractName, addr: receipt.contractAddress, args: args } }); + } + return deployed(web3, contractName, getConfig()[contractId].addr); +}; + +const deployed = (web3, contractName, contractAddr) => { + const buildFile = JSON.parse(fs.readFileSync(path.join(ARTIFACTS_DIR, contractName + ".json"), { encoding: "utf8" })); + return new web3.eth.Contract(buildFile.abi, contractAddr); +}; + +const decimalToInteger = (value, decimals) => { + const parts = [...value.split("."), ""]; + return parts[0] + parts[1].padEnd(decimals, "0"); +}; + +const percentageToPPM = (value) => { + return decimalToInteger(value.replace("%", ""), 4); +}; + +const web3Func = (func, ...args) => func(web3, account, gasPrice, ...args); +const addresses = { ETH: Web3.utils.toChecksumAddress("0x".padEnd(42, "e")) }; +const tokenDecimals = { ETH: 18 }; + +const addConverter = async (tokenOracleName, oracleMockName, oracleMockValue, oracleMockHas) => { + await initialiseWeb3(); + + if (getConfig().phase === undefined) { + setConfig({ phase }); + } + + const converterRegistry = await deployed(web3, "ConverterRegistry", getConfig().converterRegistry.addr); + const oracleWhitelist = await deployed(web3, "Whitelist", getConfig().oracleWhitelist.addr); + + //this block is just relevant for v2 pools + let underlyingOracleAddress = []; + if (oracleMockName != undefined) { + //if underlying address is defined, use it + if (getConfig().underlyingOracleAddress !== undefined) { + underlyingOracleAddress = getConfig().underlyingOracleAddress; + } + //else deploy a mockup + else { + console.log("deploying a mockup"); + const oracleMock = await web3Func(deploy, oracleMockName, oracleMockName, []); + underlyingOracleAddress = oracleMock._address; + if (oracleMockName != undefined) { + await execute(oracleMock.methods.setValue(oracleMockValue)); + } + if (oracleMockHas != undefined) { + await execute(oracleMock.methods.setHas(oracleMockHas)); + } + const tokenOracle = await web3Func(deploy, tokenOracleName, tokenOracleName, [underlyingOracleAddress]); + } + } + + //read reserve data from the config or deploy new tokens if not defined + for (const reserve of getConfig().reserves) { + if (reserve.address) { + addresses[reserve.symbol] = reserve.address; + tokenDecimals[reserve.symbol] = reserve.decimals; + setConfig({ [reserve.symbol]: { name: reserve.symbol, addr: reserve.address } }); + } else { + t = await web3Func(deploy, reserve.symbol, "ERC20Token", [ + reserve.symbol, + reserve.symbol, + reserve.decimals, + decimalToInteger("10000", reserve.decimals), + ]); + tokenDecimals[reserve.symbol] = reserve.decimals; + addresses[reserve.symbol] = t._address; + } + } + + for (const converter of getConfig().converters) { + const type = converter.type; + const name = converter.symbol + (type == 0 ? " Liquid Token" : " Liquidity Pool"); + const symbol = converter.symbol; + const decimals = converter.decimals; + const fee = percentageToPPM(converter.fee); + + const tokens = converter.reserves.map((reserve) => addresses[reserve.symbol]); + const weights = converter.reserves.map((reserve) => percentageToPPM(reserve.weight)); + const amounts = converter.reserves.map((reserve) => decimalToInteger(reserve.balance, tokenDecimals[reserve.symbol])); + const value = 0; // amounts[converter.reserves.findIndex(reserve => reserve.symbol === 'RBTC')]; + + console.log("Deploying converter for ", type, " - ", name, " with value ", value); + if (getConfig()["phase"] > 0) console.log(`Restarting from phase #${getConfig()["phase"]}`); + + let newConverter; + //if the script breaks during execution, run it again, it will resume from the point of failure automagically + if (getConfig()["phase"] < 2) { + newConverter = await converterRegistry.methods.newConverter(type, name, symbol, decimals, "1000000", tokens, weights).call(); + } else { + newConverter = getConfig()[`newLiquidityPoolV${type}Converter`].addr; + console.log("Using previously created converter ", newConverter); + } + + await execute(converterRegistry.methods.newConverter(type, name, symbol, decimals, "1000000", tokens, weights)); + await execute(converterRegistry.methods.setupConverter(type, tokens, weights, newConverter)); + + console.log("New Converter is ", newConverter); + setConfig({ [`newLiquidityPoolV${type}Converter`]: { name: `LiquidityPoolV${type}Converter`, addr: newConverter, args: "" } }); + + console.log("Calling anchors"); + console.log(await converterRegistry.methods.getAnchors().call()); + + const anchor = deployed(web3, "IConverterAnchor", (await converterRegistry.methods.getAnchors().call()).slice(-1)[0]); + + console.log("Anchor Taken: ", anchor._address) + + const converterBase = deployed(web3, "ConverterBase", newConverter); + + console.log("Now executing the settings on " + converterBase._address); + await execute(converterBase.methods.acceptOwnership()); + console.log("Done with ownership acceptance"); + await execute(converterBase.methods.setConversionFee(fee)); + console.log("Done with conversion fee"); + + if (type === 1) { + console.log("Deploying Oracle"); + const oracle = await web3Func(deploy, "Oracle", "Oracle", [converterBase._address, getConfig().btcAddress]); + + console.log("Setting k", getConfig().k); + await execute(oracle.methods.setK(getConfig().k)); + + console.log("Setting oracle in converter", oracle._address); + const liquidityV1PoolConverter = deployed(web3, "LiquidityPoolV1Converter", converterBase._address); + await execute(liquidityV1PoolConverter.methods.setOracle(oracle._address)); + console.log("Done with adding oracle"); + + console.log("Updating oracle ownership"); + await execute(oracle.methods.transferOwnership(multiSigWallet._address)); + } + + //adding the liquidity and thereby seeting the price + if (type !== 0 && amounts.every((amount) => amount > 0)) { + for (let i = 0; i < converter.reserves.length; i++) { + const reserve = converter.reserves[i]; + + console.log("Approving amount for ERC20Token: " + amounts[i]); + await execute(deployed(web3, "ERC20Token", tokens[i]).methods.approve(converterBase._address, amounts[i])); + let availableBalance = await deployed(web3, "ERC20Token", tokens[i]).methods.balanceOf(account.address).call(); + console.log("available balance: "); + console.log(availableBalance); + + if (type == 2) { + if (!reserve.oracle) { + const oracleName = reserve.symbol === "RBTC" ? "MocBTCToUSDOracle" : tokenOracleName; + //mocMedianizerMockUSDtoBTC is actually returning BTCtoUSD + const mocOracleArgs = + oracleName === "MocBTCToUSDOracle" ? [getConfig().mocMedianizerMockUSDtoBTC.addr] : [underlyingOracleAddress]; + const mocPriceOracle = await web3Func( + deploy, + "mocPriceOracle" + converter.symbol + reserve.symbol, + oracleName, + mocOracleArgs + ); + reserve.oracle = mocPriceOracle._address; + } + console.log("reserve.oracle", reserve.oracle); + await execute(oracleWhitelist.methods.addAddress(reserve.oracle)); + } + } + + if (type == 1) { + console.log("adding liquidity"); + console.log("tokens:"); + console.log(tokens); + console.log("amounts:"); + console.log(amounts); + console.log("converterBase._address:"); + console.log(converterBase._address); + await execute(deployed(web3, "LiquidityPoolV1Converter", converterBase._address).methods.addLiquidity(tokens, amounts, 1), value); + } else if (type == 2) { + const deployedConverter = deployed(web3, "LiquidityPoolV2Converter", converterBase._address); + await execute(deployedConverter.methods.activate(tokens[0], converter.reserves[0].oracle, converter.reserves[1].oracle)); + + for (let i = 0; i < converter.reserves.length; i++) { + console.log("Adding liquidity for LiquidityPoolV2Converter. ", "For token: ", tokens[i], " with amount ", amounts[i]); + await execute(deployedConverter.methods.addLiquidity(tokens[i], amounts[i], 1), value); + console.log("Liquidity added"); + } + } + } + + addresses[converter.symbol] = anchor._address; + } + + console.log("All done"); + + if (web3.currentProvider.constructor.name === "WebsocketProvider") { + web3.currentProvider.connection.close(); + } +}; + +if (TOKEN_NAME === "BPro") { + addConverter("BProOracle", "MoCStateMock", "20000000000000000000000"); +} else if (TOKEN_NAME === "USDT") { + addConverter("MocBTCToBTCOracle"); +} else { + addConverter(); +} diff --git a/solidity/utils/addFish_mainnet.json b/solidity/utils/addFish_mainnet.json index a8a1ee5..d34f431 100644 --- a/solidity/utils/addFish_mainnet.json +++ b/solidity/utils/addFish_mainnet.json @@ -8,7 +8,7 @@ { "symbol": "FISH", "decimals": 18, - "address": "" + "address": "0x055A902303746382FBB7D18f6aE0df56eFDc5213" } ], "converters": [ diff --git a/solidity/utils/addFish_testnet.json b/solidity/utils/addFish_testnet.json index a16feac..3190b91 100644 --- a/solidity/utils/addFish_testnet.json +++ b/solidity/utils/addFish_testnet.json @@ -8,7 +8,7 @@ { "symbol": "FISH", "decimals": 18, - "address": "" + "address": "0xaa7038D80521351F243168FefE0352194e3f83C3" } ], "converters": [ @@ -32,5 +32,19 @@ } ], "k": 6779, - "btcAddress": "0x69FE5cEC81D5eF92600c1A0dB1F11986AB3758Ab" + "btcAddress": "0x69FE5cEC81D5eF92600c1A0dB1F11986AB3758Ab", + "phase": 4, + "(WR)BTC": { + "name": "(WR)BTC", + "addr": "0x69FE5cEC81D5eF92600c1A0dB1F11986AB3758Ab" + }, + "FISH": { + "name": "FISH", + "addr": "0xaa7038D80521351F243168FefE0352194e3f83C3" + }, + "newLiquidityPoolV1Converter": { + "name": "LiquidityPoolV1Converter", + "addr": "0x179caA42B5024ec1C3D8513A262fC9986F565295", + "args": "" + } } \ No newline at end of file From ef19d51684bc93a86ecfad80dac46a0a0fd26aaa Mon Sep 17 00:00:00 2001 From: ororopickpocket Date: Fri, 27 Aug 2021 13:20:13 +0000 Subject: [PATCH 07/24] changed add converter script to work with truffle build files --- solidity/utils/addConverter.js | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/solidity/utils/addConverter.js b/solidity/utils/addConverter.js index 11a7e9b..ff339d0 100644 --- a/solidity/utils/addConverter.js +++ b/solidity/utils/addConverter.js @@ -119,23 +119,28 @@ const send = async (web3, account, gasPrice, transaction, value = 0) => { }; const deploy = async (web3, account, gasPrice, contractId, contractName, contractArgs) => { - if (getConfig()[contractId] === undefined) { - const abi = fs.readFileSync(path.join(ARTIFACTS_DIR, contractName + ".abi"), { encoding: "utf8" }); - const bin = fs.readFileSync(path.join(ARTIFACTS_DIR, contractName + ".bin"), { encoding: "utf8" }); - const contract = new web3.eth.Contract(JSON.parse(abi)); - const options = { data: "0x" + bin, arguments: contractArgs }; + if (getConfig()[contractId] === undefined || contractId === "Oracle") { + const buildFile = JSON.parse(fs.readFileSync(path.join(ARTIFACTS_DIR, contractName + ".json"), { encoding: "utf8" })); + + const contract = new web3.eth.Contract(buildFile.abi); + const options = { data: buildFile.bytecode, arguments: contractArgs }; const transaction = contract.deploy(options); const receipt = await send(web3, account, gasPrice, transaction); const args = transaction.encodeABI().slice(options.data.length); console.log(`${contractId} deployed at ${receipt.contractAddress}`); - setConfig({ [contractId]: { name: contractName, addr: receipt.contractAddress, args: args } }); + + let configName = contractId; + if (contractId === "Oracle") configName = `${contractId}${converterIndex++}`; + + setConfig({ [configName]: { name: contractName, addr: receipt.contractAddress, args: args } }); + return deployed(web3, contractName, receipt.contractAddress); } return deployed(web3, contractName, getConfig()[contractId].addr); }; const deployed = (web3, contractName, contractAddr) => { - const abi = fs.readFileSync(path.join(ARTIFACTS_DIR, contractName + ".abi"), { encoding: "utf8" }); - return new web3.eth.Contract(JSON.parse(abi), contractAddr); + const buildFile = JSON.parse(fs.readFileSync(path.join(ARTIFACTS_DIR, contractName + ".json"), { encoding: "utf8" })); + return new web3.eth.Contract(buildFile.abi, contractAddr); }; const decimalToInteger = (value, decimals) => { From 04475a9f79a4c3b4d79e0662b75d290f4611df07 Mon Sep 17 00:00:00 2001 From: ororopickpocket Date: Fri, 27 Aug 2021 13:21:53 +0000 Subject: [PATCH 08/24] mend --- solidity/utils/addConverter.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/solidity/utils/addConverter.js b/solidity/utils/addConverter.js index ff339d0..ab31f4a 100644 --- a/solidity/utils/addConverter.js +++ b/solidity/utils/addConverter.js @@ -8,7 +8,7 @@ const DATA_FILENAME = process.argv[4]; const NODE_ADDRESS = process.argv[5]; const PRIVATE_KEY = process.argv[6]; -const ARTIFACTS_DIR = path.resolve(__dirname, "../build"); +const ARTIFACTS_DIR = path.resolve(__dirname, "../build/contracts"); const MIN_GAS_LIMIT = 100000; From a79851bb56898bd51369510f8e74c52f9693008f Mon Sep 17 00:00:00 2001 From: Tyrone Johnson Date: Mon, 30 Aug 2021 11:08:53 +0300 Subject: [PATCH 09/24] upd/added multisig wallet to data files --- solidity/utils/data_mainnet.json | 7 ++++++- solidity/utils/data_testnet.json | 5 +++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/solidity/utils/data_mainnet.json b/solidity/utils/data_mainnet.json index e68c485..69edfa3 100644 --- a/solidity/utils/data_mainnet.json +++ b/solidity/utils/data_mainnet.json @@ -112,5 +112,10 @@ "name": "MocBTCToBTCOracle", "addr": "0xf5DF3b2AE0c4E2c8912E177f6BD8ca6d479397A2", "args": "" + }, + "multiSigWallet": { + "name": "MultiSigWallet", + "addr": "0x924f5ad34698Fd20c90Fe5D5A8A0abd3b42dc711", + "args": "" } -} +} \ No newline at end of file diff --git a/solidity/utils/data_testnet.json b/solidity/utils/data_testnet.json index dfdf3e1..7efb5fa 100644 --- a/solidity/utils/data_testnet.json +++ b/solidity/utils/data_testnet.json @@ -111,5 +111,10 @@ "name": "MocBTCToBTCOracle", "addr": "0xf37963592635c020E0AD3313bA39C9BA627a3FB5", "args": "" + }, + "multiSigWallet": { + "name": "MultiSigWallet", + "addr": "", + "args": "" } } \ No newline at end of file From 4418613ad46381b6ba2972047738e29ff836f7b7 Mon Sep 17 00:00:00 2001 From: Tyrone Johnson Date: Mon, 30 Aug 2021 11:10:25 +0300 Subject: [PATCH 10/24] upd/replaced mainnet to mainnet2 URL for RPC calls --- ADD-POOLS.md | 2 +- solidity/utils/command.txt | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/ADD-POOLS.md b/ADD-POOLS.md index 5c76fdc..dc98bc0 100644 --- a/ADD-POOLS.md +++ b/ADD-POOLS.md @@ -97,7 +97,7 @@ testnet: mainnet: -```node addConverter.js ETH addETHs_mainnet.json data_mainnet.json https://mainnet.sovryn.app/rpc ``` +```node addConverter.js ETH addETHs_mainnet.json data_mainnet.json https://mainnet2.sovryn.app/rpc ``` ```TODO: check if the following is for v2 pools only``` diff --git a/solidity/utils/command.txt b/solidity/utils/command.txt index a3ca65e..561f43c 100644 --- a/solidity/utils/command.txt +++ b/solidity/utils/command.txt @@ -12,4 +12,4 @@ testnet: node addConverter.js ETH addETHs_testnet.json data_testnet.json https://public-node.testnet.rsk.co mainnet: -node addConverter.js ETH addETHs_mainnet.json data_mainnet.json https://mainnet.sovryn.app/rpc +node addConverter.js ETH addETHs_mainnet.json data_mainnet.json https://mainnet2.sovryn.app/rpc From a5637b2f384e22035782aba5140bb6a214c888c8 Mon Sep 17 00:00:00 2001 From: Tyrone Johnson Date: Mon, 30 Aug 2021 11:10:40 +0300 Subject: [PATCH 11/24] fix/hh config formatting --- hardhat.config.js | 128 +++++++++++++++++++++++----------------------- 1 file changed, 64 insertions(+), 64 deletions(-) diff --git a/hardhat.config.js b/hardhat.config.js index e92f8ce..bc25ea2 100644 --- a/hardhat.config.js +++ b/hardhat.config.js @@ -7,19 +7,19 @@ require("@nomiclabs/hardhat-web3"); require("hardhat-contract-sizer"); //yarn run hardhat size-contracts require("solidity-coverage"); // $ npx hardhat coverage require("hardhat-log-remover"); -require('hardhat-docgen'); +require("hardhat-docgen"); // This is a sample Hardhat task. To learn how to create your own go to // https://hardhat.org/guides/create-task.html /// this is for use with ethers.js task("accounts", "Prints the list of accounts", async () => { - const accounts = await ethers.getSigners(); + const accounts = await ethers.getSigners(); - for (const account of accounts.address) { - const wallet = ethers.Wallet.fromMnemonic("test test test test test test test test test test test junk", "m/44'/60'/0'/0"); + for (const account of accounts.address) { + const wallet = ethers.Wallet.fromMnemonic("test test test test test test test test test test test junk", "m/44'/60'/0'/0"); - console.log(account); - } + console.log(account); + } }); /*task("accounts", "Prints accounts", async (_, { web3 }) => { @@ -36,61 +36,61 @@ task("accounts", "Prints the list of accounts", async () => { /**/ module.exports = { - solidity: { - version: "0.4.26", - settings: { - optimizer: { - enabled: true, - runs: 200, - }, - }, - }, - contractSizer: { - alphaSort: false, - runOnCompile: false, - disambiguatePaths: false, - }, - networks: { - hardhat: {}, - rskPublicTestnet: { - url: "https://public-node.testnet.rsk.co/", - accounts: { mnemonic: "brownie", count: 10 }, - network_id: 31, - confirmations: 4, - gasMultiplier: 1.25, - //timeout: 20000, // increase if needed; 20000 is the default value - //allowUnlimitedContractSize, //EIP170 contrtact size restriction temporal testnet workaround - }, - rskPublicMainnet: { - url: "https://public-node.rsk.co/", - network_id: 30, - //timeout: 20000, // increase if needed; 20000 is the default value - }, - rskSovrynTestnet: { - url: "https://testnet.sovryn.app/rpc", - accounts: { mnemonic: "brownie", count: 10 }, - network_id: 31, - confirmations: 4, - gasMultiplier: 1.25, - //timeout: 20000, // increase if needed; 20000 is the default value - //allowUnlimitedContractSize, //EIP170 contrtact size restriction temporal testnet workaround - }, - rskSovrynMainnet: { - url: "https://mainnet.sovryn.app/rpc", - network_id: 30, - //timeout: 20000, // increase if needed; 20000 is the default value - }, - }, - paths: { - sources: "./solidity/contracts", - tests: "./solidity/test/", - }, - mocha: { - timeout: 800000, - grep: "^(?!.*; using Ganache).*", - }, - docgen: { - path: './docs', - clear: true - } -}; \ No newline at end of file + solidity: { + version: "0.4.26", + settings: { + optimizer: { + enabled: true, + runs: 200, + }, + }, + }, + contractSizer: { + alphaSort: false, + runOnCompile: false, + disambiguatePaths: false, + }, + networks: { + hardhat: {}, + rskPublicTestnet: { + url: "https://public-node.testnet.rsk.co/", + accounts: { mnemonic: "brownie", count: 10 }, + network_id: 31, + confirmations: 4, + gasMultiplier: 1.25, + //timeout: 20000, // increase if needed; 20000 is the default value + //allowUnlimitedContractSize, //EIP170 contrtact size restriction temporal testnet workaround + }, + rskPublicMainnet: { + url: "https://public-node.rsk.co/", + network_id: 30, + //timeout: 20000, // increase if needed; 20000 is the default value + }, + rskSovrynTestnet: { + url: "https://testnet.sovryn.app/rpc", + accounts: { mnemonic: "brownie", count: 10 }, + network_id: 31, + confirmations: 4, + gasMultiplier: 1.25, + //timeout: 20000, // increase if needed; 20000 is the default value + //allowUnlimitedContractSize, //EIP170 contrtact size restriction temporal testnet workaround + }, + rskSovrynMainnet: { + url: "https://mainnet2.sovryn.app/rpc", + network_id: 30, + //timeout: 20000, // increase if needed; 20000 is the default value + }, + }, + paths: { + sources: "./solidity/contracts", + tests: "./solidity/test/", + }, + mocha: { + timeout: 800000, + grep: "^(?!.*; using Ganache).*", + }, + docgen: { + path: "./docs", + clear: true, + }, +}; From f48fedf7b58dd8e39e85312611bbaeb4745a52d1 Mon Sep 17 00:00:00 2001 From: Tyrone Johnson Date: Mon, 30 Aug 2021 11:12:42 +0300 Subject: [PATCH 12/24] fix/multisig wallet, TODOs added to process Oracle --- solidity/utils/addConverter.js | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) diff --git a/solidity/utils/addConverter.js b/solidity/utils/addConverter.js index ab31f4a..f2fd6d8 100644 --- a/solidity/utils/addConverter.js +++ b/solidity/utils/addConverter.js @@ -130,8 +130,11 @@ const deploy = async (web3, account, gasPrice, contractId, contractName, contrac console.log(`${contractId} deployed at ${receipt.contractAddress}`); let configName = contractId; - if (contractId === "Oracle") configName = `${contractId}${converterIndex++}`; - + let converterIndex = 0; + //TODO: IMPORTANT - FIGURE OUT HOW TO GET CONVERTER INDEX! IT WON'T WORK WITH MUlTIPLE CONVERTERS! + //TODO: move oracle to "converters" + //if (contractId === "Oracle") configName = `${contractId}${converterIndex++}`; + if (contractId === "Oracle") configName = `${contractId}`; setConfig({ [configName]: { name: contractName, addr: receipt.contractAddress, args: args } }); return deployed(web3, contractName, receipt.contractAddress); } @@ -178,6 +181,8 @@ const addConverter = async (tokenOracleName, oracleMockName, oracleMockValue, or const converterRegistry = await deployed(web3, "ConverterRegistry", getData().converterRegistry.addr); const oracleWhitelist = await deployed(web3, "Whitelist", getData().oracleWhitelist.addr); + let multiSigWallet; + if (getData().multiSigWallet.addr !== "") multiSigWallet = deployed(web3, getData().multiSigWallet.name, getData().multiSigWallet.addr); //this block is just relevant for v2 pools let underlyingOracleAddress = []; @@ -254,7 +259,7 @@ const addConverter = async (tokenOracleName, oracleMockName, oracleMockValue, or const anchor = deployed(web3, "IConverterAnchor", (await converterRegistry.methods.getAnchors().call()).slice(-1)[0]); // TODO: Remove next line, just here for checking which address is received from anchor. The last address shown from above anchor list should be shown. - console.log("Anchor Taken: ", anchor); + //console.log("Anchor Taken: ", anchor); const converterBase = deployed(web3, "ConverterBase", newConverter); @@ -276,8 +281,12 @@ const addConverter = async (tokenOracleName, oracleMockName, oracleMockValue, or await execute(liquidityV1PoolConverter.methods.setOracle(oracle._address)); console.log("Done with adding oracle"); - console.log("Updating oracle ownership"); - await execute(oracle.methods.transferOwnership(multiSigWallet._address)); + if (multiSigWallet !== undefined) { + console.log("Updating oracle ownership"); + await execute(oracle.methods.transferOwnership(multiSigWallet._address)); + } else { + console.log("Oracle owner is account: ", await oracle.methods.owner().call()); + } } //adding the liquidity and thereby seeting the price if (type !== 0 && amounts.every((amount) => amount > 0)) { From afacba78fc99231a20c33ea0eb4ae414ed230db6 Mon Sep 17 00:00:00 2001 From: Tyrone Johnson Date: Mon, 30 Aug 2021 11:13:23 +0300 Subject: [PATCH 13/24] upd/fish token cionfigs updates by deployment --- solidity/utils/addFish_mainnet.json | 21 ++++++++++++++++++++- solidity/utils/addFish_testnet.json | 7 ++++++- 2 files changed, 26 insertions(+), 2 deletions(-) diff --git a/solidity/utils/addFish_mainnet.json b/solidity/utils/addFish_mainnet.json index d34f431..ecffd40 100644 --- a/solidity/utils/addFish_mainnet.json +++ b/solidity/utils/addFish_mainnet.json @@ -32,5 +32,24 @@ } ], "k": 6779, - "btcAddress": "0x542fDA317318eBF1d3DEAf76E0b632741A7e677d" + "btcAddress": "0x542fDA317318eBF1d3DEAf76E0b632741A7e677d", + "phase": 7, + "(WR)BTC": { + "name": "(WR)BTC", + "addr": "0x542fDA317318eBF1d3DEAf76E0b632741A7e677d" + }, + "FISH": { + "name": "FISH", + "addr": "0x055A902303746382FBB7D18f6aE0df56eFDc5213" + }, + "newLiquidityPoolV1Converter": { + "name": "LiquidityPoolV1Converter", + "addr": "0xe731DA93034D769c2045B1ee137D42E1Aa23C18e", + "args": "" + }, + "Oracle": { + "name": "Oracle", + "addr": "0x6C58148993bB918347D6d4e0E67EE47903776ab7", + "args": "000000000000000000000000e731da93034d769c2045b1ee137d42e1aa23c18e000000000000000000000000542fda317318ebf1d3deaf76e0b632741a7e677d" + } } \ No newline at end of file diff --git a/solidity/utils/addFish_testnet.json b/solidity/utils/addFish_testnet.json index 3190b91..e8a2368 100644 --- a/solidity/utils/addFish_testnet.json +++ b/solidity/utils/addFish_testnet.json @@ -33,7 +33,7 @@ ], "k": 6779, "btcAddress": "0x69FE5cEC81D5eF92600c1A0dB1F11986AB3758Ab", - "phase": 4, + "phase": 6, "(WR)BTC": { "name": "(WR)BTC", "addr": "0x69FE5cEC81D5eF92600c1A0dB1F11986AB3758Ab" @@ -46,5 +46,10 @@ "name": "LiquidityPoolV1Converter", "addr": "0x179caA42B5024ec1C3D8513A262fC9986F565295", "args": "" + }, + "Oracle": { + "name": "Oracle", + "addr": "0x498E4D1d39968b0BB5DECD52D71055529150ba74", + "args": "000000000000000000000000179caa42b5024ec1c3d8513a262fc9986f56529500000000000000000000000069fe5cec81d5ef92600c1a0db1f11986ab3758ab" } } \ No newline at end of file From 6c92f18599cda3a2bfc5d4dbb81342e1fa05f512 Mon Sep 17 00:00:00 2001 From: Tyrone Johnson Date: Mon, 30 Aug 2021 11:21:00 +0300 Subject: [PATCH 14/24] enh/added TODO to transfer ownership to multisig --- solidity/utils/addConverter.js | 1 + 1 file changed, 1 insertion(+) diff --git a/solidity/utils/addConverter.js b/solidity/utils/addConverter.js index f2fd6d8..0835fa6 100644 --- a/solidity/utils/addConverter.js +++ b/solidity/utils/addConverter.js @@ -342,6 +342,7 @@ const addConverter = async (tokenOracleName, oracleMockName, oracleMockValue, or addresses[converter.symbol] = anchor._address; } + //TODO: add transfer ownership of converter to multisig console.log("All done"); if (web3.currentProvider.constructor.name === "WebsocketProvider") { From fedb46a2bb2f31cdc1a7c04ba3880fa866160542 Mon Sep 17 00:00:00 2001 From: Tyrone Johnson Date: Thu, 25 Nov 2021 17:52:30 +0300 Subject: [PATCH 15/24] added a newline as separator --- solidity/utils/addConverter.js | 1 + 1 file changed, 1 insertion(+) diff --git a/solidity/utils/addConverter.js b/solidity/utils/addConverter.js index 0835fa6..de90c1b 100644 --- a/solidity/utils/addConverter.js +++ b/solidity/utils/addConverter.js @@ -181,6 +181,7 @@ const addConverter = async (tokenOracleName, oracleMockName, oracleMockValue, or const converterRegistry = await deployed(web3, "ConverterRegistry", getData().converterRegistry.addr); const oracleWhitelist = await deployed(web3, "Whitelist", getData().oracleWhitelist.addr); + let multiSigWallet; if (getData().multiSigWallet.addr !== "") multiSigWallet = deployed(web3, getData().multiSigWallet.name, getData().multiSigWallet.addr); From efe5afc48aba794aa7460bb5494ef9cde760f306 Mon Sep 17 00:00:00 2001 From: Tyrone Johnson Date: Thu, 25 Nov 2021 17:52:58 +0300 Subject: [PATCH 16/24] add BZX testnet config --- solidity/utils/addBZX_testnet.json | 36 ++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) create mode 100644 solidity/utils/addBZX_testnet.json diff --git a/solidity/utils/addBZX_testnet.json b/solidity/utils/addBZX_testnet.json new file mode 100644 index 0000000..c5c6c2d --- /dev/null +++ b/solidity/utils/addBZX_testnet.json @@ -0,0 +1,36 @@ +{ + "reserves": [ + { + "symbol": "XUSD", + "decimals": 18, + "address": "0x849d38abd3962cb40d4887e4279ad0e4e5958e34" + }, + { + "symbol": "BZX", + "decimals": 18, + "address": "0xe355c280131dfaf18bf1c3648aee3c396db6b5fd" + } + ], + "converters": [ + { + "type": 1, + "symbol": "XUSD/BZX", + "decimals": 18, + "fee": "0.3%", + "reserves": [ + { + "symbol": "XUSD", + "weight": "50%", + "balance": "0" + }, + { + "symbol": "BZX", + "weight": "50%", + "balance": "0" + } + ] + } + ], + "k": 6779, + "btcAddress": "0x69FE5cEC81D5eF92600c1A0dB1F11986AB3758Ab" +} \ No newline at end of file From 392c3f3094703c464155f5285637cbbb1fd40524 Mon Sep 17 00:00:00 2001 From: Tyrone Johnson Date: Thu, 25 Nov 2021 17:53:39 +0300 Subject: [PATCH 17/24] removed legacy interim non-working addConverter --- solidity/utils/addConverter_previous.js | 337 ------------------------ 1 file changed, 337 deletions(-) delete mode 100644 solidity/utils/addConverter_previous.js diff --git a/solidity/utils/addConverter_previous.js b/solidity/utils/addConverter_previous.js deleted file mode 100644 index 6e76fd8..0000000 --- a/solidity/utils/addConverter_previous.js +++ /dev/null @@ -1,337 +0,0 @@ -const fs = require("fs"); -const path = require("path"); -const Web3 = require("web3"); - -const TOKEN_NAME = process.argv[2]; -const NETWORK = process.argv[3]; -const NODE_ADDRESS = process.argv[5]; -const PRIVATE_KEY = process.argv[6]; - -const ARTIFACTS_DIR = path.resolve(__dirname, "../build"); - -const MIN_GAS_LIMIT = 100000; -const TOKEN_CONFIG_FILENAME = `config_${NETWORK}_${TOKEN_NAME}.json`; -const DATA_FILENAME = `add_${TOKEN_NAME}.json`; -String.prototype.replaceAll = function (exp, newStr) { - return this.replace(new RegExp(exp, "gm"), newStr); -}; - -String.prototype.format = function (args) { - var result = this; - if (arguments.length < 1) { - return result; - } - - var data = arguments; - if (arguments.length == 1 && typeof args == "object") { - data = args; - } - for (var key in data) { - var value = data[key]; - if (undefined != value) { - result = result.replaceAll("\\{" + key + "\\}", value); - } - } - return result; -}; - -let web3; -let gasPrice; -let account; -let phase = 0; - -const initialiseWeb3 = async () => { - const nodeURL = NODE_ADDRESS; - const privateKey = PRIVATE_KEY; - web3 = new Web3(nodeURL); - account = await web3.eth.accounts.privateKeyToAccount(privateKey); - gasPrice = await getGasPrice(web3); -} - -const getConfig = () => { - return JSON.parse(fs.readFileSync(path.join(__dirname, TOKEN_CONFIG_FILENAME), { encoding: "utf8" })); -}; - -const setConfig = (record) => { - fs.writeFileSync(path.join(__dirname, DATA_FILENAME), JSON.stringify({ ...getConfig(), ...record }, null, 4)); -}; - -const scan = async (message) => { - process.stdout.write(message); - return await new Promise((resolve, reject) => { - process.stdin.resume(); - process.stdin.once("data", (data) => { - process.stdin.pause(); - resolve(data.toString().trim()); - }); - }); -}; - -const getGasPrice = async (web3) => { - while (true) { - const nodeGasPrice = await web3.eth.getGasPrice(); - const userGasPrice = await scan(`Enter gas-price or leave empty to use ${nodeGasPrice}: `); - if (/^\d+$/.test(userGasPrice)) { - return userGasPrice; - } - if (userGasPrice === "") { - return nodeGasPrice; - } - console.log("Illegal gas-price"); - } -}; - -const getTransactionReceipt = async (web3) => { - while (true) { - const hash = await scan("Enter transaction-hash or leave empty to retry: "); - if (/^0x([0-9A-Fa-f]{64})$/.test(hash)) { - const receipt = await web3.eth.getTransactionReceipt(hash); - if (receipt) { - return receipt; - } - console.log("Invalid transaction-hash"); - } else if (hash) { - console.log("Illegal transaction-hash"); - } else { - return null; - } - } -}; - -const send = async (web3, account, gasPrice, transaction, value = 0) => { - while (true) { - try { - const gasEstimate = await transaction.estimateGas({ from: account.address, value: value }); - console.log("gasEstimate: " + gasEstimate, " - value - ", value); - const tx = { - to: transaction._parent._address, - data: transaction.encodeABI(), - gas: Math.max(await transaction.estimateGas({ from: account.address, value: value }), MIN_GAS_LIMIT), - gasPrice: gasPrice || (await getGasPrice(web3)), - chainId: await web3.eth.net.getId(), - value: value, - }; - const signed = await web3.eth.accounts.signTransaction(tx, account.privateKey); - const receipt = await web3.eth.sendSignedTransaction(signed.rawTransaction); - return receipt; - } catch (error) { - console.log(error.message); - const receipt = await getTransactionReceipt(web3); - if (receipt) { - return receipt; - } - } - } -}; - -const deploy = async (web3, account, gasPrice, contractId, contractName, contractArgs) => { - if (getConfig()[contractId] === undefined) { - const buildFile = JSON.parse(fs.readFileSync(path.join(ARTIFACTS_DIR, contractName + ".json"), { encoding: "utf8" })); - const contract = new web3.eth.Contract(abi); - const options = { data: bin, arguments: contractArgs }; - const transaction = contract.deploy(options); - const receipt = await send(web3, account, gasPrice, transaction); - const args = transaction.encodeABI().slice(options.data.length); - console.log(`${contractId} deployed at ${receipt.contractAddress}`); - setConfig({ [contractId]: { name: contractName, addr: receipt.contractAddress, args: args } }); - } - return deployed(web3, contractName, getConfig()[contractId].addr); -}; - -const deployed = (web3, contractName, contractAddr) => { - const buildFile = JSON.parse(fs.readFileSync(path.join(ARTIFACTS_DIR, contractName + ".json"), { encoding: "utf8" })); - return new web3.eth.Contract(buildFile.abi, contractAddr); -}; - -const decimalToInteger = (value, decimals) => { - const parts = [...value.split("."), ""]; - return parts[0] + parts[1].padEnd(decimals, "0"); -}; - -const percentageToPPM = (value) => { - return decimalToInteger(value.replace("%", ""), 4); -}; - -const web3Func = (func, ...args) => func(web3, account, gasPrice, ...args); -const addresses = { ETH: Web3.utils.toChecksumAddress("0x".padEnd(42, "e")) }; -const tokenDecimals = { ETH: 18 }; - -const addConverter = async (tokenOracleName, oracleMockName, oracleMockValue, oracleMockHas) => { - await initialiseWeb3(); - - if (getConfig().phase === undefined) { - setConfig({ phase }); - } - - const converterRegistry = await deployed(web3, "ConverterRegistry", getConfig().converterRegistry.addr); - const oracleWhitelist = await deployed(web3, "Whitelist", getConfig().oracleWhitelist.addr); - - //this block is just relevant for v2 pools - let underlyingOracleAddress = []; - if (oracleMockName != undefined) { - //if underlying address is defined, use it - if (getConfig().underlyingOracleAddress !== undefined) { - underlyingOracleAddress = getConfig().underlyingOracleAddress; - } - //else deploy a mockup - else { - console.log("deploying a mockup"); - const oracleMock = await web3Func(deploy, oracleMockName, oracleMockName, []); - underlyingOracleAddress = oracleMock._address; - if (oracleMockName != undefined) { - await execute(oracleMock.methods.setValue(oracleMockValue)); - } - if (oracleMockHas != undefined) { - await execute(oracleMock.methods.setHas(oracleMockHas)); - } - const tokenOracle = await web3Func(deploy, tokenOracleName, tokenOracleName, [underlyingOracleAddress]); - } - } - - //read reserve data from the config or deploy new tokens if not defined - for (const reserve of getConfig().reserves) { - if (reserve.address) { - addresses[reserve.symbol] = reserve.address; - tokenDecimals[reserve.symbol] = reserve.decimals; - setConfig({ [reserve.symbol]: { name: reserve.symbol, addr: reserve.address } }); - } else { - t = await web3Func(deploy, reserve.symbol, "ERC20Token", [ - reserve.symbol, - reserve.symbol, - reserve.decimals, - decimalToInteger("10000", reserve.decimals), - ]); - tokenDecimals[reserve.symbol] = reserve.decimals; - addresses[reserve.symbol] = t._address; - } - } - - for (const converter of getConfig().converters) { - const type = converter.type; - const name = converter.symbol + (type == 0 ? " Liquid Token" : " Liquidity Pool"); - const symbol = converter.symbol; - const decimals = converter.decimals; - const fee = percentageToPPM(converter.fee); - - const tokens = converter.reserves.map((reserve) => addresses[reserve.symbol]); - const weights = converter.reserves.map((reserve) => percentageToPPM(reserve.weight)); - const amounts = converter.reserves.map((reserve) => decimalToInteger(reserve.balance, tokenDecimals[reserve.symbol])); - const value = 0; // amounts[converter.reserves.findIndex(reserve => reserve.symbol === 'RBTC')]; - - console.log("Deploying converter for ", type, " - ", name, " with value ", value); - if (getConfig()["phase"] > 0) console.log(`Restarting from phase #${getConfig()["phase"]}`); - - let newConverter; - //if the script breaks during execution, run it again, it will resume from the point of failure automagically - if (getConfig()["phase"] < 2) { - newConverter = await converterRegistry.methods.newConverter(type, name, symbol, decimals, "1000000", tokens, weights).call(); - } else { - newConverter = getConfig()[`newLiquidityPoolV${type}Converter`].addr; - console.log("Using previously created converter ", newConverter); - } - - await execute(converterRegistry.methods.newConverter(type, name, symbol, decimals, "1000000", tokens, weights)); - await execute(converterRegistry.methods.setupConverter(type, tokens, weights, newConverter)); - - console.log("New Converter is ", newConverter); - setConfig({ [`newLiquidityPoolV${type}Converter`]: { name: `LiquidityPoolV${type}Converter`, addr: newConverter, args: "" } }); - - console.log("Calling anchors"); - console.log(await converterRegistry.methods.getAnchors().call()); - - const anchor = deployed(web3, "IConverterAnchor", (await converterRegistry.methods.getAnchors().call()).slice(-1)[0]); - - console.log("Anchor Taken: ", anchor._address) - - const converterBase = deployed(web3, "ConverterBase", newConverter); - - console.log("Now executing the settings on " + converterBase._address); - await execute(converterBase.methods.acceptOwnership()); - console.log("Done with ownership acceptance"); - await execute(converterBase.methods.setConversionFee(fee)); - console.log("Done with conversion fee"); - - if (type === 1) { - console.log("Deploying Oracle"); - const oracle = await web3Func(deploy, "Oracle", "Oracle", [converterBase._address, getConfig().btcAddress]); - - console.log("Setting k", getConfig().k); - await execute(oracle.methods.setK(getConfig().k)); - - console.log("Setting oracle in converter", oracle._address); - const liquidityV1PoolConverter = deployed(web3, "LiquidityPoolV1Converter", converterBase._address); - await execute(liquidityV1PoolConverter.methods.setOracle(oracle._address)); - console.log("Done with adding oracle"); - - console.log("Updating oracle ownership"); - await execute(oracle.methods.transferOwnership(multiSigWallet._address)); - } - - //adding the liquidity and thereby seeting the price - if (type !== 0 && amounts.every((amount) => amount > 0)) { - for (let i = 0; i < converter.reserves.length; i++) { - const reserve = converter.reserves[i]; - - console.log("Approving amount for ERC20Token: " + amounts[i]); - await execute(deployed(web3, "ERC20Token", tokens[i]).methods.approve(converterBase._address, amounts[i])); - let availableBalance = await deployed(web3, "ERC20Token", tokens[i]).methods.balanceOf(account.address).call(); - console.log("available balance: "); - console.log(availableBalance); - - if (type == 2) { - if (!reserve.oracle) { - const oracleName = reserve.symbol === "RBTC" ? "MocBTCToUSDOracle" : tokenOracleName; - //mocMedianizerMockUSDtoBTC is actually returning BTCtoUSD - const mocOracleArgs = - oracleName === "MocBTCToUSDOracle" ? [getConfig().mocMedianizerMockUSDtoBTC.addr] : [underlyingOracleAddress]; - const mocPriceOracle = await web3Func( - deploy, - "mocPriceOracle" + converter.symbol + reserve.symbol, - oracleName, - mocOracleArgs - ); - reserve.oracle = mocPriceOracle._address; - } - console.log("reserve.oracle", reserve.oracle); - await execute(oracleWhitelist.methods.addAddress(reserve.oracle)); - } - } - - if (type == 1) { - console.log("adding liquidity"); - console.log("tokens:"); - console.log(tokens); - console.log("amounts:"); - console.log(amounts); - console.log("converterBase._address:"); - console.log(converterBase._address); - await execute(deployed(web3, "LiquidityPoolV1Converter", converterBase._address).methods.addLiquidity(tokens, amounts, 1), value); - } else if (type == 2) { - const deployedConverter = deployed(web3, "LiquidityPoolV2Converter", converterBase._address); - await execute(deployedConverter.methods.activate(tokens[0], converter.reserves[0].oracle, converter.reserves[1].oracle)); - - for (let i = 0; i < converter.reserves.length; i++) { - console.log("Adding liquidity for LiquidityPoolV2Converter. ", "For token: ", tokens[i], " with amount ", amounts[i]); - await execute(deployedConverter.methods.addLiquidity(tokens[i], amounts[i], 1), value); - console.log("Liquidity added"); - } - } - } - - addresses[converter.symbol] = anchor._address; - } - - console.log("All done"); - - if (web3.currentProvider.constructor.name === "WebsocketProvider") { - web3.currentProvider.connection.close(); - } -}; - -if (TOKEN_NAME === "BPro") { - addConverter("BProOracle", "MoCStateMock", "20000000000000000000000"); -} else if (TOKEN_NAME === "USDT") { - addConverter("MocBTCToBTCOracle"); -} else { - addConverter(); -} From 52f48f80a1add45ee9c385d998e76709a6fbf72d Mon Sep 17 00:00:00 2001 From: Tyrone Johnson Date: Thu, 25 Nov 2021 17:55:46 +0300 Subject: [PATCH 18/24] add deployment script for non-wRBTC based converters --- solidity/utils/addConverterNoOracle.js | 336 +++++++++++++++++++++++++ 1 file changed, 336 insertions(+) create mode 100644 solidity/utils/addConverterNoOracle.js diff --git a/solidity/utils/addConverterNoOracle.js b/solidity/utils/addConverterNoOracle.js new file mode 100644 index 0000000..248d4f4 --- /dev/null +++ b/solidity/utils/addConverterNoOracle.js @@ -0,0 +1,336 @@ +// This script is designed for deploying v1 converter for token pairs +// where none of them is wRBTC +// TODO: add to docs + +const fs = require("fs"); +const path = require("path"); +const Web3 = require("web3"); + +const TOKEN_NAME = process.argv[2]; +const TOKEN_CONFIG_FILENAME = process.argv[3]; +const DATA_FILENAME = process.argv[4]; +const NODE_ADDRESS = process.argv[5]; +const PRIVATE_KEY = process.argv[6]; + +const ARTIFACTS_DIR = path.resolve(__dirname, "../build/contracts"); + +const MIN_GAS_LIMIT = 100000; + +String.prototype.replaceAll = function (exp, newStr) { + return this.replace(new RegExp(exp, "gm"), newStr); +}; + +String.prototype.format = function (args) { + var result = this; + if (arguments.length < 1) { + return result; + } + + var data = arguments; + if (arguments.length == 1 && typeof args == "object") { + data = args; + } + for (var key in data) { + var value = data[key]; + if (undefined != value) { + result = result.replaceAll("\\{" + key + "\\}", value); + } + } + return result; +}; + +const getConfig = () => { + //return JSON.parse(fs.readFileSync(path.join(__dirname, "add{token}.json".format({ token: TOKEN_NAME })), { encoding: "utf8" })); + return JSON.parse(fs.readFileSync(path.join(__dirname, TOKEN_CONFIG_FILENAME), { encoding: "utf8" })); +}; + +const getData = () => { + //TODO read the config according to the network; temporarily moved to input params + //return JSON.parse(fs.readFileSync("./config_rsk_testnet.json", { encoding: "utf8" })); + return JSON.parse(fs.readFileSync(DATA_FILENAME, { encoding: "utf8" })); +}; + +const setConfig = (record) => { + fs.writeFileSync(path.join(__dirname, TOKEN_CONFIG_FILENAME), JSON.stringify({ ...getConfig(), ...record }, null, 4)); +}; + +const scan = async (message) => { + process.stdout.write(message); + return await new Promise((resolve, reject) => { + process.stdin.resume(); + process.stdin.once("data", (data) => { + process.stdin.pause(); + resolve(data.toString().trim()); + }); + }); +}; + +const getGasPrice = async (web3) => { + while (true) { + const nodeGasPrice = await web3.eth.getGasPrice(); + const userGasPrice = await scan(`Enter gas-price or leave empty to use ${nodeGasPrice}: `); + if (/^\d+$/.test(userGasPrice)) { + return userGasPrice; + } + if (userGasPrice === "") { + return nodeGasPrice; + } + console.log("Illegal gas-price"); + } +}; + +const getTransactionReceipt = async (web3) => { + while (true) { + const hash = await scan("Enter transaction-hash or leave empty to retry: "); + if (/^0x([0-9A-Fa-f]{64})$/.test(hash)) { + const receipt = await web3.eth.getTransactionReceipt(hash); + if (receipt) { + return receipt; + } + console.log("Invalid transaction-hash"); + } else if (hash) { + console.log("Illegal transaction-hash"); + } else { + return null; + } + } +}; + +const send = async (web3, account, gasPrice, transaction, value = 0) => { + while (true) { + try { + const gasEstimate = await transaction.estimateGas({ from: account.address, value: value }); + console.log("gasEstimate: " + gasEstimate, " - value - ", value); + const tx = { + to: transaction._parent._address, + data: transaction.encodeABI(), + gas: Math.max(await transaction.estimateGas({ from: account.address, value: value }), MIN_GAS_LIMIT), + gasPrice: gasPrice || (await getGasPrice(web3)), + chainId: await web3.eth.net.getId(), + value: value, + }; + const signed = await web3.eth.accounts.signTransaction(tx, account.privateKey); + const receipt = await web3.eth.sendSignedTransaction(signed.rawTransaction); + return receipt; + } catch (error) { + console.log(error.message); + const receipt = await getTransactionReceipt(web3); + if (receipt) { + return receipt; + } + } + } +}; + +const deploy = async (web3, account, gasPrice, contractId, contractName, contractArgs) => { + if (getConfig()[contractId] === undefined || contractId === "Oracle") { + const buildFile = JSON.parse(fs.readFileSync(path.join(ARTIFACTS_DIR, contractName + ".json"), { encoding: "utf8" })); + + const contract = new web3.eth.Contract(buildFile.abi); + const options = { data: buildFile.bytecode, arguments: contractArgs }; + const transaction = contract.deploy(options); + const receipt = await send(web3, account, gasPrice, transaction); + const args = transaction.encodeABI().slice(options.data.length); + console.log(`${contractId} deployed at ${receipt.contractAddress}`); + setConfig({ [contractId]: { name: contractName, addr: receipt.contractAddress, args: args } }); + } + return deployed(web3, contractName, getConfig()[contractId].addr); +}; + +const deployed = (web3, contractName, contractAddr) => { + const buildFile = JSON.parse(fs.readFileSync(path.join(ARTIFACTS_DIR, contractName + ".json"), { encoding: "utf8" })); + return new web3.eth.Contract(buildFile.abi, contractAddr); +}; + +const decimalToInteger = (value, decimals) => { + const parts = [...value.split("."), ""]; + return parts[0] + parts[1].padEnd(decimals, "0"); +}; + +const percentageToPPM = (value) => { + return decimalToInteger(value.replace("%", ""), 4); +}; + +const addConverter = async (tokenOracleName, oracleMockName, oracleMockValue, oracleMockHas) => { + const web3 = new Web3(NODE_ADDRESS); + + const gasPrice = await getGasPrice(web3); + const account = web3.eth.accounts.privateKeyToAccount(PRIVATE_KEY); + console.log("account: ", account); + const web3Func = (func, ...args) => func(web3, account, gasPrice, ...args); + + const addresses = { ETH: Web3.utils.toChecksumAddress("0x".padEnd(42, "e")) }; + const tokenDecimals = { ETH: 18 }; + + let phase = 0; + if (getConfig().phase === undefined) { + setConfig({ phase }); + } + + const execute = async (transaction, ...args) => { + if (getConfig().phase === phase++) { + await web3Func(send, transaction, ...args); + console.log(`phase ${phase} executed`); + setConfig({ phase }); + } + }; + + const converterRegistry = await deployed(web3, "ConverterRegistry", getData().converterRegistry.addr); + const oracleWhitelist = await deployed(web3, "Whitelist", getData().oracleWhitelist.addr); + + let multiSigWallet; + if (getData().multiSigWallet.addr !== "") multiSigWallet = deployed(web3, getData().multiSigWallet.name, getData().multiSigWallet.addr); + + //this block is just relevant for v2 pools + let underlyingOracleAddress = []; + if (oracleMockName != undefined) { + //if underlying address is defined, use it + if (getConfig().underlyingOracleAddress !== undefined) { + underlyingOracleAddress = getConfig().underlyingOracleAddress; + } + //else deploy a mockup + else { + console.log("deploying a mockup"); + const oracleMock = await web3Func(deploy, oracleMockName, oracleMockName, []); + underlyingOracleAddress = oracleMock._address; + if (oracleMockName != undefined) { + await execute(oracleMock.methods.setValue(oracleMockValue)); + } + if (oracleMockHas != undefined) { + await execute(oracleMock.methods.setHas(oracleMockHas)); + } + const tokenOracle = await web3Func(deploy, tokenOracleName, tokenOracleName, [underlyingOracleAddress]); + } + } + + //read reserve data from the config or deploy new tokens if not defined + for (const reserve of getConfig().reserves) { + if (reserve.address) { + addresses[reserve.symbol] = reserve.address; + tokenDecimals[reserve.symbol] = reserve.decimals; + setConfig({ [reserve.symbol]: { name: reserve.symbol, addr: reserve.address } }); + } else { + t = await web3Func(deploy, reserve.symbol, "ERC20Token", [ + reserve.symbol, + reserve.symbol, + reserve.decimals, + decimalToInteger("10000", reserve.decimals), + ]); + tokenDecimals[reserve.symbol] = reserve.decimals; + addresses[reserve.symbol] = t._address; + } + } + + for (const converter of getConfig().converters) { + const type = converter.type; + const name = converter.symbol + (type == 0 ? " Liquid Token" : " Liquidity Pool"); + const symbol = converter.symbol; + const decimals = converter.decimals; + const fee = percentageToPPM(converter.fee); + + const tokens = converter.reserves.map((reserve) => addresses[reserve.symbol]); + const weights = converter.reserves.map((reserve) => percentageToPPM(reserve.weight)); + const amounts = converter.reserves.map((reserve) => decimalToInteger(reserve.balance, tokenDecimals[reserve.symbol])); + const value = 0; // amounts[converter.reserves.findIndex(reserve => reserve.symbol === 'RBTC')]; + + console.log("Deploying converter for ", type, " - ", name, " with value ", value); + if (getConfig()["phase"] > 0) console.log(`Restarting from phase #${getConfig()["phase"]}`); + + let newConverter; + //if the script breaks during execution, run it again, it will resume from the point of failure automagically + if (getConfig()["phase"] < 2) { + newConverter = await converterRegistry.methods.newConverter(type, name, symbol, decimals, "1000000", tokens, weights).call(); + } else { + newConverter = getConfig()[`newLiquidityPoolV${type}Converter`].addr; + console.log("Using previously created converter ", newConverter); + } + + await execute(converterRegistry.methods.newConverter(type, name, symbol, decimals, "1000000", tokens, weights)); + await execute(converterRegistry.methods.setupConverter(type, tokens, weights, newConverter)); + console.log("New Converter is ", newConverter); + setConfig({ [`newLiquidityPoolV${type}Converter`]: { name: `LiquidityPoolV${type}Converter`, addr: newConverter, args: "" } }); + + console.log("Calling anchors"); + console.log(await converterRegistry.methods.getAnchors().call()); + + const anchor = deployed(web3, "IConverterAnchor", (await converterRegistry.methods.getAnchors().call()).slice(-1)[0]); + + // TODO: Remove next line, just here for checking which address is received from anchor. The last address shown from above anchor list should be shown. + console.log("Anchor Taken: ", anchor._address) + + const converterBase = deployed(web3, "ConverterBase", newConverter); + + console.log("Now executing the settings on " + converterBase._address); + await execute(converterBase.methods.acceptOwnership()); + console.log("Done with ownership acceptance"); + await execute(converterBase.methods.setConversionFee(fee)); + console.log("Done with conversion fee"); + + //adding the liquidity and thereby seeting the price + if (type !== 0 && amounts.every((amount) => amount > 0)) { + for (let i = 0; i < converter.reserves.length; i++) { + const reserve = converter.reserves[i]; + + console.log("Approving amount for ERC20Token: " + amounts[i]); + await execute(deployed(web3, "ERC20Token", tokens[i]).methods.approve(converterBase._address, amounts[i])); + let availableBalance = await deployed(web3, "ERC20Token", tokens[i]).methods.balanceOf(account.address).call(); + console.log("available balance: "); + console.log(availableBalance); + + if (type == 2) { + if (!reserve.oracle) { + const oracleName = reserve.symbol === "RBTC" ? "MocBTCToUSDOracle" : tokenOracleName; + //mocMedianizerMockUSDtoBTC is actually returning BTCtoUSD + const mocOracleArgs = + oracleName === "MocBTCToUSDOracle" ? [getData().mocMedianizerMockUSDtoBTC.addr] : [underlyingOracleAddress]; + const mocPriceOracle = await web3Func( + deploy, + "mocPriceOracle" + converter.symbol + reserve.symbol, + oracleName, + mocOracleArgs + ); + reserve.oracle = mocPriceOracle._address; + } + console.log("reserve.oracle", reserve.oracle); + await execute(oracleWhitelist.methods.addAddress(reserve.oracle)); + } + } + + if (type == 1) { + console.log("adding liquidity"); + console.log("tokens:"); + console.log(tokens); + console.log("amounts:"); + console.log(amounts); + console.log("converterBase._address:"); + console.log(converterBase._address); + await execute(deployed(web3, "LiquidityPoolV1Converter", converterBase._address).methods.addLiquidity(tokens, amounts, 1), value); + } else if (type == 2) { + const deployedConverter = deployed(web3, "LiquidityPoolV2Converter", converterBase._address); + await execute(deployedConverter.methods.activate(tokens[0], converter.reserves[0].oracle, converter.reserves[1].oracle)); + + for (let i = 0; i < converter.reserves.length; i++) { + console.log("Adding liquidity for LiquidityPoolV2Converter. ", "For token: ", tokens[i], " with amount ", amounts[i]); + await execute(deployedConverter.methods.addLiquidity(tokens[i], amounts[i], 1), value); + console.log("Liquidity added"); + } + } + } + + addresses[converter.symbol] = anchor._address; + } + + console.log("All done"); + + if (web3.currentProvider.constructor.name === "WebsocketProvider") { + web3.currentProvider.connection.close(); + } +}; + +if (TOKEN_NAME === "BPro") { + addConverter("BProOracle", "MoCStateMock", "20000000000000000000000"); +} else if (TOKEN_NAME === "USDT") { + addConverter("MocBTCToBTCOracle"); +} else { + addConverter(); +} From 7326baa7bfddea957b4ec3675ecb350166ad0f77 Mon Sep 17 00:00:00 2001 From: Tyrone Johnson Date: Thu, 25 Nov 2021 18:04:13 +0300 Subject: [PATCH 19/24] fixed token symbol --- .../utils/{addBZX_testnet.json => addBRZ_testnet.json} | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) rename solidity/utils/{addBZX_testnet.json => addBRZ_testnet.json} (81%) diff --git a/solidity/utils/addBZX_testnet.json b/solidity/utils/addBRZ_testnet.json similarity index 81% rename from solidity/utils/addBZX_testnet.json rename to solidity/utils/addBRZ_testnet.json index c5c6c2d..bce4a38 100644 --- a/solidity/utils/addBZX_testnet.json +++ b/solidity/utils/addBRZ_testnet.json @@ -6,7 +6,7 @@ "address": "0x849d38abd3962cb40d4887e4279ad0e4e5958e34" }, { - "symbol": "BZX", + "symbol": "BRZ", "decimals": 18, "address": "0xe355c280131dfaf18bf1c3648aee3c396db6b5fd" } @@ -14,7 +14,7 @@ "converters": [ { "type": 1, - "symbol": "XUSD/BZX", + "symbol": "XUSD/BRZ", "decimals": 18, "fee": "0.3%", "reserves": [ @@ -24,13 +24,14 @@ "balance": "0" }, { - "symbol": "BZX", + "symbol": "BRZ", "weight": "50%", "balance": "0" } ] } ], + "ALERT": "THIS PAIR IS NOT wRBTC BASED, 'K' AND 'btcAddress below are not used", "k": 6779, "btcAddress": "0x69FE5cEC81D5eF92600c1A0dB1F11986AB3758Ab" } \ No newline at end of file From 1aa1fd1f9927d234004bd9611f735b1888034f69 Mon Sep 17 00:00:00 2001 From: Tyrone Johnson Date: Thu, 25 Nov 2021 23:00:54 +0300 Subject: [PATCH 20/24] fixed BRZ decimals --- solidity/utils/addBRZ_testnet.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/solidity/utils/addBRZ_testnet.json b/solidity/utils/addBRZ_testnet.json index bce4a38..f9d4f93 100644 --- a/solidity/utils/addBRZ_testnet.json +++ b/solidity/utils/addBRZ_testnet.json @@ -7,7 +7,7 @@ }, { "symbol": "BRZ", - "decimals": 18, + "decimals": 4, "address": "0xe355c280131dfaf18bf1c3648aee3c396db6b5fd" } ], From 43c713a32698f22063e9d90ef46b1c09e965d104 Mon Sep 17 00:00:00 2001 From: Tyrone Johnson Date: Mon, 29 Nov 2021 13:22:39 +0300 Subject: [PATCH 21/24] added funding amounts for the testnet --- solidity/utils/addBRZ_testnet.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/solidity/utils/addBRZ_testnet.json b/solidity/utils/addBRZ_testnet.json index f9d4f93..d6a72ce 100644 --- a/solidity/utils/addBRZ_testnet.json +++ b/solidity/utils/addBRZ_testnet.json @@ -21,12 +21,12 @@ { "symbol": "XUSD", "weight": "50%", - "balance": "0" + "balance": "90" }, { "symbol": "BRZ", "weight": "50%", - "balance": "0" + "balance": "500" } ] } From 42c2da8437568c061753863efab83f92557fe252 Mon Sep 17 00:00:00 2001 From: Tyrone Johnson Date: Tue, 30 Nov 2021 15:31:39 +0300 Subject: [PATCH 22/24] added XUSD/BRZ converter & manual updated --- ADD-POOLS.md | 35 ++++++++++++++++++++++++------ solidity/utils/addBRZ_testnet.json | 24 +++++++++++++++----- 2 files changed, 47 insertions(+), 12 deletions(-) diff --git a/ADD-POOLS.md b/ADD-POOLS.md index dc98bc0..74ce7ce 100644 --- a/ADD-POOLS.md +++ b/ADD-POOLS.md @@ -80,12 +80,27 @@ The configuration file is updated during the process, in order to allow resuming ### Adding LM pools to the testnet and mainnet (only needed if contracts' abi were changed) -1. Before adding pools we need to make sure having updated comipled contracts in [./solidity/build](./solidity/build) - - Change contract folder in script Compile contracts `../../scripts/compile.sh` - - Run from root dir `./scripts/compile.sh` -2. Top up RBTC and WRBTC account with some RBTC to pay for tx and **WRBTC** amount for initial deposit (0.01 usually) +1. Use ```yarn install``` or ```npm install``` from the root to install node modules +2. Before adding pools we need to make sure having updated compiled contracts in [./solidity/build/contracts](./solidity/build/contracts) + - Run from root dir ```truffle compile``` +3. Top up deploying account with RBTC to pay tx fees and pair tokens for initial deposit if it is not zero - at least `balance` amounts in config file, e.g. 18 XUSD and 100 BRZ: + ``` + "reserves": [ + { + "symbol": "XUSD", + "weight": "50%", + "balance": "18" + }, + { + "symbol": "BRZ", + "weight": "50%", + "balance": "100" + } + ] + ``` + * For WRBTC-paired tokens **WRBTC** amount for initial deposit is usually 0.01 -To add converters to an existing swap network, use ```addConverter.js```. +To add converters to an existing swap network, use ```addConverter.js``` or ```addConverterNoOracle.js```. Example creation v1 pool WRBTC/ETH @@ -93,11 +108,17 @@ Note: `data_testnet.json` and `data_mainnet.json` store contracts addresses part testnet: -```node addConverter.js ETH addETHs_testnet.json data_testnet.json https://public-node.testnet.rsk.co ``` +```node addConverter.js ETH addETHs_testnet.json data_testnet.json https://public-node.testnet.rsk.co ``` + +for pairs with no WRBTC (with no internal oracle): + +```node addConverterNoOracle.js ETH addBRZ_testnet.json data_testnet.json https://public-node.testnet.rsk.co ``` mainnet: -```node addConverter.js ETH addETHs_mainnet.json data_mainnet.json https://mainnet2.sovryn.app/rpc ``` +```node addConverter.js ETH addETHs_mainnet.json data_mainnet.json https://mainnet2.sovryn.app/rpc ``` + or respectively +```node addConverterNoOracle.js ETH addBRZ_testnet.json data_testnet.json https://public-node.testnet.rsk.co ``` ```TODO: check if the following is for v2 pools only``` diff --git a/solidity/utils/addBRZ_testnet.json b/solidity/utils/addBRZ_testnet.json index d6a72ce..4ad12ac 100644 --- a/solidity/utils/addBRZ_testnet.json +++ b/solidity/utils/addBRZ_testnet.json @@ -3,7 +3,7 @@ { "symbol": "XUSD", "decimals": 18, - "address": "0x849d38abd3962cb40d4887e4279ad0e4e5958e34" + "address": "0x74858FE37d391f81F89472e1D8BC8Ef9CF67B3b1" }, { "symbol": "BRZ", @@ -21,17 +21,31 @@ { "symbol": "XUSD", "weight": "50%", - "balance": "90" + "balance": "18" }, { "symbol": "BRZ", "weight": "50%", - "balance": "500" + "balance": "100" } ] } ], - "ALERT": "THIS PAIR IS NOT wRBTC BASED, 'K' AND 'btcAddress below are not used", + "ALERT": "THIS PAIR IS NOT wRBTC BASED - NO INTERNAL ORACLE - 'K' AND 'btcAddress below are not used", "k": 6779, - "btcAddress": "0x69FE5cEC81D5eF92600c1A0dB1F11986AB3758Ab" + "btcAddress": "0x69FE5cEC81D5eF92600c1A0dB1F11986AB3758Ab", + "phase": 7, + "XUSD": { + "name": "XUSD", + "addr": "0x74858FE37d391f81F89472e1D8BC8Ef9CF67B3b1" + }, + "BRZ": { + "name": "BRZ", + "addr": "0xe355c280131dfaf18bf1c3648aee3c396db6b5fd" + }, + "newLiquidityPoolV1Converter": { + "name": "LiquidityPoolV1Converter", + "addr": "0x6Ca500A8F39C452CE7533AA320c9b7752F04AA64", + "args": "" + } } \ No newline at end of file From 929fca7e597eb44a84c0558a552a4c3a9740b4f3 Mon Sep 17 00:00:00 2001 From: Tyrone Johnson <77393391+tjcloa@users.noreply.github.com> Date: Fri, 13 May 2022 20:24:47 +0300 Subject: [PATCH 23/24] fix wss://testnet.sovryn.app/ws URI MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit wss://testnet.sovryn.app/ws -> wss://testnet.sovryn.app/websocket --- rbtcwrapperproxy/truffle-config.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/rbtcwrapperproxy/truffle-config.js b/rbtcwrapperproxy/truffle-config.js index 430c67e..9dec249 100644 --- a/rbtcwrapperproxy/truffle-config.js +++ b/rbtcwrapperproxy/truffle-config.js @@ -59,7 +59,7 @@ module.exports = { // options below to some value. // testnet: { - provider: () => new HDWalletProvider(privateKey, "wss://testnet.sovryn.app/ws"), + provider: () => new HDWalletProvider(privateKey, "wss://testnet.sovryn.app/websocket"), network_id: 31, gasPrice: 95000010, skipDryRun: true, From 695f17393cd35692c0e5aba1b2b083095d6831eb Mon Sep 17 00:00:00 2001 From: Tyrone Johnson Date: Wed, 18 May 2022 03:01:43 +0400 Subject: [PATCH 24/24] update XUSD address in XUSD/BRZ converter config --- ADD-POOLS.md | 10 ++++++---- solidity/utils/addBRZ_testnet.json | 10 +++++----- 2 files changed, 11 insertions(+), 9 deletions(-) diff --git a/ADD-POOLS.md b/ADD-POOLS.md index 74ce7ce..e54fa84 100644 --- a/ADD-POOLS.md +++ b/ADD-POOLS.md @@ -84,7 +84,7 @@ The configuration file is updated during the process, in order to allow resuming 2. Before adding pools we need to make sure having updated compiled contracts in [./solidity/build/contracts](./solidity/build/contracts) - Run from root dir ```truffle compile``` 3. Top up deploying account with RBTC to pay tx fees and pair tokens for initial deposit if it is not zero - at least `balance` amounts in config file, e.g. 18 XUSD and 100 BRZ: - ``` + ```js "reserves": [ { "symbol": "XUSD", @@ -96,7 +96,9 @@ The configuration file is updated during the process, in order to allow resuming "weight": "50%", "balance": "100" } - ] + ], + "k": 6779, + "btcAddress": "0x69FE5cEC81D5eF92600c1A0dB1F11986AB3758Ab", ``` * For WRBTC-paired tokens **WRBTC** amount for initial deposit is usually 0.01 @@ -112,13 +114,13 @@ testnet: for pairs with no WRBTC (with no internal oracle): -```node addConverterNoOracle.js ETH addBRZ_testnet.json data_testnet.json https://public-node.testnet.rsk.co ``` +```node addConverterNoOracle.js BRZ addBRZ_testnet.json data_testnet.json https://public-node.testnet.rsk.co ``` mainnet: ```node addConverter.js ETH addETHs_mainnet.json data_mainnet.json https://mainnet2.sovryn.app/rpc ``` or respectively -```node addConverterNoOracle.js ETH addBRZ_testnet.json data_testnet.json https://public-node.testnet.rsk.co ``` +```node addConverterNoOracle.js BRZ addBRZ_testnet.json data_testnet.json https://public-node.testnet.rsk.co ``` ```TODO: check if the following is for v2 pools only``` diff --git a/solidity/utils/addBRZ_testnet.json b/solidity/utils/addBRZ_testnet.json index 4ad12ac..323d801 100644 --- a/solidity/utils/addBRZ_testnet.json +++ b/solidity/utils/addBRZ_testnet.json @@ -3,7 +3,7 @@ { "symbol": "XUSD", "decimals": 18, - "address": "0x74858FE37d391f81F89472e1D8BC8Ef9CF67B3b1" + "address": "0xa9262CC3fB54Ea55B1B0af00EfCa9416B8d59570" }, { "symbol": "BRZ", @@ -21,12 +21,12 @@ { "symbol": "XUSD", "weight": "50%", - "balance": "18" + "balance": "100" }, { "symbol": "BRZ", "weight": "50%", - "balance": "100" + "balance": "495" } ] } @@ -37,7 +37,7 @@ "phase": 7, "XUSD": { "name": "XUSD", - "addr": "0x74858FE37d391f81F89472e1D8BC8Ef9CF67B3b1" + "addr": "0xa9262CC3fB54Ea55B1B0af00EfCa9416B8d59570" }, "BRZ": { "name": "BRZ", @@ -45,7 +45,7 @@ }, "newLiquidityPoolV1Converter": { "name": "LiquidityPoolV1Converter", - "addr": "0x6Ca500A8F39C452CE7533AA320c9b7752F04AA64", + "addr": "0x3378E4dc28c862E71E9c097C12305513B3cCc6B9", "args": "" } } \ No newline at end of file