From 7f6bd61f2b133b76ff91dc949bbaa9cc98883199 Mon Sep 17 00:00:00 2001 From: rachit2501 Date: Sun, 26 Sep 2021 20:55:11 +0530 Subject: [PATCH 01/15] fixes --- contract/bridge/migrations/2_deploy_onebtc.js | 4 +- contract/bridge/scripts/sla.js | 0 .../bridge/test/ExchangeRateOracle.test.js | 66 ++++++++++++++----- contract/bridge/test/exchangeRateOracle.js | 22 ------- contract/bridge/test/sla.js | 22 +++++++ contract/bridge/truffle-config.js | 34 +++++----- 6 files changed, 88 insertions(+), 60 deletions(-) create mode 100644 contract/bridge/scripts/sla.js delete mode 100644 contract/bridge/test/exchangeRateOracle.js create mode 100644 contract/bridge/test/sla.js diff --git a/contract/bridge/migrations/2_deploy_onebtc.js b/contract/bridge/migrations/2_deploy_onebtc.js index a7f012f..1cc95a4 100644 --- a/contract/bridge/migrations/2_deploy_onebtc.js +++ b/contract/bridge/migrations/2_deploy_onebtc.js @@ -1,9 +1,9 @@ const OneBtc = artifacts.require("OneBtc"); const RelayMock = artifacts.require("RelayMock"); -module.exports = async function(deployer) { +module.exports = async function (deployer) { const IRelay = await RelayMock.deployed(); await deployer.deploy(OneBtc, IRelay.address); const c = await OneBtc.deployed(); - console.log(c.address) + console.log(c.address); }; diff --git a/contract/bridge/scripts/sla.js b/contract/bridge/scripts/sla.js new file mode 100644 index 0000000..e69de29 diff --git a/contract/bridge/test/ExchangeRateOracle.test.js b/contract/bridge/test/ExchangeRateOracle.test.js index 7a8a049..64c4fe1 100644 --- a/contract/bridge/test/ExchangeRateOracle.test.js +++ b/contract/bridge/test/ExchangeRateOracle.test.js @@ -1,7 +1,9 @@ const BN = require("bn.js"); const { expectRevert } = require("@openzeppelin/test-helpers"); const { web3 } = require("@openzeppelin/test-helpers/src/setup"); -const ExchangeRateOracleWrapper = artifacts.require("ExchangeRateOracleWrapper"); +const ExchangeRateOracleWrapper = artifacts.require( + "ExchangeRateOracleWrapper" +); web3.extend({ property: "miner", @@ -22,17 +24,24 @@ web3.extend({ contract("ExchangeRateOracle unit test", (accounts) => { before(async function () { this.ExchangeRateOracleWrapper = await ExchangeRateOracleWrapper.new(); - + this.authorizedOracle = accounts[1]; - this.unauthorizedOracle = accounts[2] + this.unauthorizedOracle = accounts[2]; }); - it ("add authorized oracle", async function () { - await this.ExchangeRateOracleWrapper.addAuthorizedOracle(this.authorizedOracle); + it("add authorized oracle", async function () { + await this.ExchangeRateOracleWrapper.addAuthorizedOracle( + this.authorizedOracle + ); - let isAuthorizedOracle = await this.ExchangeRateOracleWrapper.authorizedOracles(this.authorizedOracle); + let isAuthorizedOracle = + await this.ExchangeRateOracleWrapper.authorizedOracles( + this.authorizedOracle + ); assert.equal(isAuthorizedOracle, true); - isAuthorizedOracle = await this.ExchangeRateOracleWrapper.authorizedOracles(this.unauthorizedOracle); + isAuthorizedOracle = await this.ExchangeRateOracleWrapper.authorizedOracles( + this.unauthorizedOracle + ); assert.equal(isAuthorizedOracle, false); }); @@ -42,10 +51,16 @@ contract("ExchangeRateOracle unit test", (accounts) => { assert.equal(exchangeRate, 0); // set exchange rate to 100 - const req = await this.ExchangeRateOracleWrapper.setExchangeRate(this.authorizedOracle, 100); + const req = await this.ExchangeRateOracleWrapper.setExchangeRate( + this.authorizedOracle, + 100 + ); // check exchange rate, reverted with `ERR_INVALID_ORACLE_SOURCE` due to the MAX_DELAY limit - await expectRevert(this.ExchangeRateOracleWrapper.getExchangeRate(), 'ERR_MISSING_EXCHANGE_RATE'); + await expectRevert( + this.ExchangeRateOracleWrapper.getExchangeRate(), + "ERR_MISSING_EXCHANGE_RATE" + ); // increase time await web3.miner.incTime(Number(1001)); // MAX_DELAY = 1000 @@ -60,43 +75,58 @@ contract("ExchangeRateOracle unit test", (accounts) => { }); it("Error on setExchange with unauthorizedOracle", async function () { - await expectRevert(this.ExchangeRateOracleWrapper.setExchangeRate(this.unauthorizedOracle, 200), 'ERR_INVALID_ORACLE_SOURCE'); + await expectRevert( + this.ExchangeRateOracleWrapper.setExchangeRate( + this.unauthorizedOracle, + 200 + ), + "ERR_INVALID_ORACLE_SOURCE" + ); }); it("setSatoshiPerBytes", async function () { - const req = await this.ExchangeRateOracleWrapper.setSatoshiPerBytes(5, 10, { from: this.authorizedOracle }); + const req = await this.ExchangeRateOracleWrapper.setSatoshiPerBytes(5, 10, { + from: this.authorizedOracle, + }); const event = req.logs.filter((log) => log.event == "SetSatoshiPerByte")[0]; assert.equal(event.args.fee, 5); assert.equal(event.args.inclusionEstimate, 10); }); it("Error on setSatoshiPerBytes with unauthorizedOracle", async function () { - await expectRevert(this.ExchangeRateOracleWrapper.setSatoshiPerBytes(5, 10, { from: this.unauthorizedOracle }), 'ERR_INVALID_ORACLE_SOURCE'); + await expectRevert( + this.ExchangeRateOracleWrapper.setSatoshiPerBytes(5, 10, { + from: this.unauthorizedOracle, + }), + "ERR_INVALID_ORACLE_SOURCE" + ); }); it("collateralToWrapped", async function () { const amount = 10000; - const collateralToWrapped = await this.ExchangeRateOracleWrapper.collateralToWrapped(amount); - + const collateralToWrapped = + await this.ExchangeRateOracleWrapper.collateralToWrapped(amount); + // increase time and get exchange rate await web3.miner.incTime(Number(1001)); // MAX_DELAY = 1000 await web3.miner.mine(); const exchangeRate = await this.ExchangeRateOracleWrapper.getExchangeRate(); // check collateralToWrapped - assert.equal(collateralToWrapped, amount/exchangeRate) + assert.equal(collateralToWrapped, amount / exchangeRate); }); it("wrappedToCollateral", async function () { const amount = 10; - const wrappedToCollateral = await this.ExchangeRateOracleWrapper.wrappedToCollateral(amount); - + const wrappedToCollateral = + await this.ExchangeRateOracleWrapper.wrappedToCollateral(amount); + // increase time and get exchange rate await web3.miner.incTime(Number(1001)); // MAX_DELAY = 1000 await web3.miner.mine(); const exchangeRate = await this.ExchangeRateOracleWrapper.getExchangeRate(); // check collateralToWrapped - assert.equal(wrappedToCollateral, amount*exchangeRate) + assert.equal(wrappedToCollateral, amount * exchangeRate); }); }); diff --git a/contract/bridge/test/exchangeRateOracle.js b/contract/bridge/test/exchangeRateOracle.js deleted file mode 100644 index 62b3993..0000000 --- a/contract/bridge/test/exchangeRateOracle.js +++ /dev/null @@ -1,22 +0,0 @@ -const exchangeRate = artifacts.require("ExchangeRateOracle") - -contract("ExchangeRateOracle",(account)=>{ - let contractInstance; - before(()=>{ - contractInstance = await exchangeRate.new(); - }) - it("setExchangeRate()", async ()=>{ - await contractInstance.setExchangeRate("0x5B38Da6a701c568545dCfcB03FcB875f56beddC4",10); - const exchangeRate = await contractInstance.getExchangeRate(); - - assert.equal(exchangeRate, 10); - }) - it("collateralToWrapped", ()=>{ - const rate = await contractInstance.collateralToWrapped(1000) - assert.equal(rate, 100) - }) - it("wrapped To collateral", ()=>{ - const rate = await contractInstance.wrappedToCollateral(1000) - assert.equal(rate, 10000) - }) -}) diff --git a/contract/bridge/test/sla.js b/contract/bridge/test/sla.js new file mode 100644 index 0000000..767fa76 --- /dev/null +++ b/contract/bridge/test/sla.js @@ -0,0 +1,22 @@ +const SLA = artifacts.require("SLA"); + +contract("SLA", (account) => { + let contractInstance; + before(async () => { + contractInstance = await SLA.new(); + }); + it("_depositSlaChange()", async () => { + await contractInstance._depositSlaChange(10); + const SLA = await contractInstance.getSLA(); + + assert.equal(SLA, 10); + }); + it("collateralToWrapped", async () => { + const rate = await contractInstance.collateralToWrapped(1000); + assert.equal(rate, 100); + }); + it("wrapped To collateral", async () => { + const rate = await contractInstance.wrappedToCollateral(1000); + assert.equal(rate, 10000); + }); +}); diff --git a/contract/bridge/truffle-config.js b/contract/bridge/truffle-config.js index fa7c9ac..1bd6fc3 100644 --- a/contract/bridge/truffle-config.js +++ b/contract/bridge/truffle-config.js @@ -33,38 +33,35 @@ module.exports = { networks: { test: { - host: 'localhost', - port: 7545, - network_id: '5777', + host: "localhost", + port: 9545, + network_id: "5777", // gas: 4712388 // host: "127.0.0.1", // port: 8545, // network_id: '*', - accounts: 5, - defaultEtherBalance: 500, - blockTime: 0 }, local: { - host: 'localhost', + host: "localhost", port: 7545, - network_id: '5777', + network_id: "5777", // gas: 4712388 // host: "127.0.0.1", // port: 8545, // network_id: '*', accounts: 5, defaultEtherBalance: 500, - blockTime: 0 + blockTime: 0, }, develop: { host: "127.0.0.1", port: 8545, - network_id: '*', + network_id: "*", accounts: 5, defaultEtherBalance: 500, - blockTime: 0 + blockTime: 0, }, }, @@ -76,14 +73,15 @@ module.exports = { // Configure your compilers compilers: { solc: { - version: "0.6.12+commit.27d51765", // Fetch exact version from solc-bin (default: truffle's version) - settings: { // See the solidity docs for advice about optimization and evmVersion + version: "0.6.12+commit.27d51765", // Fetch exact version from solc-bin (default: truffle's version) + settings: { + // See the solidity docs for advice about optimization and evmVersion optimizer: { enabled: true, - runs: 200 + runs: 200, }, - // evmVersion: "byzantium" - } - } - } + // evmVersion: "byzantium", + }, + }, + }, }; From b4563655a90b7448e80318114a160009e37c2256 Mon Sep 17 00:00:00 2001 From: rachit2501 Date: Mon, 27 Sep 2021 03:00:49 +0530 Subject: [PATCH 02/15] sla contract --- contract/bridge/contracts/SLA.sol | 32 +++++++++++++++++-- contract/bridge/contracts/test/SlaWrapper.sol | 7 ++++ 2 files changed, 37 insertions(+), 2 deletions(-) create mode 100644 contract/bridge/contracts/test/SlaWrapper.sol diff --git a/contract/bridge/contracts/SLA.sol b/contract/bridge/contracts/SLA.sol index d9e7e7a..250dd88 100644 --- a/contract/bridge/contracts/SLA.sol +++ b/contract/bridge/contracts/SLA.sol @@ -2,7 +2,12 @@ pragma solidity ^0.6.12; +import "@openzeppelin/contracts/utils/math/SafeMath.sol"; + contract SLA { + + using SafeMath for uint256; + event UpdateVaultSLA( address indexed vaultId, uint256 boundedNewSla, @@ -51,6 +56,7 @@ contract SLA { mapping(address => SlaData) VaultSLA; mapping(address => SlaData) StakedRelayerSLA; + mapping(address => bool) VaultTrue; function _executeIssueSlaChange(uint256 amount) private returns (uint256) { uint256 count = TotalIssueCount + 1; @@ -145,7 +151,29 @@ contract SLA { emit UpdateVaultSLA(vaultId, boundedNewSla, int256(deltaSla)); } - function SlashVault(address account) internal returns (uint256) {} + function SlashVault(address account) internal returns (uint256) { + SlaData vault = VaultSLA[account]; + uint256 slaTarget = vault.vaultTargetSla; + uint256 sla = vaule.sla; + uint256 liquidateThreshold = vault.liquidate; + uint256 premiumRedeemThreshold = vault.vaultRedeemFailure; - function updateSLA(address account, uint256 delta) internal {} + uint256 realSlashed = premiumRedeemThreshold.sub(liquidateThreshold).div(slaTarget).mul(sla).add(liquidateThreshold); + + return realSlashed; + } + + function updateSLA(address account, int256 delta) internal { + SlaData storage vault; + if(VaultTrue[address]){ + vault = VaultSLA[address]; + vault.sla = int256(vault).sla + delta; + UpdateVaultSLA(account, vault.sla, delta); + } + else { + vault = StakedRelayerSLA[address]; + vault.sla = int256(vault).sla + delta; + UpdateRelayerSLA(account, vault.sla, delta); + } + } } diff --git a/contract/bridge/contracts/test/SlaWrapper.sol b/contract/bridge/contracts/test/SlaWrapper.sol new file mode 100644 index 0000000..746bd05 --- /dev/null +++ b/contract/bridge/contracts/test/SlaWrapper.sol @@ -0,0 +1,7 @@ +pragma solidity ^0.6.12; + +import {SLA} from "../SLA.sol"; + +contract SLAWrapper is SLA { + +} From de0342629c00f2f7c92917b672a0c9e7758b3e60 Mon Sep 17 00:00:00 2001 From: rachit2501 Date: Mon, 27 Sep 2021 03:07:13 +0530 Subject: [PATCH 03/15] sla wrapper --- contract/bridge/contracts/test/SlaWrapper.sol | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/contract/bridge/contracts/test/SlaWrapper.sol b/contract/bridge/contracts/test/SlaWrapper.sol index 746bd05..eae6d85 100644 --- a/contract/bridge/contracts/test/SlaWrapper.sol +++ b/contract/bridge/contracts/test/SlaWrapper.sol @@ -3,5 +3,12 @@ pragma solidity ^0.6.12; import {SLA} from "../SLA.sol"; contract SLAWrapper is SLA { - + function slashVaultTest (address account) public returns (uint256){ + uint256 slashAmount = SlashVault(account); + return slashAmount; + } + + function updateSlaTes (address account, int256 delta) internal { + updateSLA(account, delta); + } } From 2a0ac7716c9c2c40424730ddc791cc45fbfab5f4 Mon Sep 17 00:00:00 2001 From: rachit2501 Date: Mon, 1 Nov 2021 16:43:25 +0530 Subject: [PATCH 04/15] sla functions --- contract/bridge/contracts/SLA.sol | 83 ++++++++++++++++++++++++++++--- 1 file changed, 76 insertions(+), 7 deletions(-) diff --git a/contract/bridge/contracts/SLA.sol b/contract/bridge/contracts/SLA.sol index 250dd88..eba1bf7 100644 --- a/contract/bridge/contracts/SLA.sol +++ b/contract/bridge/contracts/SLA.sol @@ -58,6 +58,16 @@ contract SLA { mapping(address => SlaData) StakedRelayerSLA; mapping(address => bool) VaultTrue; + + /* + - adjust stake + - liquidate stake + - calculate slashed amount + - fixed point unsigned to signed + - wrapper to uint128 + - currency to fixed point + */ + function _executeIssueSlaChange(uint256 amount) private returns (uint256) { uint256 count = TotalIssueCount + 1; TotalIssueCount = count; @@ -97,7 +107,7 @@ contract SLA { // TODO //Self::liquidateStake::(vaultId)?; //Self::liquidateStake::(vaultId)?; - revert("TODO"); + // revert("TODO"); SlaData storage slaData = VaultSLA[vaultId]; int256 deltaSla = -int256(slaData.sla); slaData.sla = 0; @@ -151,7 +161,47 @@ contract SLA { emit UpdateVaultSLA(vaultId, boundedNewSla, int256(deltaSla)); } - function SlashVault(address account) internal returns (uint256) { + + function eventUpdateRelayerSla( + address relayerId, + VaultEvent eventType, + uint256 amount + ) internal { + SlaData storage slaData = StakedRelayerSLA[relayerId]; + uint256 currentSla = slaData.sla; + uint256 deltaSla; + if (eventType == VaultEvent.RedeemFailure) { + deltaSla = slaData.vaultRedeemFailure; + } else if (eventType == VaultEvent.SubmitIssueProof) { + deltaSla = slaData.vaultSubmitIssueProof; + } else if (eventType == VaultEvent.Refund) { + deltaSla = slaData.vaultRefund; + } else if (eventType == VaultEvent.ExecuteIssue) { + deltaSla = _executeIssueSlaChange(amount); + } else if (eventType == VaultEvent.Deposit) { + deltaSla = _depositSlaChange(amount); + } else if (eventType == VaultEvent.Withdraw) { + deltaSla = _withdrawSlaChange(amount); + } else if (eventType == VaultEvent.Liquidate) { + _liquidateSla(relayerId); + return; + } else { + revert("unknown type"); + } + + uint256 newSla = currentSla + deltaSla; + uint256 maxSla = slaData.vaultTargetSla; // todo: check that this is indeed the max + + uint256 boundedNewSla = limit(0, newSla, maxSla); + /* + Self::adjustStake::(vaultId, deltaSla)?; + Self::adjustStake::(vaultId, deltaSla)?; + */ + slaData.sla = boundedNewSla; + emit UpdateVaultSLA(vaultId, boundedNewSla, int256(deltaSla)); + } + + function calculateSlashAmount(address account) internal returns (uint256) { SlaData vault = VaultSLA[account]; uint256 slaTarget = vault.vaultTargetSla; uint256 sla = vaule.sla; @@ -163,17 +213,36 @@ contract SLA { return realSlashed; } - function updateSLA(address account, int256 delta) internal { + + + function updateVaultSLA(address account, int256 delta) internal { SlaData storage vault; - if(VaultTrue[address]){ vault = VaultSLA[address]; vault.sla = int256(vault).sla + delta; UpdateVaultSLA(account, vault.sla, delta); - } - else { + } + + function updateRelayerSla(address account, int256 delta) internal { vault = StakedRelayerSLA[address]; vault.sla = int256(vault).sla + delta; UpdateRelayerSLA(account, vault.sla, delta); - } + + } + + // for use in tests + function setVaultSla(uint256 vaultId, uint256 sla){ + VaultSLA[vauleId].sla = sla; + } + + function setRelayerSla(uint256 vaultId, uint256 sla){ + RelayerSla[valueId].sla = sla; + } + + function getRelayerSla ( uint256 vaultId) returns (uint256){ + return RelayerSla[vaultId].sla; + } + + function getVauleSla(uint256 vauleId) returns (uint256 ){ + return VauleSla[vauleId].sla; } } From 02f64ca52750c0e949e1eb8a33a68953eb96c43f Mon Sep 17 00:00:00 2001 From: rachit2501 Date: Mon, 1 Nov 2021 17:52:28 +0530 Subject: [PATCH 05/15] contuctor setup --- contract/bridge/contracts/SLA.sol | 86 ++++++++++++------- contract/bridge/contracts/test/SlaWrapper.sol | 54 ++++++++++-- contract/bridge/test/sla.js | 18 +++- 3 files changed, 121 insertions(+), 37 deletions(-) diff --git a/contract/bridge/contracts/SLA.sol b/contract/bridge/contracts/SLA.sol index eba1bf7..f8f8b05 100644 --- a/contract/bridge/contracts/SLA.sol +++ b/contract/bridge/contracts/SLA.sol @@ -2,7 +2,7 @@ pragma solidity ^0.6.12; -import "@openzeppelin/contracts/utils/math/SafeMath.sol"; +import "@openzeppelin/contracts/math/SafeMath.sol"; contract SLA { @@ -16,7 +16,7 @@ contract SLA { event UpdateRelayerSLA( address indexed relayerId, uint256 newSla, - uint256 deltaSla + int256 deltaSla ); enum VaultEvent { @@ -68,7 +68,27 @@ contract SLA { - currency to fixed point */ - function _executeIssueSlaChange(uint256 amount) private returns (uint256) { + constructor( uint256 _TotalIssueCount, + uint256 _LifetimeIssued, + uint256 _VaultExecuteIssueMaxSlaChange, + uint256 _VaultDepositMaxSlaChange, + uint256 _VaultWithdrawMaxSlaChange, + uint256 _AverageDepositCount, + uint256 _AverageDeposit, + uint256 _AverageWithdrawCount, + uint256 _AverageWithdraw) public { + TotalIssueCount = _TotalIssueCount; + LifetimeIssued = _LifetimeIssued; + VaultDepositMaxSlaChange = _VaultDepositMaxSlaChange; + VaultWithdrawMaxSlaChange = _VaultWithdrawMaxSlaChange; + AverageDeposit = _AverageDeposit; + AverageDepositCount = _AverageDepositCount; + AverageWithdraw = _AverageWithdraw; + AverageWithdrawCount = _AverageWithdrawCount; + } + + + function _executeIssueSlaChange(uint256 amount) internal returns (uint256) { uint256 count = TotalIssueCount + 1; TotalIssueCount = count; uint256 total = LifetimeIssued + amount; @@ -79,7 +99,12 @@ contract SLA { return (amount * maxSlaChange) / average; } - function _depositSlaChange(uint256 amount) private returns (uint256) { + + // Calculates the potential sla change for a vault depositing collateral. The value will be + // clipped between 0 and VaultDepositMaxSlaChange, but it does not take into consideration + // Vault's current SLA. It can return a value > 0 when its sla is already at the maximum. + + function _depositSlaChange(uint256 amount) internal returns (uint256) { uint256 maxSlaChange = VaultDepositMaxSlaChange; uint256 count = AverageDepositCount + 1; @@ -91,7 +116,7 @@ contract SLA { return (amount / average) * maxSlaChange; } - function _withdrawSlaChange(uint256 amount) private returns (uint256) { + function _withdrawSlaChange(uint256 amount) internal returns (uint256) { uint256 maxSlaChange = VaultWithdrawMaxSlaChange; uint256 count = AverageWithdrawCount + 1; @@ -103,7 +128,7 @@ contract SLA { return (amount / average) * maxSlaChange; } - function _liquidateSla(address vaultId) private returns (int256) { + function _liquidateSla(address vaultId) internal returns (int256) { // TODO //Self::liquidateStake::(vaultId)?; //Self::liquidateStake::(vaultId)?; @@ -118,7 +143,7 @@ contract SLA { uint256 min, uint256 cur, uint256 max - ) private pure returns (uint256) { + ) internal pure returns (uint256) { return cur > max ? max : (cur > min ? cur : min); } @@ -198,13 +223,13 @@ contract SLA { Self::adjustStake::(vaultId, deltaSla)?; */ slaData.sla = boundedNewSla; - emit UpdateVaultSLA(vaultId, boundedNewSla, int256(deltaSla)); + emit UpdateVaultSLA(relayerId, boundedNewSla, int256(deltaSla)); } function calculateSlashAmount(address account) internal returns (uint256) { - SlaData vault = VaultSLA[account]; + SlaData memory vault = VaultSLA[account]; uint256 slaTarget = vault.vaultTargetSla; - uint256 sla = vaule.sla; + uint256 sla = vault.sla; uint256 liquidateThreshold = vault.liquidate; uint256 premiumRedeemThreshold = vault.vaultRedeemFailure; @@ -213,36 +238,37 @@ contract SLA { return realSlashed; } - - function updateVaultSLA(address account, int256 delta) internal { SlaData storage vault; - vault = VaultSLA[address]; - vault.sla = int256(vault).sla + delta; - UpdateVaultSLA(account, vault.sla, delta); + vault = VaultSLA[account]; + + if(delta > 0){ + vault.sla = vault.sla + uint256(delta); + } + if(delta <0){ + vault.sla = vault.sla - uint256(delta); + } + UpdateVaultSLA(account, vault.sla, delta); } - function updateRelayerSla(address account, int256 delta) internal { - vault = StakedRelayerSLA[address]; - vault.sla = int256(vault).sla + delta; + function _updateRelayerSla(address account, int256 delta) internal { + SlaData storage vault = StakedRelayerSLA[account]; + if(delta > 0){ + vault.sla = vault.sla + uint256(delta); + } + if(delta <0){ + vault.sla = vault.sla - uint256(delta); + } UpdateRelayerSLA(account, vault.sla, delta); } - // for use in tests - function setVaultSla(uint256 vaultId, uint256 sla){ - VaultSLA[vauleId].sla = sla; - } - - function setRelayerSla(uint256 vaultId, uint256 sla){ - RelayerSla[valueId].sla = sla; - } - function getRelayerSla ( uint256 vaultId) returns (uint256){ - return RelayerSla[vaultId].sla; + function getRelayerSla ( address vaultId) public view returns (uint256){ + return StakedRelayerSLA[vaultId].sla; } - function getVauleSla(uint256 vauleId) returns (uint256 ){ - return VauleSla[vauleId].sla; + function getVaultSla(address vaultId) public view returns (uint256 ){ + return VaultSLA[vaultId].sla; } } diff --git a/contract/bridge/contracts/test/SlaWrapper.sol b/contract/bridge/contracts/test/SlaWrapper.sol index eae6d85..af4c29f 100644 --- a/contract/bridge/contracts/test/SlaWrapper.sol +++ b/contract/bridge/contracts/test/SlaWrapper.sol @@ -3,12 +3,56 @@ pragma solidity ^0.6.12; import {SLA} from "../SLA.sol"; contract SLAWrapper is SLA { - function slashVaultTest (address account) public returns (uint256){ - uint256 slashAmount = SlashVault(account); - return slashAmount; + // function slashVaultTest (address account) public returns (uint256){ + // uint256 slashAmount = SlashVault(account); + // return slashAmount; + // } + + // function updateSlaTes (address account, int256 delta) internal returns(uint256){ + // updateSLA(account, delta); + // } + + constructor(uint256 _TotalIssueCount, + uint256 _LifetimeIssued, + uint256 _VaultExecuteIssueMaxSlaChange, + uint256 _VaultDepositMaxSlaChange, + uint256 _VaultWithdrawMaxSlaChange, + uint256 _AverageDepositCount, + uint256 _AverageDeposit, + uint256 _AverageWithdrawCount, + uint256 _AverageWithdraw) SLA( _TotalIssueCount, + _LifetimeIssued, + _VaultExecuteIssueMaxSlaChange, + _VaultDepositMaxSlaChange, + _VaultWithdrawMaxSlaChange, + _AverageDepositCount, + _AverageDeposit, + _AverageWithdrawCount, + _AverageWithdraw) public {} + + function depositSlaChange(uint256 amount) public returns (uint256) { + _depositSlaChange(amount); + } + + function executeIssusSlaChange(uint256 amount) public returns (uint256){ + _executeIssueSlaChange(amount); + } + + function withdrawSlaChange(uint256 amount) public returns (uint256){ + return _withdrawSlaChange(amount); + } + + function updateRelayerSla(address account, int256 delta) public { + _updateRelayerSla(account, delta); } - function updateSlaTes (address account, int256 delta) internal { - updateSLA(account, delta); + // for use in tests + function setVaultSla(address vaultId, uint256 sla) public { + VaultSLA[vaultId].sla = sla; } + + function setRelayerSla(address vaultId, uint256 sla) public { + StakedRelayerSLA[vaultId].sla = sla; + } + } diff --git a/contract/bridge/test/sla.js b/contract/bridge/test/sla.js index 767fa76..c151465 100644 --- a/contract/bridge/test/sla.js +++ b/contract/bridge/test/sla.js @@ -1,10 +1,24 @@ -const SLA = artifacts.require("SLA"); +const SLA = artifacts.require("SLAWrapper"); contract("SLA", (account) => { let contractInstance; + const vaultId = account[3]; + before(async () => { - contractInstance = await SLA.new(); + contractInstance = await SLA.new(100, 100, 10, 10, 10, 20, 20, 20, 20); + }); + + it("get functions working correctly and setting up vaultSla values for tests", async () => { + assert.equal(await contractInstance.getRelayerSla(vaultId), 0); + assert.equal(await contractInstance.getVaultSla(vaultId), 0); + + await contractInstance.setVaultSla(vaultId, 50); + await contractInstance.setRelayerSla(vaultId, 30); + + assert.equal(await contractInstance.getRelayerSla(vaultId), 30); + assert.equal(await contractInstance.getVaultSla(vaultId), 50); }); + it("_depositSlaChange()", async () => { await contractInstance._depositSlaChange(10); const SLA = await contractInstance.getSLA(); From 7dff36004733aa8d9e92229dd863ae2d6a9ac324 Mon Sep 17 00:00:00 2001 From: rachit2501 Date: Mon, 1 Nov 2021 18:29:49 +0530 Subject: [PATCH 06/15] more tests --- contract/bridge/test/sla.js | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) diff --git a/contract/bridge/test/sla.js b/contract/bridge/test/sla.js index c151465..6a6326f 100644 --- a/contract/bridge/test/sla.js +++ b/contract/bridge/test/sla.js @@ -20,17 +20,9 @@ contract("SLA", (account) => { }); it("_depositSlaChange()", async () => { - await contractInstance._depositSlaChange(10); + await contractInstance.depositSlaChange(10); const SLA = await contractInstance.getSLA(); assert.equal(SLA, 10); }); - it("collateralToWrapped", async () => { - const rate = await contractInstance.collateralToWrapped(1000); - assert.equal(rate, 100); - }); - it("wrapped To collateral", async () => { - const rate = await contractInstance.wrappedToCollateral(1000); - assert.equal(rate, 10000); - }); }); From f510d4beddce9de7a65eba6c0efc0fb3242aea65 Mon Sep 17 00:00:00 2001 From: rachit2501 Date: Mon, 15 Nov 2021 02:11:47 +0530 Subject: [PATCH 07/15] sla v1 --- contract/bridge/contracts/SLA.sol | 15 ++++---- contract/bridge/contracts/test/SlaWrapper.sol | 11 ++---- contract/bridge/test/sla.js | 37 +++++++++++++++++-- 3 files changed, 45 insertions(+), 18 deletions(-) diff --git a/contract/bridge/contracts/SLA.sol b/contract/bridge/contracts/SLA.sol index f8f8b05..162b7eb 100644 --- a/contract/bridge/contracts/SLA.sol +++ b/contract/bridge/contracts/SLA.sol @@ -48,7 +48,6 @@ contract SLA { uint256 withdraw; uint256 liquidate; uint256 sla; - uint256 vaultTargetSla; } uint256 public VaultSLATarget = 100; @@ -147,7 +146,9 @@ contract SLA { return cur > max ? max : (cur > min ? cur : min); } - function eventUpdateVaultSla( + event data (uint256,uint256,uint256, uint256); + + function _eventUpdateVaultSla( address vaultId, VaultEvent eventType, uint256 amount @@ -171,11 +172,11 @@ contract SLA { _liquidateSla(vaultId); return; } else { - revert("unknow type"); + revert("unknown type"); } uint256 newSla = currentSla + deltaSla; - uint256 maxSla = slaData.vaultTargetSla; // todo: check that this is indeed the max + uint256 maxSla = VaultSLATarget; // todo: check that this is indeed the max uint256 boundedNewSla = limit(0, newSla, maxSla); /* @@ -187,7 +188,7 @@ contract SLA { } - function eventUpdateRelayerSla( + function _eventUpdateRelayerSla( address relayerId, VaultEvent eventType, uint256 amount @@ -215,7 +216,7 @@ contract SLA { } uint256 newSla = currentSla + deltaSla; - uint256 maxSla = slaData.vaultTargetSla; // todo: check that this is indeed the max + uint256 maxSla = VaultSLATarget; // todo: check that this is indeed the max uint256 boundedNewSla = limit(0, newSla, maxSla); /* @@ -228,7 +229,7 @@ contract SLA { function calculateSlashAmount(address account) internal returns (uint256) { SlaData memory vault = VaultSLA[account]; - uint256 slaTarget = vault.vaultTargetSla; + uint256 slaTarget = VaultSLATarget; uint256 sla = vault.sla; uint256 liquidateThreshold = vault.liquidate; uint256 premiumRedeemThreshold = vault.vaultRedeemFailure; diff --git a/contract/bridge/contracts/test/SlaWrapper.sol b/contract/bridge/contracts/test/SlaWrapper.sol index af4c29f..298a38c 100644 --- a/contract/bridge/contracts/test/SlaWrapper.sol +++ b/contract/bridge/contracts/test/SlaWrapper.sol @@ -30,16 +30,13 @@ contract SLAWrapper is SLA { _AverageWithdrawCount, _AverageWithdraw) public {} - function depositSlaChange(uint256 amount) public returns (uint256) { - _depositSlaChange(amount); + function eventUpdateVaultSla(address vaultId, VaultEvent eventType,uint256 amount) public returns (uint256) { + _eventUpdateVaultSla(vaultId, eventType, amount); } - function executeIssusSlaChange(uint256 amount) public returns (uint256){ - _executeIssueSlaChange(amount); - } - function withdrawSlaChange(uint256 amount) public returns (uint256){ - return _withdrawSlaChange(amount); + function eventUpdateRelayerSla(address vaultId, VaultEvent eventType,uint256 amount) public returns (uint256) { + _eventUpdateRelayerSla(vaultId, eventType, amount); } function updateRelayerSla(address account, int256 delta) public { diff --git a/contract/bridge/test/sla.js b/contract/bridge/test/sla.js index 6a6326f..e81b0f8 100644 --- a/contract/bridge/test/sla.js +++ b/contract/bridge/test/sla.js @@ -19,10 +19,39 @@ contract("SLA", (account) => { assert.equal(await contractInstance.getVaultSla(vaultId), 50); }); - it("_depositSlaChange()", async () => { - await contractInstance.depositSlaChange(10); - const SLA = await contractInstance.getSLA(); + it("deposit sla change - vault id : 4", async () => { + await contractInstance.eventUpdateVaultSla(vaultId, 4, 60); + const sla = await contractInstance.getVaultSla(vaultId); + assert.equal(sla.toNumber(), 70); + }); + + it("withdraw sla change - vault id: 5", async () => { + await contractInstance.eventUpdateVaultSla(vaultId, 5, 55); + const sla = await contractInstance.getVaultSla(vaultId); + assert.equal(sla.toNumber(), 90); + }); + + it("execute issue sla change - vault id: 3", async () => { + await contractInstance.eventUpdateVaultSla(vaultId, 3, 25); + const sla = await contractInstance.getVaultSla(vaultId); + assert.equal(sla.toNumber(), 90); + }); + + it("deposit sla change - relayer id : 4", async () => { + await contractInstance.eventUpdateRelayerSla(vaultId, 4, 60); + const sla = await contractInstance.getRelayerSla(vaultId); + assert.equal(sla.toNumber(), 50); + }); + + it("withdraw sla change - relayer id: 5", async () => { + await contractInstance.eventUpdateRelayerSla(vaultId, 5, 55); + const sla = await contractInstance.getRelayerSla(vaultId); + assert.equal(sla.toNumber(), 70); + }); - assert.equal(SLA, 10); + it("execute issue sla change - relayer id: 3", async () => { + await contractInstance.eventUpdateRelayerSla(vaultId, 3, 25); + const sla = await contractInstance.getRelayerSla(vaultId); + assert.equal(sla.toNumber(), 70); }); }); From e7d1e47a7ef0c1b5789c8c84137cb87b07b4d063 Mon Sep 17 00:00:00 2001 From: rachit2501 Date: Mon, 27 Sep 2021 03:00:49 +0530 Subject: [PATCH 08/15] sla contract --- contract/bridge/contracts/SLA.sol | 32 +++++++++++++++++-- contract/bridge/contracts/test/SlaWrapper.sol | 7 ++++ 2 files changed, 37 insertions(+), 2 deletions(-) create mode 100644 contract/bridge/contracts/test/SlaWrapper.sol diff --git a/contract/bridge/contracts/SLA.sol b/contract/bridge/contracts/SLA.sol index d9e7e7a..250dd88 100644 --- a/contract/bridge/contracts/SLA.sol +++ b/contract/bridge/contracts/SLA.sol @@ -2,7 +2,12 @@ pragma solidity ^0.6.12; +import "@openzeppelin/contracts/utils/math/SafeMath.sol"; + contract SLA { + + using SafeMath for uint256; + event UpdateVaultSLA( address indexed vaultId, uint256 boundedNewSla, @@ -51,6 +56,7 @@ contract SLA { mapping(address => SlaData) VaultSLA; mapping(address => SlaData) StakedRelayerSLA; + mapping(address => bool) VaultTrue; function _executeIssueSlaChange(uint256 amount) private returns (uint256) { uint256 count = TotalIssueCount + 1; @@ -145,7 +151,29 @@ contract SLA { emit UpdateVaultSLA(vaultId, boundedNewSla, int256(deltaSla)); } - function SlashVault(address account) internal returns (uint256) {} + function SlashVault(address account) internal returns (uint256) { + SlaData vault = VaultSLA[account]; + uint256 slaTarget = vault.vaultTargetSla; + uint256 sla = vaule.sla; + uint256 liquidateThreshold = vault.liquidate; + uint256 premiumRedeemThreshold = vault.vaultRedeemFailure; - function updateSLA(address account, uint256 delta) internal {} + uint256 realSlashed = premiumRedeemThreshold.sub(liquidateThreshold).div(slaTarget).mul(sla).add(liquidateThreshold); + + return realSlashed; + } + + function updateSLA(address account, int256 delta) internal { + SlaData storage vault; + if(VaultTrue[address]){ + vault = VaultSLA[address]; + vault.sla = int256(vault).sla + delta; + UpdateVaultSLA(account, vault.sla, delta); + } + else { + vault = StakedRelayerSLA[address]; + vault.sla = int256(vault).sla + delta; + UpdateRelayerSLA(account, vault.sla, delta); + } + } } diff --git a/contract/bridge/contracts/test/SlaWrapper.sol b/contract/bridge/contracts/test/SlaWrapper.sol new file mode 100644 index 0000000..746bd05 --- /dev/null +++ b/contract/bridge/contracts/test/SlaWrapper.sol @@ -0,0 +1,7 @@ +pragma solidity ^0.6.12; + +import {SLA} from "../SLA.sol"; + +contract SLAWrapper is SLA { + +} From 69057d65a8b5a60354e4bee4c29b4efd34844cad Mon Sep 17 00:00:00 2001 From: rachit2501 Date: Mon, 27 Sep 2021 03:07:13 +0530 Subject: [PATCH 09/15] sla wrapper --- contract/bridge/contracts/test/SlaWrapper.sol | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/contract/bridge/contracts/test/SlaWrapper.sol b/contract/bridge/contracts/test/SlaWrapper.sol index 746bd05..eae6d85 100644 --- a/contract/bridge/contracts/test/SlaWrapper.sol +++ b/contract/bridge/contracts/test/SlaWrapper.sol @@ -3,5 +3,12 @@ pragma solidity ^0.6.12; import {SLA} from "../SLA.sol"; contract SLAWrapper is SLA { - + function slashVaultTest (address account) public returns (uint256){ + uint256 slashAmount = SlashVault(account); + return slashAmount; + } + + function updateSlaTes (address account, int256 delta) internal { + updateSLA(account, delta); + } } From ed5a48b53b8e307eb0ff87733413ea233a3028a8 Mon Sep 17 00:00:00 2001 From: rachit2501 Date: Mon, 1 Nov 2021 16:43:25 +0530 Subject: [PATCH 10/15] sla functions --- contract/bridge/contracts/SLA.sol | 83 ++++++++++++++++++++++++++++--- 1 file changed, 76 insertions(+), 7 deletions(-) diff --git a/contract/bridge/contracts/SLA.sol b/contract/bridge/contracts/SLA.sol index 250dd88..eba1bf7 100644 --- a/contract/bridge/contracts/SLA.sol +++ b/contract/bridge/contracts/SLA.sol @@ -58,6 +58,16 @@ contract SLA { mapping(address => SlaData) StakedRelayerSLA; mapping(address => bool) VaultTrue; + + /* + - adjust stake + - liquidate stake + - calculate slashed amount + - fixed point unsigned to signed + - wrapper to uint128 + - currency to fixed point + */ + function _executeIssueSlaChange(uint256 amount) private returns (uint256) { uint256 count = TotalIssueCount + 1; TotalIssueCount = count; @@ -97,7 +107,7 @@ contract SLA { // TODO //Self::liquidateStake::(vaultId)?; //Self::liquidateStake::(vaultId)?; - revert("TODO"); + // revert("TODO"); SlaData storage slaData = VaultSLA[vaultId]; int256 deltaSla = -int256(slaData.sla); slaData.sla = 0; @@ -151,7 +161,47 @@ contract SLA { emit UpdateVaultSLA(vaultId, boundedNewSla, int256(deltaSla)); } - function SlashVault(address account) internal returns (uint256) { + + function eventUpdateRelayerSla( + address relayerId, + VaultEvent eventType, + uint256 amount + ) internal { + SlaData storage slaData = StakedRelayerSLA[relayerId]; + uint256 currentSla = slaData.sla; + uint256 deltaSla; + if (eventType == VaultEvent.RedeemFailure) { + deltaSla = slaData.vaultRedeemFailure; + } else if (eventType == VaultEvent.SubmitIssueProof) { + deltaSla = slaData.vaultSubmitIssueProof; + } else if (eventType == VaultEvent.Refund) { + deltaSla = slaData.vaultRefund; + } else if (eventType == VaultEvent.ExecuteIssue) { + deltaSla = _executeIssueSlaChange(amount); + } else if (eventType == VaultEvent.Deposit) { + deltaSla = _depositSlaChange(amount); + } else if (eventType == VaultEvent.Withdraw) { + deltaSla = _withdrawSlaChange(amount); + } else if (eventType == VaultEvent.Liquidate) { + _liquidateSla(relayerId); + return; + } else { + revert("unknown type"); + } + + uint256 newSla = currentSla + deltaSla; + uint256 maxSla = slaData.vaultTargetSla; // todo: check that this is indeed the max + + uint256 boundedNewSla = limit(0, newSla, maxSla); + /* + Self::adjustStake::(vaultId, deltaSla)?; + Self::adjustStake::(vaultId, deltaSla)?; + */ + slaData.sla = boundedNewSla; + emit UpdateVaultSLA(vaultId, boundedNewSla, int256(deltaSla)); + } + + function calculateSlashAmount(address account) internal returns (uint256) { SlaData vault = VaultSLA[account]; uint256 slaTarget = vault.vaultTargetSla; uint256 sla = vaule.sla; @@ -163,17 +213,36 @@ contract SLA { return realSlashed; } - function updateSLA(address account, int256 delta) internal { + + + function updateVaultSLA(address account, int256 delta) internal { SlaData storage vault; - if(VaultTrue[address]){ vault = VaultSLA[address]; vault.sla = int256(vault).sla + delta; UpdateVaultSLA(account, vault.sla, delta); - } - else { + } + + function updateRelayerSla(address account, int256 delta) internal { vault = StakedRelayerSLA[address]; vault.sla = int256(vault).sla + delta; UpdateRelayerSLA(account, vault.sla, delta); - } + + } + + // for use in tests + function setVaultSla(uint256 vaultId, uint256 sla){ + VaultSLA[vauleId].sla = sla; + } + + function setRelayerSla(uint256 vaultId, uint256 sla){ + RelayerSla[valueId].sla = sla; + } + + function getRelayerSla ( uint256 vaultId) returns (uint256){ + return RelayerSla[vaultId].sla; + } + + function getVauleSla(uint256 vauleId) returns (uint256 ){ + return VauleSla[vauleId].sla; } } From f501f7add276bdde1ecc5b84439700f15b3b42ab Mon Sep 17 00:00:00 2001 From: rachit2501 Date: Mon, 1 Nov 2021 17:52:28 +0530 Subject: [PATCH 11/15] contuctor setup --- contract/bridge/contracts/SLA.sol | 86 ++++++++++++------- contract/bridge/contracts/test/SlaWrapper.sol | 54 ++++++++++-- 2 files changed, 105 insertions(+), 35 deletions(-) diff --git a/contract/bridge/contracts/SLA.sol b/contract/bridge/contracts/SLA.sol index eba1bf7..f8f8b05 100644 --- a/contract/bridge/contracts/SLA.sol +++ b/contract/bridge/contracts/SLA.sol @@ -2,7 +2,7 @@ pragma solidity ^0.6.12; -import "@openzeppelin/contracts/utils/math/SafeMath.sol"; +import "@openzeppelin/contracts/math/SafeMath.sol"; contract SLA { @@ -16,7 +16,7 @@ contract SLA { event UpdateRelayerSLA( address indexed relayerId, uint256 newSla, - uint256 deltaSla + int256 deltaSla ); enum VaultEvent { @@ -68,7 +68,27 @@ contract SLA { - currency to fixed point */ - function _executeIssueSlaChange(uint256 amount) private returns (uint256) { + constructor( uint256 _TotalIssueCount, + uint256 _LifetimeIssued, + uint256 _VaultExecuteIssueMaxSlaChange, + uint256 _VaultDepositMaxSlaChange, + uint256 _VaultWithdrawMaxSlaChange, + uint256 _AverageDepositCount, + uint256 _AverageDeposit, + uint256 _AverageWithdrawCount, + uint256 _AverageWithdraw) public { + TotalIssueCount = _TotalIssueCount; + LifetimeIssued = _LifetimeIssued; + VaultDepositMaxSlaChange = _VaultDepositMaxSlaChange; + VaultWithdrawMaxSlaChange = _VaultWithdrawMaxSlaChange; + AverageDeposit = _AverageDeposit; + AverageDepositCount = _AverageDepositCount; + AverageWithdraw = _AverageWithdraw; + AverageWithdrawCount = _AverageWithdrawCount; + } + + + function _executeIssueSlaChange(uint256 amount) internal returns (uint256) { uint256 count = TotalIssueCount + 1; TotalIssueCount = count; uint256 total = LifetimeIssued + amount; @@ -79,7 +99,12 @@ contract SLA { return (amount * maxSlaChange) / average; } - function _depositSlaChange(uint256 amount) private returns (uint256) { + + // Calculates the potential sla change for a vault depositing collateral. The value will be + // clipped between 0 and VaultDepositMaxSlaChange, but it does not take into consideration + // Vault's current SLA. It can return a value > 0 when its sla is already at the maximum. + + function _depositSlaChange(uint256 amount) internal returns (uint256) { uint256 maxSlaChange = VaultDepositMaxSlaChange; uint256 count = AverageDepositCount + 1; @@ -91,7 +116,7 @@ contract SLA { return (amount / average) * maxSlaChange; } - function _withdrawSlaChange(uint256 amount) private returns (uint256) { + function _withdrawSlaChange(uint256 amount) internal returns (uint256) { uint256 maxSlaChange = VaultWithdrawMaxSlaChange; uint256 count = AverageWithdrawCount + 1; @@ -103,7 +128,7 @@ contract SLA { return (amount / average) * maxSlaChange; } - function _liquidateSla(address vaultId) private returns (int256) { + function _liquidateSla(address vaultId) internal returns (int256) { // TODO //Self::liquidateStake::(vaultId)?; //Self::liquidateStake::(vaultId)?; @@ -118,7 +143,7 @@ contract SLA { uint256 min, uint256 cur, uint256 max - ) private pure returns (uint256) { + ) internal pure returns (uint256) { return cur > max ? max : (cur > min ? cur : min); } @@ -198,13 +223,13 @@ contract SLA { Self::adjustStake::(vaultId, deltaSla)?; */ slaData.sla = boundedNewSla; - emit UpdateVaultSLA(vaultId, boundedNewSla, int256(deltaSla)); + emit UpdateVaultSLA(relayerId, boundedNewSla, int256(deltaSla)); } function calculateSlashAmount(address account) internal returns (uint256) { - SlaData vault = VaultSLA[account]; + SlaData memory vault = VaultSLA[account]; uint256 slaTarget = vault.vaultTargetSla; - uint256 sla = vaule.sla; + uint256 sla = vault.sla; uint256 liquidateThreshold = vault.liquidate; uint256 premiumRedeemThreshold = vault.vaultRedeemFailure; @@ -213,36 +238,37 @@ contract SLA { return realSlashed; } - - function updateVaultSLA(address account, int256 delta) internal { SlaData storage vault; - vault = VaultSLA[address]; - vault.sla = int256(vault).sla + delta; - UpdateVaultSLA(account, vault.sla, delta); + vault = VaultSLA[account]; + + if(delta > 0){ + vault.sla = vault.sla + uint256(delta); + } + if(delta <0){ + vault.sla = vault.sla - uint256(delta); + } + UpdateVaultSLA(account, vault.sla, delta); } - function updateRelayerSla(address account, int256 delta) internal { - vault = StakedRelayerSLA[address]; - vault.sla = int256(vault).sla + delta; + function _updateRelayerSla(address account, int256 delta) internal { + SlaData storage vault = StakedRelayerSLA[account]; + if(delta > 0){ + vault.sla = vault.sla + uint256(delta); + } + if(delta <0){ + vault.sla = vault.sla - uint256(delta); + } UpdateRelayerSLA(account, vault.sla, delta); } - // for use in tests - function setVaultSla(uint256 vaultId, uint256 sla){ - VaultSLA[vauleId].sla = sla; - } - - function setRelayerSla(uint256 vaultId, uint256 sla){ - RelayerSla[valueId].sla = sla; - } - function getRelayerSla ( uint256 vaultId) returns (uint256){ - return RelayerSla[vaultId].sla; + function getRelayerSla ( address vaultId) public view returns (uint256){ + return StakedRelayerSLA[vaultId].sla; } - function getVauleSla(uint256 vauleId) returns (uint256 ){ - return VauleSla[vauleId].sla; + function getVaultSla(address vaultId) public view returns (uint256 ){ + return VaultSLA[vaultId].sla; } } diff --git a/contract/bridge/contracts/test/SlaWrapper.sol b/contract/bridge/contracts/test/SlaWrapper.sol index eae6d85..af4c29f 100644 --- a/contract/bridge/contracts/test/SlaWrapper.sol +++ b/contract/bridge/contracts/test/SlaWrapper.sol @@ -3,12 +3,56 @@ pragma solidity ^0.6.12; import {SLA} from "../SLA.sol"; contract SLAWrapper is SLA { - function slashVaultTest (address account) public returns (uint256){ - uint256 slashAmount = SlashVault(account); - return slashAmount; + // function slashVaultTest (address account) public returns (uint256){ + // uint256 slashAmount = SlashVault(account); + // return slashAmount; + // } + + // function updateSlaTes (address account, int256 delta) internal returns(uint256){ + // updateSLA(account, delta); + // } + + constructor(uint256 _TotalIssueCount, + uint256 _LifetimeIssued, + uint256 _VaultExecuteIssueMaxSlaChange, + uint256 _VaultDepositMaxSlaChange, + uint256 _VaultWithdrawMaxSlaChange, + uint256 _AverageDepositCount, + uint256 _AverageDeposit, + uint256 _AverageWithdrawCount, + uint256 _AverageWithdraw) SLA( _TotalIssueCount, + _LifetimeIssued, + _VaultExecuteIssueMaxSlaChange, + _VaultDepositMaxSlaChange, + _VaultWithdrawMaxSlaChange, + _AverageDepositCount, + _AverageDeposit, + _AverageWithdrawCount, + _AverageWithdraw) public {} + + function depositSlaChange(uint256 amount) public returns (uint256) { + _depositSlaChange(amount); + } + + function executeIssusSlaChange(uint256 amount) public returns (uint256){ + _executeIssueSlaChange(amount); + } + + function withdrawSlaChange(uint256 amount) public returns (uint256){ + return _withdrawSlaChange(amount); + } + + function updateRelayerSla(address account, int256 delta) public { + _updateRelayerSla(account, delta); } - function updateSlaTes (address account, int256 delta) internal { - updateSLA(account, delta); + // for use in tests + function setVaultSla(address vaultId, uint256 sla) public { + VaultSLA[vaultId].sla = sla; } + + function setRelayerSla(address vaultId, uint256 sla) public { + StakedRelayerSLA[vaultId].sla = sla; + } + } From 789b9be9ffc3e54c505a01050836ac493633fac9 Mon Sep 17 00:00:00 2001 From: rachit2501 Date: Mon, 15 Nov 2021 02:11:47 +0530 Subject: [PATCH 12/15] sla v1 --- contract/bridge/contracts/SLA.sol | 15 ++++++++------- contract/bridge/contracts/test/SlaWrapper.sol | 11 ++++------- 2 files changed, 12 insertions(+), 14 deletions(-) diff --git a/contract/bridge/contracts/SLA.sol b/contract/bridge/contracts/SLA.sol index f8f8b05..162b7eb 100644 --- a/contract/bridge/contracts/SLA.sol +++ b/contract/bridge/contracts/SLA.sol @@ -48,7 +48,6 @@ contract SLA { uint256 withdraw; uint256 liquidate; uint256 sla; - uint256 vaultTargetSla; } uint256 public VaultSLATarget = 100; @@ -147,7 +146,9 @@ contract SLA { return cur > max ? max : (cur > min ? cur : min); } - function eventUpdateVaultSla( + event data (uint256,uint256,uint256, uint256); + + function _eventUpdateVaultSla( address vaultId, VaultEvent eventType, uint256 amount @@ -171,11 +172,11 @@ contract SLA { _liquidateSla(vaultId); return; } else { - revert("unknow type"); + revert("unknown type"); } uint256 newSla = currentSla + deltaSla; - uint256 maxSla = slaData.vaultTargetSla; // todo: check that this is indeed the max + uint256 maxSla = VaultSLATarget; // todo: check that this is indeed the max uint256 boundedNewSla = limit(0, newSla, maxSla); /* @@ -187,7 +188,7 @@ contract SLA { } - function eventUpdateRelayerSla( + function _eventUpdateRelayerSla( address relayerId, VaultEvent eventType, uint256 amount @@ -215,7 +216,7 @@ contract SLA { } uint256 newSla = currentSla + deltaSla; - uint256 maxSla = slaData.vaultTargetSla; // todo: check that this is indeed the max + uint256 maxSla = VaultSLATarget; // todo: check that this is indeed the max uint256 boundedNewSla = limit(0, newSla, maxSla); /* @@ -228,7 +229,7 @@ contract SLA { function calculateSlashAmount(address account) internal returns (uint256) { SlaData memory vault = VaultSLA[account]; - uint256 slaTarget = vault.vaultTargetSla; + uint256 slaTarget = VaultSLATarget; uint256 sla = vault.sla; uint256 liquidateThreshold = vault.liquidate; uint256 premiumRedeemThreshold = vault.vaultRedeemFailure; diff --git a/contract/bridge/contracts/test/SlaWrapper.sol b/contract/bridge/contracts/test/SlaWrapper.sol index af4c29f..298a38c 100644 --- a/contract/bridge/contracts/test/SlaWrapper.sol +++ b/contract/bridge/contracts/test/SlaWrapper.sol @@ -30,16 +30,13 @@ contract SLAWrapper is SLA { _AverageWithdrawCount, _AverageWithdraw) public {} - function depositSlaChange(uint256 amount) public returns (uint256) { - _depositSlaChange(amount); + function eventUpdateVaultSla(address vaultId, VaultEvent eventType,uint256 amount) public returns (uint256) { + _eventUpdateVaultSla(vaultId, eventType, amount); } - function executeIssusSlaChange(uint256 amount) public returns (uint256){ - _executeIssueSlaChange(amount); - } - function withdrawSlaChange(uint256 amount) public returns (uint256){ - return _withdrawSlaChange(amount); + function eventUpdateRelayerSla(address vaultId, VaultEvent eventType,uint256 amount) public returns (uint256) { + _eventUpdateRelayerSla(vaultId, eventType, amount); } function updateRelayerSla(address account, int256 delta) public { From e22341814977cdce4c094b3be8cd7ad1b376dfd7 Mon Sep 17 00:00:00 2001 From: rachit2501 Date: Mon, 29 Nov 2021 03:28:52 +0530 Subject: [PATCH 13/15] merge --- contract/bridge/package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/contract/bridge/package.json b/contract/bridge/package.json index 6016396..961c338 100644 --- a/contract/bridge/package.json +++ b/contract/bridge/package.json @@ -1,11 +1,11 @@ { "dependencies": { + "@harmony-js/core": "^0.1.57", "@interlay/bitcoin-spv-sol": "^3.2.2", "@openzeppelin/contracts": "3.1.0", "@openzeppelin/test-helpers": "^0.5.11", - "bitcoinjs-lib": "^5.2.0", - "@harmony-js/core": "^0.1.57", "@truffle/hdwallet-provider": "^1.2.1", + "bitcoinjs-lib": "^5.2.0", "dotenv": "^8.2.0", "eth-ens-namehash": "^2.0.8", "solium": "^1.2.5", From a38d598186ae9b4df37fd39ee75d2e4a06f362a2 Mon Sep 17 00:00:00 2001 From: rachit2501 Date: Mon, 29 Nov 2021 03:37:39 +0530 Subject: [PATCH 14/15] fix exchange contract merge issue --- contract/bridge/test/sla.js | 57 +++++++++++++++++++++++++++++++ contract/bridge/truffle-config.js | 33 +++++++++--------- 2 files changed, 74 insertions(+), 16 deletions(-) create mode 100644 contract/bridge/test/sla.js diff --git a/contract/bridge/test/sla.js b/contract/bridge/test/sla.js new file mode 100644 index 0000000..e81b0f8 --- /dev/null +++ b/contract/bridge/test/sla.js @@ -0,0 +1,57 @@ +const SLA = artifacts.require("SLAWrapper"); + +contract("SLA", (account) => { + let contractInstance; + const vaultId = account[3]; + + before(async () => { + contractInstance = await SLA.new(100, 100, 10, 10, 10, 20, 20, 20, 20); + }); + + it("get functions working correctly and setting up vaultSla values for tests", async () => { + assert.equal(await contractInstance.getRelayerSla(vaultId), 0); + assert.equal(await contractInstance.getVaultSla(vaultId), 0); + + await contractInstance.setVaultSla(vaultId, 50); + await contractInstance.setRelayerSla(vaultId, 30); + + assert.equal(await contractInstance.getRelayerSla(vaultId), 30); + assert.equal(await contractInstance.getVaultSla(vaultId), 50); + }); + + it("deposit sla change - vault id : 4", async () => { + await contractInstance.eventUpdateVaultSla(vaultId, 4, 60); + const sla = await contractInstance.getVaultSla(vaultId); + assert.equal(sla.toNumber(), 70); + }); + + it("withdraw sla change - vault id: 5", async () => { + await contractInstance.eventUpdateVaultSla(vaultId, 5, 55); + const sla = await contractInstance.getVaultSla(vaultId); + assert.equal(sla.toNumber(), 90); + }); + + it("execute issue sla change - vault id: 3", async () => { + await contractInstance.eventUpdateVaultSla(vaultId, 3, 25); + const sla = await contractInstance.getVaultSla(vaultId); + assert.equal(sla.toNumber(), 90); + }); + + it("deposit sla change - relayer id : 4", async () => { + await contractInstance.eventUpdateRelayerSla(vaultId, 4, 60); + const sla = await contractInstance.getRelayerSla(vaultId); + assert.equal(sla.toNumber(), 50); + }); + + it("withdraw sla change - relayer id: 5", async () => { + await contractInstance.eventUpdateRelayerSla(vaultId, 5, 55); + const sla = await contractInstance.getRelayerSla(vaultId); + assert.equal(sla.toNumber(), 70); + }); + + it("execute issue sla change - relayer id: 3", async () => { + await contractInstance.eventUpdateRelayerSla(vaultId, 3, 25); + const sla = await contractInstance.getRelayerSla(vaultId); + assert.equal(sla.toNumber(), 70); + }); +}); diff --git a/contract/bridge/truffle-config.js b/contract/bridge/truffle-config.js index fa7c9ac..2585444 100644 --- a/contract/bridge/truffle-config.js +++ b/contract/bridge/truffle-config.js @@ -33,38 +33,38 @@ module.exports = { networks: { test: { - host: 'localhost', - port: 7545, - network_id: '5777', + host: "localhost", + port: 9545, + network_id: "5777", // gas: 4712388 // host: "127.0.0.1", // port: 8545, // network_id: '*', accounts: 5, defaultEtherBalance: 500, - blockTime: 0 + blockTime: 0, }, local: { - host: 'localhost', + host: "localhost", port: 7545, - network_id: '5777', + network_id: "5777", // gas: 4712388 // host: "127.0.0.1", // port: 8545, // network_id: '*', accounts: 5, defaultEtherBalance: 500, - blockTime: 0 + blockTime: 0, }, develop: { host: "127.0.0.1", port: 8545, - network_id: '*', + network_id: "*", accounts: 5, defaultEtherBalance: 500, - blockTime: 0 + blockTime: 0, }, }, @@ -76,14 +76,15 @@ module.exports = { // Configure your compilers compilers: { solc: { - version: "0.6.12+commit.27d51765", // Fetch exact version from solc-bin (default: truffle's version) - settings: { // See the solidity docs for advice about optimization and evmVersion + version: "0.6.12+commit.27d51765", // Fetch exact version from solc-bin (default: truffle's version) + settings: { + // See the solidity docs for advice about optimization and evmVersion optimizer: { enabled: true, - runs: 200 + runs: 200, }, - // evmVersion: "byzantium" - } - } - } + // evmVersion: "byzantium" + }, + }, + }, }; From d43ba3a47f4079bd07228927517573f415c47441 Mon Sep 17 00:00:00 2001 From: rachit2501 Date: Sun, 12 Dec 2021 11:23:02 +0530 Subject: [PATCH 15/15] ExchangeRateOracle removal --- .../bridge/contracts/ExchangeRateOracle.sol | 105 +++++++++++------- 1 file changed, 64 insertions(+), 41 deletions(-) diff --git a/contract/bridge/contracts/ExchangeRateOracle.sol b/contract/bridge/contracts/ExchangeRateOracle.sol index 41153da..f55856a 100644 --- a/contract/bridge/contracts/ExchangeRateOracle.sol +++ b/contract/bridge/contracts/ExchangeRateOracle.sol @@ -7,39 +7,45 @@ https://onebtc-dev.web.app/spec/oracle.html The Exchange Rate Oracle receives a continuous data feed on the exchange rate between BTC and ONE. */ -pragma solidity 0.6.12; - -import "@openzeppelin/contracts-upgradeable/proxy/Initializable.sol"; -import "@openzeppelin/contracts-upgradeable/math/SafeMathUpgradeable.sol"; -import "@openzeppelin/contracts-upgradeable/math/MathUpgradeable.sol"; - -contract ExchangeRateOracle is Initializable { - using SafeMathUpgradeable for uint256; +pragma solidity ^0.6.12; +contract ExchangeRateOracle { uint256 constant MAX_DELAY = 1000; - uint256 public lastExchangeRateTime; uint256 exchangeRate; - - mapping(address => bool) authorizedOracles; - - event SetExchangeRate(address oracle, uint256 rate); - - event recoverFromORACLEOFFLINE(address oracle, uint256 rate); - - function initialize(address provider) public initializer { - lastExchangeRateTime = now; - authorizedOracles[provider] = true; + uint256 satoshiPerBytes; + mapping (address => bool) authorizedOracles; + + event SetExchangeRate( + address oracle, + uint256 rate + ); + + event SetSatoshiPerByte( + uint256 fee, + uint256 inclusionEstimate + ); + + event recoverFromORACLEOFFLINE( + address oracle, + uint256 rate + ); + + constructor() public { + authorizedOracles[0x5B38Da6a701c568545dCfcB03FcB875f56beddC4] = true; } - function setExchangeRate(uint256 btcPrice, uint256 onePrice) public { - address oracle = msg.sender; - require(authorizedOracles[oracle], "Sender is not authorized"); + /** + @notice Set the latest (aggregate) BTC/ONE exchange rate. This function invokes a check of vault collateral rates in the Vault Registry component. + @param oracle the oracle account calling this function. Must be pre-authorized and tracked in this component! + @param rate the u128 BTC/ONE exchange rate. + */ + function setExchangeRate(address oracle, uint256 rate) public { + require(authorizedOracles[oracle], "ERR_INVALID_ORACLE_SOURCE"); - uint256 rate = btcPrice.div(onePrice); exchangeRate = rate; - if (now - lastExchangeRateTime > MAX_DELAY) { + if (lastExchangeRateTime - now > MAX_DELAY) { emit recoverFromORACLEOFFLINE(oracle, rate); } @@ -48,32 +54,49 @@ contract ExchangeRateOracle is Initializable { emit SetExchangeRate(oracle, rate); } - function getExchangeRate() private view returns (uint256) { - require( - now - lastExchangeRateTime <= MAX_DELAY, - "Exchange rate avaialble is too old" - ); + /** + @notice Set the Satoshi per bytes fee + @param fee the Satoshi per byte fee. + @param inclusionEstimate the estimated inclusion time. + */ + function setSatoshiPerBytes(uint256 fee, uint256 inclusionEstimate) public { + // 1. The BTC Bridge status in the Security component MUST be set to RUNNING:0. + // TODO require() + + require(authorizedOracles[msg.sender], "ERR_INVALID_ORACLE_SOURCE"); + + satoshiPerBytes = inclusionEstimate; + + emit SetSatoshiPerByte(fee, inclusionEstimate); + } + + /** + @notice Returns the latest BTC/ONE exchange rate, as received from the external data sources. + @return uint256 (aggregate) exchange rate value + */ + function getExchangeRate() public view returns (uint256) { + require (now - lastExchangeRateTime > MAX_DELAY, "ERR_MISSING_EXCHANGE_RATE"); return exchangeRate; } /** - * @notice Get BTC amount by ONE. - * @param amount collateral(ONE) amount - * @return BTC amount - */ - function collateralToWrapped(uint256 amount) public view returns (uint256) { + * @notice Get BTC amount by ONE. + * @param amount collateral(ONE) amount + * @return BTC amount + */ + function collateralToWrapped(uint256 amount) public view returns(uint256) { uint256 rate = getExchangeRate(); - return amount.div(rate).mul(10**8).div(10**18); + return amount/rate; } /** - * @notice Get ONE amount by BTC. - * @param amount BTC amount - * @return ONE amount - */ - function wrappedToCollateral(uint256 amount) public view returns (uint256) { + * @notice Get ONE amount by BTC. + * @param amount BTC amount + * @return ONE amount + */ + function wrappedToCollateral(uint256 amount) public view returns(uint256) { uint256 rate = getExchangeRate(); - return amount.mul(rate).mul(10**18).div(10**8); + return amount*rate; } }