Skip to content

Commit

Permalink
Merge pull request #6 from 0xPolygon/dev
Browse files Browse the repository at this point in the history
Dev
  • Loading branch information
gretzke authored Sep 1, 2023
2 parents 0aefc00 + 4e8eb8a commit cd19c4c
Show file tree
Hide file tree
Showing 15 changed files with 208 additions and 399 deletions.
72 changes: 36 additions & 36 deletions .github/workflows/test.yml
Original file line number Diff line number Diff line change
@@ -1,43 +1,43 @@
name: test

on:
push:
branches: [main, dev]
pull_request:
branches: [main, dev, feat/stakeManager]
push:
branches: [main, dev]
pull_request:
branches: [main, dev, feat/stakeManager]

env:
FOUNDRY_PROFILE: ci
FOUNDRY_PROFILE: ci

jobs:
check:
strategy:
fail-fast: true

name: Foundry project
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
submodules: recursive

- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1
with:
version: nightly

- name: Get node.js
uses: actions/setup-node@v3
with:
node-version: 18.x

- name: Run Forge build
run: |
forge --version
forge build --sizes
id: build

- name: Run Forge tests
# ! revert back to FOUNDRY_PROFILE=intense forge test -vvv
run: forge test -vvv
id: test
check:
strategy:
fail-fast: true

name: Foundry project
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v3
with:
submodules: recursive

- name: Install Foundry
uses: foundry-rs/foundry-toolchain@v1
with:
version: nightly

- name: Get node.js
uses: actions/setup-node@v3
with:
node-version: 18.x

- name: Run Forge build
run: |
forge --version
forge build --sizes
id: build

- name: Run Forge tests
# ! revert back to FOUNDRY_PROFILE=intense forge test -vvv
run: forge test -vvv
id: test
5 changes: 5 additions & 0 deletions .prettierignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
.prettierrc
foundry.toml
out
lib/
cache/
7 changes: 7 additions & 0 deletions .prettierrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"printWidth": 120,
"tabWidth": 4,
"useTabs": false,
"singleQuote": false,
"bracketSpacing": false
}
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
@@ -1 +1 @@
# indicia
# indicia
32 changes: 13 additions & 19 deletions script/Deploy.s.sol
Original file line number Diff line number Diff line change
Expand Up @@ -15,43 +15,37 @@ contract Deploy is Script {
deployerPrivateKey = vm.envUint("PRIVATE_KEY");
}

function run(
address matic,
address governance,
address treasury,
address stakeManager
) public {
function run(address matic, address governance, address treasury, address stakeManager) public {
vm.startBroadcast(deployerPrivateKey);

PolygonMigration migration = new PolygonMigration(matic, governance);
address migrationImplementation = address(new PolygonMigration());

address inflationManagerImplementation = address(
new DefaultInflationManager()
);
address inflationManagerProxy = address(
address migrationProxy = address(
new TransparentUpgradeableProxy(
address(inflationManagerImplementation),
migrationImplementation,
governance,
""
abi.encodeCall(PolygonMigration.initialize, matic)
)
);

Polygon polygonToken = new Polygon(
address(migration),
address(inflationManagerProxy)
address inflationManagerImplementation = address(new DefaultInflationManager());
address inflationManagerProxy = address(
new TransparentUpgradeableProxy(address(inflationManagerImplementation), governance, "")
);

Polygon polygonToken = new Polygon(migrationProxy, inflationManagerProxy);

DefaultInflationManager(inflationManagerProxy).initialize(
address(polygonToken),
address(migration),
migrationProxy,
stakeManager,
treasury,
governance
);

migration.setPolygonToken(address(polygonToken));
PolygonMigration(migrationProxy).setPolygonToken(address(polygonToken));

migration.transferOwnership(governance); // governance needs to accept the ownership transfer
PolygonMigration(migrationProxy).transferOwnership(governance); // governance needs to accept the ownership transfer

vm.stopBroadcast();
}
Expand Down
3 changes: 3 additions & 0 deletions slither.config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
{
"filter_paths": "(lib/|test/|script/)"
}
42 changes: 17 additions & 25 deletions src/DefaultInflationManager.sol
Original file line number Diff line number Diff line change
Expand Up @@ -10,19 +10,15 @@ import {SafeERC20} from "openzeppelin-contracts/contracts/token/ERC20/utils/Safe
import {PowUtil} from "./lib/PowUtil.sol";

/// @title Default Inflation Manager
/// @author QEDK <[email protected]> (https://polygon.technology)
/// @author Polygon Labs (@DhairyaSethi, @gretzke, @qedk)
/// @notice A default inflation manager implementation for the Polygon ERC20 token contract on Ethereum L1
/// @dev The contract allows for a 1% mint *each* per year (compounded every second) to the stakeManager and treasury contracts
/// @dev The contract allows for a 1% mint *each* per year (compounded every year) to the stakeManager and treasury contracts
/// @custom:security-contact [email protected]
contract DefaultInflationManager is
Initializable,
Ownable2StepUpgradeable,
IDefaultInflationManager
{
contract DefaultInflationManager is Initializable, Ownable2StepUpgradeable, IDefaultInflationManager {
using SafeERC20 for IPolygon;

// log2(2%pa continuously compounded inflation per second) in 18 decimals(Wad), see _inflatedSupplyAfter
uint256 public constant INTEREST_PER_SECOND_LOG2 = 0.000000000914951192e18;
// log2(2%pa continuously compounded inflation per year) in 18 decimals, see _inflatedSupplyAfter
uint256 public constant INTEREST_PER_YEAR_LOG2 = 0.028569152196770894e18;
uint256 public constant START_SUPPLY = 10_000_000_000e18;

IPolygon public token;
Expand Down Expand Up @@ -61,7 +57,7 @@ contract DefaultInflationManager is
assert(START_SUPPLY == token.totalSupply());

token.safeApprove(migration_, type(uint256).max);

// initial ownership setup bypassing 2 step ownership transfer process
_transferOwnership(owner_);
}

Expand All @@ -79,27 +75,23 @@ contract DefaultInflationManager is
uint256 treasuryAmt = amountToMint / 2;
uint256 stakeManagerAmt = amountToMint - treasuryAmt;

emit TokenMint(amountToMint, msg.sender);

token.mint(address(this), amountToMint);
token.transfer(treasury, treasuryAmt);
token.safeTransfer(treasury, treasuryAmt);
// backconvert POL to MATIC before sending to StakeManager
migration.unmigrateTo(stakeManagerAmt, stakeManager);

emit TokenMint(amountToMint, msg.sender);
migration.unmigrateTo(stakeManager, stakeManagerAmt);
}

/// @notice Returns total supply from compounded inflation after timeElapsed from startTimestamp (deployment)
/// @param timeElapsed The time elapsed since startTimestamp
/// @dev interestRatePerSecond = 1.000000000634195839; 2% per year in seconds with 18 decimals
/// approximate the compounded interest rate per second using x^y = 2^(log2(x)*y)
/// where x is the interest rate per second and y is the number of seconds elapsed since deployment
/// log2(interestRatePerSecond) = 0.000000000914951192 with 18 decimals, as the interest rate does not change, hard code the value
/// @dev interestRatePerYear = 1.02; 2% per year
/// approximate the compounded interest rate using x^y = 2^(log2(x)*y)
/// where x is the interest rate per year and y is the number of seconds elapsed since deployment divided by 365 days in seconds
/// log2(interestRatePerYear) = 0.028569152196770894 with 18 decimals, as the interest rate does not change, hard code the value
/// @return supply total supply from compounded inflation after timeElapsed
function _inflatedSupplyAfter(
uint256 timeElapsed
) private pure returns (uint256 supply) {
uint256 supplyFactor = PowUtil.exp2(
INTEREST_PER_SECOND_LOG2 * timeElapsed
);
function _inflatedSupplyAfter(uint256 timeElapsed) private pure returns (uint256 supply) {
uint256 supplyFactor = PowUtil.exp2((INTEREST_PER_YEAR_LOG2 * timeElapsed) / 365 days);
supply = (supplyFactor * START_SUPPLY) / 1e18;
}

Expand All @@ -108,5 +100,5 @@ contract DefaultInflationManager is
* variables without shifting down storage in the inheritance chain.
* See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps
*/
uint256[49] private __gap;
uint256[50] private __gap;
}
23 changes: 8 additions & 15 deletions src/Polygon.sol
Original file line number Diff line number Diff line change
Expand Up @@ -6,22 +6,18 @@ import {IPolygon} from "./interfaces/IPolygon.sol";
import {IDefaultInflationManager} from "./interfaces/IDefaultInflationManager.sol";

/// @title Polygon ERC20 token
/// @author QEDK <[email protected]> (https://polygon.technology)
/// @author Polygon Labs (@DhairyaSethi, @gretzke, @qedk)
/// @notice This is the Polygon ERC20 token contract on Ethereum L1
/// @dev The contract allows for a 1-to-1 representation between $POL and $MATIC and allows for additional inflation based
/// on hub and treasury requirements
/// @custom:security-contact [email protected]
contract Polygon is ERC20Permit, IPolygon {
uint256 public constant MINT_PER_SECOND_CAP = 0.0000000420e18; // 0.0000042% of POL Supply per second, in 18 decimals
address public immutable inflationManager;
uint256 public constant mintPerSecondCap = 0.00000001e18; // 0.00000001% of POL Supply per second, in 18 deciamls
uint256 public lastMint;

constructor(
address migration_,
address inflationManager_
) ERC20("Polygon", "POL") ERC20Permit("Polygon") {
if (migration_ == address(0) || inflationManager_ == address(0))
revert InvalidAddress();
constructor(address migration_, address inflationManager_) ERC20("Polygon", "POL") ERC20Permit("Polygon") {
if (migration_ == address(0) || inflationManager_ == address(0)) revert InvalidAddress();

inflationManager = inflationManager_;
_mint(migration_, 10_000_000_000e18);
Expand All @@ -33,14 +29,11 @@ contract Polygon is ERC20Permit, IPolygon {
/// @param amount Amount to mint
function mint(address to, uint256 amount) external {
if (msg.sender != inflationManager) revert OnlyInflationManager();
if (lastMint == 0)
lastMint = IDefaultInflationManager(inflationManager)
.startTimestamp();
uint256 lastMintCache = lastMint;
if (lastMintCache == 0) lastMintCache = IDefaultInflationManager(inflationManager).startTimestamp();

uint256 timeElapsedSinceLastMint = block.timestamp - lastMint;
uint256 maxMint = (timeElapsedSinceLastMint *
mintPerSecondCap *
totalSupply()) / 1e18;
uint256 timeElapsedSinceLastMint = block.timestamp - lastMintCache;
uint256 maxMint = (timeElapsedSinceLastMint * MINT_PER_SECOND_CAP * totalSupply()) / 1e18;
if (amount > maxMint) revert MaxMintExceeded(maxMint, amount);

lastMint = block.timestamp;
Expand Down
Loading

0 comments on commit cd19c4c

Please sign in to comment.