From 4262994941c048d872feb1e7164737b307c68056 Mon Sep 17 00:00:00 2001 From: Andrea Franz Date: Wed, 2 Oct 2024 15:08:05 +0200 Subject: [PATCH 1/8] feat(XPToken): add base XPToken with IXPProvider interface --- src/XPToken.sol | 72 ++++++++++++++++++++++++++++++++++ src/interfaces/IXPProvider.sol | 7 ++++ 2 files changed, 79 insertions(+) create mode 100644 src/XPToken.sol create mode 100644 src/interfaces/IXPProvider.sol diff --git a/src/XPToken.sol b/src/XPToken.sol new file mode 100644 index 0000000..62f788d --- /dev/null +++ b/src/XPToken.sol @@ -0,0 +1,72 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.26; + +import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; +import { IXPProvider } from "./interfaces/IXPProvider.sol"; + +contract XPToken is Ownable { + string public name = "XP Token"; + string public symbol = "XP"; + uint8 public decimals = 18; + + uint256 public totalSupply; + + IXPProvider[] public xpProviders; + + error XPToken__TransfersNotAllowed(); + error XPProvider__IndexOutOfBounds(); + + constructor(uint256 _totalSupply) Ownable(msg.sender) { + totalSupply = _totalSupply; + } + + function setTotalSupply(uint256 _totalSupply) external onlyOwner { + totalSupply = _totalSupply; + } + + function addXPProvider(IXPProvider provider) external onlyOwner { + xpProviders.push(provider); + } + + function removeXPProvider(uint256 index) external onlyOwner { + if (index >= xpProviders.length) { + revert XPProvider__IndexOutOfBounds(); + } + + xpProviders[index] = xpProviders[xpProviders.length - 1]; + xpProviders.pop(); + } + + function balanceOf(address account) public view returns (uint256) { + uint256 userTotalXP = 0; + uint256 systemTotalXP = 0; + + for (uint256 i = 0; i < xpProviders.length; i++) { + IXPProvider provider = xpProviders[i]; + userTotalXP += provider.getUserXP(account); + systemTotalXP += provider.getTotalXP(); + } + + if (systemTotalXP == 0) { + return 0; + } + + return (totalSupply * userTotalXP) / systemTotalXP; + } + + function transfer(address, uint256) external pure returns (bool) { + revert XPToken__TransfersNotAllowed(); + } + + function approve(address, uint256) external pure returns (bool) { + revert XPToken__TransfersNotAllowed(); + } + + function transferFrom(address, address, uint256) external pure returns (bool) { + revert XPToken__TransfersNotAllowed(); + } + + function allowance(address, address) external pure returns (uint256) { + return 0; + } +} diff --git a/src/interfaces/IXPProvider.sol b/src/interfaces/IXPProvider.sol new file mode 100644 index 0000000..16c3e09 --- /dev/null +++ b/src/interfaces/IXPProvider.sol @@ -0,0 +1,7 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.26; + +interface IXPProvider { + function getTotalXP() external view returns (uint256); + function getUserXP(address user) external view returns (uint256); +} From c9e44dea70ff92dc07ed77beef564c014eb33907 Mon Sep 17 00:00:00 2001 From: Andrea Franz Date: Tue, 8 Oct 2024 10:56:41 +0200 Subject: [PATCH 2/8] chore: update libs --- lib/forge-std | 2 +- lib/openzeppelin-contracts | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/forge-std b/lib/forge-std index 1714bee..035de35 160000 --- a/lib/forge-std +++ b/lib/forge-std @@ -1 +1 @@ -Subproject commit 1714bee72e286e73f76e320d110e0eaf5c4e649d +Subproject commit 035de35f5e366c8d6ed142aec4ccb57fe2dd87d4 diff --git a/lib/openzeppelin-contracts b/lib/openzeppelin-contracts index dbb6104..8b591ba 160000 --- a/lib/openzeppelin-contracts +++ b/lib/openzeppelin-contracts @@ -1 +1 @@ -Subproject commit dbb6104ce834628e473d2173bbc9d47f81a9eec3 +Subproject commit 8b591baef460523e5ca1c53712c464bcc1a1c467 From 5b1d529e3dd07bb2eccdfeb881e3bbc801b4bf30 Mon Sep 17 00:00:00 2001 From: Andrea Franz Date: Tue, 8 Oct 2024 10:57:15 +0200 Subject: [PATCH 3/8] chore(XPToken): use XP Contribution for providers functions --- src/XPToken.sol | 22 +++++++++++++--------- src/interfaces/IXPProvider.sol | 4 ++-- 2 files changed, 15 insertions(+), 11 deletions(-) diff --git a/src/XPToken.sol b/src/XPToken.sol index 62f788d..422d64c 100644 --- a/src/XPToken.sol +++ b/src/XPToken.sol @@ -5,9 +5,9 @@ import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; import { IXPProvider } from "./interfaces/IXPProvider.sol"; contract XPToken is Ownable { - string public name = "XP Token"; - string public symbol = "XP"; - uint8 public decimals = 18; + string public constant name = "XP Token"; + string public constant symbol = "XP"; + uint256 public constant decimals = 18; uint256 public totalSupply; @@ -37,21 +37,25 @@ contract XPToken is Ownable { xpProviders.pop(); } + function getXPProviders() external view returns (IXPProvider[] memory) { + return xpProviders; + } + function balanceOf(address account) public view returns (uint256) { - uint256 userTotalXP = 0; - uint256 systemTotalXP = 0; + uint256 userTotalXPContribution = 0; + uint256 totalXPContribution = 0; for (uint256 i = 0; i < xpProviders.length; i++) { IXPProvider provider = xpProviders[i]; - userTotalXP += provider.getUserXP(account); - systemTotalXP += provider.getTotalXP(); + userTotalXPContribution += provider.getUserXPContribution(account); + totalXPContribution += provider.getTotalXPContribution(); } - if (systemTotalXP == 0) { + if (totalXPContribution == 0) { return 0; } - return (totalSupply * userTotalXP) / systemTotalXP; + return (totalSupply * userTotalXPContribution) / totalXPContribution; } function transfer(address, uint256) external pure returns (bool) { diff --git a/src/interfaces/IXPProvider.sol b/src/interfaces/IXPProvider.sol index 16c3e09..fa50f5a 100644 --- a/src/interfaces/IXPProvider.sol +++ b/src/interfaces/IXPProvider.sol @@ -2,6 +2,6 @@ pragma solidity ^0.8.26; interface IXPProvider { - function getTotalXP() external view returns (uint256); - function getUserXP(address user) external view returns (uint256); + function getTotalXPContribution() external view returns (uint256); + function getUserXPContribution(address user) external view returns (uint256); } From 92ae1d66e00e8db2890f8506098e498bd2a3633d Mon Sep 17 00:00:00 2001 From: Andrea Franz Date: Tue, 8 Oct 2024 10:58:36 +0200 Subject: [PATCH 4/8] test(XPToken): add tests --- test/XPToken.t.sol | 126 ++++++++++++++++++++++++++++++++++ test/mocks/XPProviderMock.sol | 26 +++++++ 2 files changed, 152 insertions(+) create mode 100644 test/XPToken.t.sol create mode 100644 test/mocks/XPProviderMock.sol diff --git a/test/XPToken.t.sol b/test/XPToken.t.sol new file mode 100644 index 0000000..d85826f --- /dev/null +++ b/test/XPToken.t.sol @@ -0,0 +1,126 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.26; + +import { Test } from "forge-std/Test.sol"; +import { XPToken } from "../src/XPToken.sol"; +import { XPProviderMock } from "./mocks/XPProviderMock.sol"; +import { IXPProvider } from "../src/interfaces/IXPProvider.sol"; +import { Ownable } from "@openzeppelin/contracts/access/Ownable.sol"; + +contract XPTokenTest is Test { + XPToken xpToken; + address owner = address(0x1); + address alice = address(0x2); + address bob = address(0x3); + + XPProviderMock provider1; + XPProviderMock provider2; + + function setUp() public { + vm.prank(owner); + xpToken = new XPToken(1000e18); + + provider1 = new XPProviderMock(); + provider2 = new XPProviderMock(); + + vm.prank(owner); + xpToken.addXPProvider(provider1); + + vm.prank(owner); + xpToken.addXPProvider(provider2); + } + + function testAddXPProviderOnlyOwner() public { + XPProviderMock provider3 = new XPProviderMock(); + + vm.prank(alice); + vm.expectPartialRevert(Ownable.OwnableUnauthorizedAccount.selector); + xpToken.addXPProvider(provider3); + + vm.prank(owner); + xpToken.addXPProvider(provider3); + + IXPProvider[] memory providers = xpToken.getXPProviders(); + assertEq(providers.length, 3); + assertEq(address(providers[0]), address(provider1)); + assertEq(address(providers[1]), address(provider2)); + assertEq(address(providers[2]), address(provider3)); + } + + function testRemoveXPProviderOnlyOwner() public { + vm.prank(alice); + vm.expectPartialRevert(Ownable.OwnableUnauthorizedAccount.selector); + xpToken.removeXPProvider(0); + + vm.prank(owner); + xpToken.removeXPProvider(0); + + IXPProvider[] memory providers = xpToken.getXPProviders(); + assertEq(providers.length, 1); + assertEq(address(providers[0]), address(provider2)); + } + + function testRemoveXPProviderIndexOutOfBounds() public { + vm.prank(owner); + vm.expectRevert(XPToken.XPProvider__IndexOutOfBounds.selector); + xpToken.removeXPProvider(10); + } + + function testTotalSupply() public view { + uint256 totalSupply = xpToken.totalSupply(); + assertEq(totalSupply, 1000 ether); + } + + function testBalanceOfWithNoSystemTotalXP() public view { + uint256 aliceBalance = xpToken.balanceOf(alice); + assertEq(aliceBalance, 0); + + uint256 bobBalance = xpToken.balanceOf(bob); + assertEq(bobBalance, 0); + } + + function testBalanceOf() public { + provider1.setUserXPContribution(alice, 100e18); + provider1.setTotalXPContribution(1000e18); + + provider2.setUserXPContribution(alice, 200e18); + provider2.setTotalXPContribution(2000e18); + + // Expected balance calculation + uint256 userTotalXP = 100e18 + 200e18; + uint256 systemTotalXP = 1000e18 + 2000e18; + + uint256 expectedBalance = (xpToken.totalSupply() * userTotalXP) / systemTotalXP; + + uint256 balance = xpToken.balanceOf(alice); + assertEq(balance, expectedBalance); + } + + function testSetTotalSupplyOnlyOwner() public { + uint256 totalSupply = xpToken.totalSupply(); + assertEq(totalSupply, 1000e18); + + vm.prank(alice); + vm.expectPartialRevert(Ownable.OwnableUnauthorizedAccount.selector); + xpToken.setTotalSupply(2000e18); + + vm.prank(owner); + xpToken.setTotalSupply(2000e18); + totalSupply = xpToken.totalSupply(); + assertEq(totalSupply, 2000e18); + } + + function testTransfersNotAllowed() public { + vm.expectRevert(XPToken.XPToken__TransfersNotAllowed.selector); + xpToken.transfer(alice, 100e18); + + vm.expectRevert(XPToken.XPToken__TransfersNotAllowed.selector); + xpToken.approve(alice, 100e18); + + vm.expectRevert(XPToken.XPToken__TransfersNotAllowed.selector); + xpToken.transferFrom(alice, bob, 100e18); + + uint256 allowance = xpToken.allowance(alice, bob); + assertEq(allowance, 0); + } +} diff --git a/test/mocks/XPProviderMock.sol b/test/mocks/XPProviderMock.sol new file mode 100644 index 0000000..6b606ad --- /dev/null +++ b/test/mocks/XPProviderMock.sol @@ -0,0 +1,26 @@ +// SPDX-License-Identifier: MIT +pragma solidity ^0.8.26; + +import { IXPProvider } from "../../src/interfaces/IXPProvider.sol"; + +contract XPProviderMock is IXPProvider { + mapping(address => uint256) public userXPContribution; + + uint256 public totalXPContribution; + + function setUserXPContribution(address user, uint256 xp) external { + userXPContribution[user] = xp; + } + + function setTotalXPContribution(uint256 xp) external { + totalXPContribution = xp; + } + + function getUserXPContribution(address account) external view override returns (uint256) { + return userXPContribution[account]; + } + + function getTotalXPContribution() external view override returns (uint256) { + return totalXPContribution; + } +} From bae9fecc421177061803848588c37d4b789069f4 Mon Sep 17 00:00:00 2001 From: Andrea Franz Date: Tue, 8 Oct 2024 11:27:22 +0200 Subject: [PATCH 5/8] chore(XPToken): add certora base config --- .../{certora.conf => confs/RewardsStreamerMP.conf} | 1 - certora/confs/XPToken.conf | 13 +++++++++++++ certora/specs/RewardsStreamerMP.spec | 2 +- certora/specs/XPToken.spec | 3 +++ package.json | 4 +++- 5 files changed, 20 insertions(+), 3 deletions(-) rename certora/{certora.conf => confs/RewardsStreamerMP.conf} (99%) create mode 100644 certora/confs/XPToken.conf create mode 100644 certora/specs/XPToken.spec diff --git a/certora/certora.conf b/certora/confs/RewardsStreamerMP.conf similarity index 99% rename from certora/certora.conf rename to certora/confs/RewardsStreamerMP.conf index 80b0d47..4123e8d 100644 --- a/certora/certora.conf +++ b/certora/confs/RewardsStreamerMP.conf @@ -11,4 +11,3 @@ "@openzeppelin=lib/openzeppelin-contracts" ] } - diff --git a/certora/confs/XPToken.conf b/certora/confs/XPToken.conf new file mode 100644 index 0000000..9bcbb48 --- /dev/null +++ b/certora/confs/XPToken.conf @@ -0,0 +1,13 @@ +{ + "files": ["src/XPToken.sol"], + "msg": "Verifying XPToken.sol", + "rule_sanity": "basic", + "verify": "XPToken:certora/specs/XPToken.spec", + "wait_for_results": "all", + "optimistic_loop": true, + "loop_iter": "3", + "packages": [ + "forge-std=lib/forge-std/src", + "@openzeppelin=lib/openzeppelin-contracts" + ] +} diff --git a/certora/specs/RewardsStreamerMP.spec b/certora/specs/RewardsStreamerMP.spec index 6d54f28..4be8f4d 100644 --- a/certora/specs/RewardsStreamerMP.spec +++ b/certora/specs/RewardsStreamerMP.spec @@ -1,3 +1,3 @@ -rule checkIdOutputIsAlwaysEqualToInput { +rule test { assert true; } diff --git a/certora/specs/XPToken.spec b/certora/specs/XPToken.spec new file mode 100644 index 0000000..4be8f4d --- /dev/null +++ b/certora/specs/XPToken.spec @@ -0,0 +1,3 @@ +rule test { + assert true; +} diff --git a/package.json b/package.json index a762524..ceb6d04 100644 --- a/package.json +++ b/package.json @@ -23,7 +23,9 @@ "scripts": { "clean": "rm -rf cache out", "lint": "pnpm lint:sol && pnpm prettier:check", - "verify": "certoraRun certora/certora.conf", + "verify": "pnpm verify:rewards_streamer_mp && pnpm verify:xp_token", + "verify:rewards_streamer_mp": "certoraRun certora/confs/RewardsStreamerMP.conf", + "verify:xp_token": "certoraRun certora/confs/XPToken.conf", "lint:sol": "forge fmt --check && pnpm solhint {script,src,test,certora}/**/*.sol", "prettier:check": "prettier --check **/*.{json,md,yml} --ignore-path=.prettierignore", "prettier:write": "prettier --write **/*.{json,md,yml} --ignore-path=.prettierignore", From b963336826e642a19973089b50caa01b6a1fa9c7 Mon Sep 17 00:00:00 2001 From: Andrea Franz Date: Wed, 9 Oct 2024 10:22:24 +0200 Subject: [PATCH 6/8] chore(XPToken): use share instead of contribution in IXPProvider function names --- src/XPToken.sol | 4 ++-- src/interfaces/IXPProvider.sol | 4 ++-- test/XPToken.t.sol | 8 ++++---- test/mocks/XPProviderMock.sol | 20 ++++++++++---------- 4 files changed, 18 insertions(+), 18 deletions(-) diff --git a/src/XPToken.sol b/src/XPToken.sol index 422d64c..b918ad2 100644 --- a/src/XPToken.sol +++ b/src/XPToken.sol @@ -47,8 +47,8 @@ contract XPToken is Ownable { for (uint256 i = 0; i < xpProviders.length; i++) { IXPProvider provider = xpProviders[i]; - userTotalXPContribution += provider.getUserXPContribution(account); - totalXPContribution += provider.getTotalXPContribution(); + userTotalXPContribution += provider.getUserXPShare(account); + totalXPContribution += provider.getTotalXPShares(); } if (totalXPContribution == 0) { diff --git a/src/interfaces/IXPProvider.sol b/src/interfaces/IXPProvider.sol index fa50f5a..cdad5f1 100644 --- a/src/interfaces/IXPProvider.sol +++ b/src/interfaces/IXPProvider.sol @@ -2,6 +2,6 @@ pragma solidity ^0.8.26; interface IXPProvider { - function getTotalXPContribution() external view returns (uint256); - function getUserXPContribution(address user) external view returns (uint256); + function getTotalXPShares() external view returns (uint256); + function getUserXPShare(address user) external view returns (uint256); } diff --git a/test/XPToken.t.sol b/test/XPToken.t.sol index d85826f..a7c42e6 100644 --- a/test/XPToken.t.sol +++ b/test/XPToken.t.sol @@ -80,11 +80,11 @@ contract XPTokenTest is Test { } function testBalanceOf() public { - provider1.setUserXPContribution(alice, 100e18); - provider1.setTotalXPContribution(1000e18); + provider1.setUserXPShare(alice, 100e18); + provider1.setTotalXPShares(1000e18); - provider2.setUserXPContribution(alice, 200e18); - provider2.setTotalXPContribution(2000e18); + provider2.setUserXPShare(alice, 200e18); + provider2.setTotalXPShares(2000e18); // Expected balance calculation uint256 userTotalXP = 100e18 + 200e18; diff --git a/test/mocks/XPProviderMock.sol b/test/mocks/XPProviderMock.sol index 6b606ad..1776641 100644 --- a/test/mocks/XPProviderMock.sol +++ b/test/mocks/XPProviderMock.sol @@ -4,23 +4,23 @@ pragma solidity ^0.8.26; import { IXPProvider } from "../../src/interfaces/IXPProvider.sol"; contract XPProviderMock is IXPProvider { - mapping(address => uint256) public userXPContribution; + mapping(address => uint256) public userXPShare; - uint256 public totalXPContribution; + uint256 public totalXPShares; - function setUserXPContribution(address user, uint256 xp) external { - userXPContribution[user] = xp; + function setUserXPShare(address user, uint256 xp) external { + userXPShare[user] = xp; } - function setTotalXPContribution(uint256 xp) external { - totalXPContribution = xp; + function setTotalXPShares(uint256 xp) external { + totalXPShares = xp; } - function getUserXPContribution(address account) external view override returns (uint256) { - return userXPContribution[account]; + function getUserXPShare(address account) external view override returns (uint256) { + return userXPShare[account]; } - function getTotalXPContribution() external view override returns (uint256) { - return totalXPContribution; + function getTotalXPShares() external view override returns (uint256) { + return totalXPShares; } } From c4dba087964745ef00566eadf7704fb443659a31 Mon Sep 17 00:00:00 2001 From: Andrea Franz Date: Thu, 10 Oct 2024 18:21:21 +0200 Subject: [PATCH 7/8] chore(XPToken): rename local variables to use the suffix share instead of contribution --- src/XPToken.sol | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/XPToken.sol b/src/XPToken.sol index b918ad2..853a975 100644 --- a/src/XPToken.sol +++ b/src/XPToken.sol @@ -42,20 +42,20 @@ contract XPToken is Ownable { } function balanceOf(address account) public view returns (uint256) { - uint256 userTotalXPContribution = 0; - uint256 totalXPContribution = 0; + uint256 userTotalXPShare = 0; + uint256 totalXPShares = 0; for (uint256 i = 0; i < xpProviders.length; i++) { IXPProvider provider = xpProviders[i]; - userTotalXPContribution += provider.getUserXPShare(account); - totalXPContribution += provider.getTotalXPShares(); + userTotalXPShare += provider.getUserXPShare(account); + totalXPShares += provider.getTotalXPShares(); } - if (totalXPContribution == 0) { + if (totalXPShares == 0) { return 0; } - return (totalSupply * userTotalXPContribution) / totalXPContribution; + return (totalSupply * userTotalXPShare) / totalXPShares; } function transfer(address, uint256) external pure returns (bool) { From c77c79576a4082950120b2c8a266ebb70806f198 Mon Sep 17 00:00:00 2001 From: Andrea Franz Date: Thu, 10 Oct 2024 18:23:11 +0200 Subject: [PATCH 8/8] chore: update gas reports --- .gas-report | 58 +++++++++++++++++++++++++++++++++++++------------ .gas-snapshot | 60 +++++++++++++++++++++++++++++++-------------------- 2 files changed, 81 insertions(+), 37 deletions(-) diff --git a/.gas-report b/.gas-report index aecda42..673a871 100644 --- a/.gas-report +++ b/.gas-report @@ -15,21 +15,40 @@ | src/RewardsStreamerMP.sol:RewardsStreamerMP contract | | | | | | |------------------------------------------------------|-----------------|--------|--------|--------|---------| | Deployment Cost | Deployment Size | | | | | -| 1105804 | 4983 | | | | | +| 1114894 | 5025 | | | | | | Function Name | min | avg | median | max | # calls | | MAX_LOCKING_PERIOD | 228 | 228 | 228 | 228 | 18 | -| MAX_MULTIPLIER | 229 | 229 | 229 | 229 | 24 | +| MAX_MULTIPLIER | 274 | 274 | 274 | 274 | 34 | | MIN_LOCKING_PERIOD | 229 | 229 | 229 | 229 | 8 | -| SCALE_FACTOR | 251 | 251 | 251 | 251 | 28 | -| accountedRewards | 373 | 963 | 373 | 2373 | 44 | -| getUserInfo | 1553 | 1553 | 1553 | 1553 | 41 | -| potentialMP | 330 | 330 | 330 | 330 | 44 | -| rewardIndex | 373 | 418 | 373 | 2373 | 44 | -| stake | 167821 | 215459 | 228608 | 249401 | 35 | -| totalMP | 352 | 352 | 352 | 352 | 44 | -| totalStaked | 330 | 330 | 330 | 330 | 44 | +| MP_RATE_PER_YEAR | 231 | 231 | 231 | 231 | 2 | +| SCALE_FACTOR | 251 | 251 | 251 | 251 | 30 | +| accountedRewards | 373 | 921 | 373 | 2373 | 62 | +| getUserInfo | 1531 | 1531 | 1531 | 1531 | 61 | +| potentialMP | 330 | 330 | 330 | 330 | 62 | +| rewardIndex | 373 | 405 | 373 | 2373 | 62 | +| stake | 167787 | 215055 | 228586 | 249379 | 43 | +| totalMP | 352 | 352 | 352 | 352 | 62 | +| totalStaked | 373 | 373 | 373 | 373 | 62 | | unstake | 75511 | 107650 | 110519 | 134250 | 10 | -| updateGlobalState | 30008 | 69159 | 80335 | 80335 | 10 | +| updateGlobalState | 30008 | 57540 | 50309 | 80335 | 22 | +| updateUserMP | 29022 | 38080 | 40060 | 40060 | 16 | + + +| src/XPToken.sol:XPToken contract | | | | | | +|----------------------------------|-----------------|-------|--------|-------|---------| +| Deployment Cost | Deployment Size | | | | | +| 725645 | 3153 | | | | | +| Function Name | min | avg | median | max | # calls | +| addXPProvider | 23968 | 57184 | 51091 | 68191 | 18 | +| allowance | 488 | 488 | 488 | 488 | 1 | +| approve | 390 | 390 | 390 | 390 | 1 | +| balanceOf | 8808 | 14560 | 11066 | 23808 | 3 | +| getXPProviders | 1033 | 3286 | 3286 | 5539 | 2 | +| removeXPProvider | 23665 | 28074 | 25780 | 34777 | 3 | +| setTotalSupply | 23792 | 26266 | 26266 | 28740 | 2 | +| totalSupply | 363 | 1863 | 2363 | 2363 | 4 | +| transfer | 411 | 411 | 411 | 411 | 1 | +| transferFrom | 521 | 521 | 521 | 521 | 1 | | test/mocks/MockToken.sol:MockToken contract | | | | | | @@ -37,11 +56,22 @@ | Deployment Cost | Deployment Size | | | | | | 639406 | 3369 | | | | | | Function Name | min | avg | median | max | # calls | -| approve | 46346 | 46346 | 46346 | 46346 | 120 | -| balanceOf | 561 | 1327 | 561 | 2561 | 201 | -| mint | 51284 | 58124 | 51284 | 68384 | 120 | +| approve | 46346 | 46346 | 46346 | 46346 | 150 | +| balanceOf | 561 | 1321 | 561 | 2561 | 271 | +| mint | 51284 | 58124 | 51284 | 68384 | 150 | | transfer | 34390 | 48070 | 51490 | 51490 | 10 | +| test/mocks/XPProviderMock.sol:XPProviderMock contract | | | | | | +|-------------------------------------------------------|-----------------|-------|--------|-------|---------| +| Deployment Cost | Deployment Size | | | | | +| 152145 | 489 | | | | | +| Function Name | min | avg | median | max | # calls | +| getTotalXPShares | 302 | 968 | 302 | 2302 | 6 | +| getUserXPShare | 504 | 1837 | 2504 | 2504 | 6 | +| setTotalXPShares | 43632 | 43632 | 43632 | 43632 | 2 | +| setUserXPShare | 43900 | 43900 | 43900 | 43900 | 2 | + + diff --git a/.gas-snapshot b/.gas-snapshot index 11a2fd5..ca08778 100644 --- a/.gas-snapshot +++ b/.gas-snapshot @@ -1,24 +1,38 @@ -IntegrationTest:testStake() (gas: 1378213) +IntegrationTest:testStake() (gas: 1378182) RewardsStreamerTest:testStake() (gas: 869874) -StakeTest:test_StakeMultipleAccounts() (gas: 438756) -StakeTest:test_StakeMultipleAccountsAndRewards() (gas: 586002) -StakeTest:test_StakeMultipleAccountsWithMinLockUp() (gas: 449214) -StakeTest:test_StakeMultipleAccountsWithRandomLockUp() (gas: 470881) -StakeTest:test_StakeOneAccount() (gas: 267795) -StakeTest:test_StakeOneAccountAndRewards() (gas: 415039) -StakeTest:test_StakeOneAccountWithMaxLockUp() (gas: 284120) -StakeTest:test_StakeOneAccountWithMinLockUp() (gas: 284152) -StakeTest:test_StakeOneAccountWithRandomLockUp() (gas: 284196) -UnstakeTest:test_StakeMultipleAccounts() (gas: 438778) -UnstakeTest:test_StakeMultipleAccountsAndRewards() (gas: 586002) -UnstakeTest:test_StakeMultipleAccountsWithMinLockUp() (gas: 449214) -UnstakeTest:test_StakeMultipleAccountsWithRandomLockUp() (gas: 470903) -UnstakeTest:test_StakeOneAccount() (gas: 267795) -UnstakeTest:test_StakeOneAccountAndRewards() (gas: 415061) -UnstakeTest:test_StakeOneAccountWithMaxLockUp() (gas: 284120) -UnstakeTest:test_StakeOneAccountWithMinLockUp() (gas: 284152) -UnstakeTest:test_StakeOneAccountWithRandomLockUp() (gas: 284196) -UnstakeTest:test_UnstakeMultipleAccounts() (gas: 616327) -UnstakeTest:test_UnstakeMultipleAccountsAndRewards() (gas: 937593) -UnstakeTest:test_UnstakeOneAccount() (gas: 446306) -UnstakeTest:test_UnstakeOneAccountAndRewards() (gas: 557157) \ No newline at end of file +StakeTest:test_StakeMultipleAccounts() (gas: 438733) +StakeTest:test_StakeMultipleAccountsAndRewards() (gas: 586000) +StakeTest:test_StakeMultipleAccountsMPIncreasesPotentialMPDecreases() (gas: 761311) +StakeTest:test_StakeMultipleAccountsWithMinLockUp() (gas: 449348) +StakeTest:test_StakeMultipleAccountsWithRandomLockUp() (gas: 471037) +StakeTest:test_StakeOneAccount() (gas: 267794) +StakeTest:test_StakeOneAccountAndRewards() (gas: 415103) +StakeTest:test_StakeOneAccountMPIncreasesPotentialMPDecreases() (gas: 484709) +StakeTest:test_StakeOneAccountReachingMPLimit() (gas: 446674) +StakeTest:test_StakeOneAccountWithMaxLockUp() (gas: 284253) +StakeTest:test_StakeOneAccountWithMinLockUp() (gas: 284263) +StakeTest:test_StakeOneAccountWithRandomLockUp() (gas: 284307) +UnstakeTest:test_StakeMultipleAccounts() (gas: 438755) +UnstakeTest:test_StakeMultipleAccountsAndRewards() (gas: 586045) +UnstakeTest:test_StakeMultipleAccountsMPIncreasesPotentialMPDecreases() (gas: 761245) +UnstakeTest:test_StakeMultipleAccountsWithMinLockUp() (gas: 449348) +UnstakeTest:test_StakeMultipleAccountsWithRandomLockUp() (gas: 471059) +UnstakeTest:test_StakeOneAccount() (gas: 267794) +UnstakeTest:test_StakeOneAccountAndRewards() (gas: 415125) +UnstakeTest:test_StakeOneAccountMPIncreasesPotentialMPDecreases() (gas: 484709) +UnstakeTest:test_StakeOneAccountReachingMPLimit() (gas: 446696) +UnstakeTest:test_StakeOneAccountWithMaxLockUp() (gas: 284276) +UnstakeTest:test_StakeOneAccountWithMinLockUp() (gas: 284263) +UnstakeTest:test_StakeOneAccountWithRandomLockUp() (gas: 284352) +UnstakeTest:test_UnstakeMultipleAccounts() (gas: 616281) +UnstakeTest:test_UnstakeMultipleAccountsAndRewards() (gas: 937677) +UnstakeTest:test_UnstakeOneAccount() (gas: 446369) +UnstakeTest:test_UnstakeOneAccountAndRewards() (gas: 557220) +XPTokenTest:testAddXPProviderOnlyOwner() (gas: 285732) +XPTokenTest:testBalanceOf() (gas: 210530) +XPTokenTest:testBalanceOfWithNoSystemTotalXP() (gas: 45808) +XPTokenTest:testRemoveXPProviderIndexOutOfBounds() (gas: 36277) +XPTokenTest:testRemoveXPProviderOnlyOwner() (gas: 72074) +XPTokenTest:testSetTotalSupplyOnlyOwner() (gas: 70544) +XPTokenTest:testTotalSupply() (gas: 10507) +XPTokenTest:testTransfersNotAllowed() (gas: 20634)