-
Notifications
You must be signed in to change notification settings - Fork 7
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
6 changed files
with
124 additions
and
25 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,12 +11,12 @@ import {PowUtil} from "./lib/PowUtil.sol"; | |
/// @title Default Emission Manager | ||
/// @author Polygon Labs (@DhairyaSethi, @gretzke, @qedk, @simonDos) | ||
/// @notice A default emission manager implementation for the Polygon ERC20 token contract on Ethereum L1 | ||
/// @dev The contract allows for a 3% mint per year (compounded). 2% staking layer and 1% treasury | ||
/// @dev The contract allows for a 2.5% mint per year (compounded). 1.5% staking layer and 1% treasury | ||
/// @custom:security-contact [email protected] | ||
contract DefaultEmissionManager is Ownable2StepUpgradeable, IDefaultEmissionManager { | ||
using SafeERC20 for IPolygonEcosystemToken; | ||
|
||
uint256 public constant INTEREST_PER_YEAR_LOG2 = 0.04264433740849372e18; | ||
uint256 public constant INTEREST_PER_YEAR_LOG2 = 0.03562390973072122e18; // log2(1.025) | ||
uint256 public constant START_SUPPLY = 10_000_000_000e18; | ||
address private immutable DEPLOYER; | ||
|
||
|
@@ -27,6 +27,9 @@ contract DefaultEmissionManager is Ownable2StepUpgradeable, IDefaultEmissionMana | |
IPolygonEcosystemToken public token; | ||
uint256 public startTimestamp; | ||
|
||
// NEW STORAGE 1.2.0 | ||
uint256 public START_SUPPLY_1_2_0; | ||
|
||
constructor(address migration_, address stakeManager_, address treasury_) { | ||
if (migration_ == address(0) || stakeManager_ == address(0) || treasury_ == address(0)) revert InvalidAddress(); | ||
DEPLOYER = msg.sender; | ||
|
@@ -38,6 +41,11 @@ contract DefaultEmissionManager is Ownable2StepUpgradeable, IDefaultEmissionMana | |
_disableInitializers(); | ||
} | ||
|
||
function reinitialize() external reinitializer(2) { | ||
START_SUPPLY_1_2_0 = token.totalSupply(); | ||
startTimestamp = block.timestamp; | ||
} | ||
|
||
function initialize(address token_, address owner_) external initializer { | ||
// prevent front-running since we can't initialize on proxy deployment | ||
if (DEPLOYER != msg.sender) revert(); | ||
|
@@ -62,7 +70,8 @@ contract DefaultEmissionManager is Ownable2StepUpgradeable, IDefaultEmissionMana | |
uint256 amountToMint = newSupply - currentSupply; | ||
if (amountToMint == 0) return; // no minting required | ||
|
||
uint256 treasuryAmt = amountToMint / 3; | ||
// 2/5 of 2.5% is 1% going to the treasury | ||
uint256 treasuryAmt = amountToMint * 2 / 5; | ||
uint256 stakeManagerAmt = amountToMint - treasuryAmt; | ||
|
||
emit TokenMint(amountToMint, msg.sender); | ||
|
@@ -77,15 +86,15 @@ contract DefaultEmissionManager is Ownable2StepUpgradeable, IDefaultEmissionMana | |
} | ||
|
||
/// @inheritdoc IDefaultEmissionManager | ||
function inflatedSupplyAfter(uint256 timeElapsed) public pure returns (uint256 supply) { | ||
function inflatedSupplyAfter(uint256 timeElapsed) public view returns (uint256 supply) { | ||
uint256 supplyFactor = PowUtil.exp2((INTEREST_PER_YEAR_LOG2 * timeElapsed) / 365 days); | ||
supply = (supplyFactor * START_SUPPLY) / 1e18; | ||
supply = (supplyFactor * START_SUPPLY_1_2_0) / 1e18; | ||
} | ||
|
||
/// @inheritdoc IDefaultEmissionManager | ||
function version() external pure returns (string memory) { | ||
return "1.1.0"; | ||
return "1.2.0"; | ||
} | ||
|
||
uint256[48] private __gap; | ||
uint256[47] private __gap; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,80 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity 0.8.21; | ||
|
||
import {PolygonEcosystemToken} from "src/PolygonEcosystemToken.sol"; | ||
import {DefaultEmissionManager} from "src/DefaultEmissionManager.sol"; | ||
import {PolygonMigration} from "src/PolygonMigration.sol"; | ||
import {ERC20PresetMinterPauser} from "openzeppelin-contracts/contracts/token/ERC20/presets/ERC20PresetMinterPauser.sol"; | ||
import { | ||
ProxyAdmin, | ||
TransparentUpgradeableProxy, | ||
ITransparentUpgradeableProxy | ||
} from "openzeppelin-contracts/contracts/proxy/transparent/ProxyAdmin.sol"; | ||
import {Test} from "forge-std/Test.sol"; | ||
|
||
// this test forks mainnet and tests the upgradeability of DefaultEmissionManagerProxy | ||
|
||
contract DefaultEmissionManagerTest is Test { | ||
uint256 mainnetFork; | ||
|
||
address POLYGON_PROTOCOL_COUNCIL = 0x37D085ca4a24f6b29214204E8A8666f12cf19516; | ||
address EM_PROXY = 0xbC9f74b3b14f460a6c47dCdDFd17411cBc7b6c53; | ||
address COMMUNITY_TREASURY = 0x2ff25495d77f380d5F65B95F103181aE8b1cf898; | ||
address EM_PROXY_ADMIN = 0xEBea33f2c92D03556b417F4F572B2FbbE62C39c3; | ||
PolygonEcosystemToken pol = PolygonEcosystemToken(0x455e53CBB86018Ac2B8092FdCd39d8444aFFC3F6); | ||
|
||
uint256 NEW_INTEREST_PER_YEAR_LOG2 = 0.03562390973072122e18; // log2(1.025) | ||
|
||
string[] internal inputs = new string[](5); | ||
|
||
function setUp() public { | ||
string memory MAINNET_RPC_URL = vm.envString("MAINNET_RPC_URL"); | ||
mainnetFork = vm.createFork(MAINNET_RPC_URL); | ||
} | ||
|
||
function testUpgrade() external { | ||
vm.selectFork(mainnetFork); | ||
|
||
address newTreasury = makeAddr("newTreasury"); | ||
|
||
DefaultEmissionManager emProxy = DefaultEmissionManager(EM_PROXY); | ||
|
||
assertEq(emProxy.treasury(), COMMUNITY_TREASURY); | ||
|
||
address migration = address(emProxy.migration()); | ||
address stakeManager = emProxy.stakeManager(); | ||
|
||
DefaultEmissionManager newEmImpl = new DefaultEmissionManager(migration, stakeManager, newTreasury); | ||
|
||
ProxyAdmin admin = ProxyAdmin(EM_PROXY_ADMIN); | ||
|
||
vm.prank(POLYGON_PROTOCOL_COUNCIL); | ||
|
||
admin.upgradeAndCall( | ||
ITransparentUpgradeableProxy(address(emProxy)), | ||
address(newEmImpl), | ||
abi.encodeWithSelector(DefaultEmissionManager.reinitialize.selector) | ||
); | ||
|
||
// initialize can still not be called | ||
vm.expectRevert("Initializable: contract is already initialized"); | ||
emProxy.initialize(makeAddr("token"), msg.sender); | ||
|
||
assertEq(pol.totalSupply(), emProxy.START_SUPPLY_1_2_0()); | ||
assertEq(block.timestamp, emProxy.startTimestamp()); | ||
|
||
// emission is now 2.5% | ||
inputs[0] = "node"; | ||
inputs[1] = "test/util/calc.js"; | ||
inputs[2] = vm.toString(uint256(365 days)); | ||
inputs[3] = vm.toString(pol.totalSupply()); | ||
// vm.ffi executes the js script which contains the new emission rate | ||
uint256 newSupply = abi.decode(vm.ffi(inputs), (uint256)); | ||
assertApproxEqAbs(newSupply, emProxy.inflatedSupplyAfter(365 days), 1e20); | ||
|
||
// treasury has been updated | ||
assertEq(emProxy.treasury(), newTreasury); | ||
// emission has been updated | ||
assertEq(emProxy.INTEREST_PER_YEAR_LOG2(), NEW_INTEREST_PER_YEAR_LOG2); | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters