Skip to content

Commit

Permalink
Merge pull request #29 from 0xPolygon/feat/QoL
Browse files Browse the repository at this point in the history
Deployment Logging + Docs
  • Loading branch information
gretzke authored Oct 4, 2023
2 parents 299c420 + d9990fb commit 40fff90
Show file tree
Hide file tree
Showing 25 changed files with 1,106 additions and 11 deletions.
4 changes: 4 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -4,3 +4,7 @@
/coverage
lcov.info
.DS_Store
broadcast/
.env

output/31337.json
1 change: 1 addition & 0 deletions .nvmrc
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
18.16.0
21 changes: 21 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,27 @@ A default implementation is included and this contract will be proxy upgradable

[Source Code](https://github.com/0xPolygon/pol-token/tree/main/src/DefaultEmissionManager.sol)

## Development

# Setup

- Install foundry: https://book.getfoundry.sh/getting-started/installation
- Install Dependencies: `forge install`
- Build: `forge build`
- Test: `forge test`

# Deployment

1. Ensure .env file is set, `cp .env.example`
2. Populate Enviornment variables: `source .env`

3. We use a forge script to deploy the contracts, and have an additional extract.js script to store a JSON file with

- (mainnet): `forge script script/Deploy.s.sol --broadcast --verify --rpc-url $RPC_URL --private-key $PRIVATE_KEY --etherscan-api-key $ETHERSCAN_API_KEY`
- (testnet, goerli for example): `forge script script/Deploy.s.sol --broadcast --verify --rpc-url $RPC_URL --private-key $PRIVATE_KEY --verifier-url https://api-goerli.etherscan.io/api --chain-id 5`

4. Run `node script/util/extract.js` to extract deployment information from forge broadcast output (broadcast/latest-run.json specifically).

---

Copyright (C) 2023 PT Services DMCC
1 change: 1 addition & 0 deletions docs/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
book/
13 changes: 13 additions & 0 deletions docs/book.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
table {
margin: 0 auto;
border-collapse: collapse;
width: 100%;
}

table td:first-child {
width: 15%;
}

table td:nth-child(2) {
width: 25%;
}
12 changes: 12 additions & 0 deletions docs/book.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[book]
src = "src"
title = ""

[output.html]
no-section-label = true
additional-js = ["solidity.min.js"]
additional-css = ["book.css"]
git-repository-url = "https://github.com/0xPolygon/pol-token"

[output.html.fold]
enable = true
74 changes: 74 additions & 0 deletions docs/solidity.min.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
hljs.registerLanguage("solidity",(()=>{"use strict";function e(){try{return!0
}catch(e){return!1}}
var a=/-?(\b0[xX]([a-fA-F0-9]_?)*[a-fA-F0-9]|(\b[1-9](_?\d)*(\.((\d_?)*\d)?)?|\.\d(_?\d)*)([eE][-+]?\d(_?\d)*)?|\b0)(?!\w|\$)/
;e()&&(a=a.source.replace(/\\b/g,"(?<!\\$)\\b"));var s={className:"number",
begin:a,relevance:0},n={
keyword:"assembly let function if switch case default for leave break continue u256 jump jumpi stop return revert selfdestruct invalid",
built_in:"add sub mul div sdiv mod smod exp not lt gt slt sgt eq iszero and or xor byte shl shr sar addmod mulmod signextend keccak256 pc pop dup1 dup2 dup3 dup4 dup5 dup6 dup7 dup8 dup9 dup10 dup11 dup12 dup13 dup14 dup15 dup16 swap1 swap2 swap3 swap4 swap5 swap6 swap7 swap8 swap9 swap10 swap11 swap12 swap13 swap14 swap15 swap16 mload mstore mstore8 sload sstore msize gas address balance selfbalance caller callvalue calldataload calldatasize calldatacopy codesize codecopy extcodesize extcodecopy returndatasize returndatacopy extcodehash create create2 call callcode delegatecall staticcall log0 log1 log2 log3 log4 chainid origin gasprice basefee blockhash coinbase timestamp number difficulty gaslimit",
literal:"true false"},i={className:"string",
begin:/\bhex'(([0-9a-fA-F]{2}_?)*[0-9a-fA-F]{2})?'/},t={className:"string",
begin:/\bhex"(([0-9a-fA-F]{2}_?)*[0-9a-fA-F]{2})?"/};function r(e){
return e.inherit(e.APOS_STRING_MODE,{begin:/(\bunicode)?'/})}function l(e){
return e.inherit(e.QUOTE_STRING_MODE,{begin:/(\bunicode)?"/})}var o={
SOL_ASSEMBLY_KEYWORDS:n,baseAssembly:e=>{
var a=r(e),o=l(e),c=/[A-Za-z_$][A-Za-z_$0-9.]*/,d=e.inherit(e.TITLE_MODE,{
begin:/[A-Za-z$_][0-9A-Za-z$_]*/,lexemes:c,keywords:n}),u={className:"params",
begin:/\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,lexemes:c,keywords:n,
contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,a,o,s]},_={
className:"operator",begin:/:=|->/};return{keywords:n,lexemes:c,
contains:[a,o,i,t,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,s,_,{
className:"function",lexemes:c,beginKeywords:"function",end:"{",excludeEnd:!0,
contains:[d,u,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,_]}]}},
solAposStringMode:r,solQuoteStringMode:l,HEX_APOS_STRING_MODE:i,
HEX_QUOTE_STRING_MODE:t,SOL_NUMBER:s,isNegativeLookbehindAvailable:e}
;const{baseAssembly:c,solAposStringMode:d,solQuoteStringMode:u,HEX_APOS_STRING_MODE:_,HEX_QUOTE_STRING_MODE:m,SOL_NUMBER:b,isNegativeLookbehindAvailable:E}=o
;return e=>{for(var a=d(e),s=u(e),n=[],i=0;i<32;i++)n[i]=i+1
;var t=n.map((e=>8*e)),r=[];for(i=0;i<=80;i++)r[i]=i
;var l=n.map((e=>"bytes"+e)).join(" ")+" ",o=t.map((e=>"uint"+e)).join(" ")+" ",g=t.map((e=>"int"+e)).join(" ")+" ",M=[].concat.apply([],t.map((e=>r.map((a=>e+"x"+a))))),p={
keyword:"var bool string int uint "+g+o+"byte bytes "+l+"fixed ufixed "+M.map((e=>"fixed"+e)).join(" ")+" "+M.map((e=>"ufixed"+e)).join(" ")+" enum struct mapping address new delete if else for while continue break return throw emit try catch revert unchecked _ function modifier event constructor fallback receive error virtual override constant immutable anonymous indexed storage memory calldata external public internal payable pure view private returns import from as using pragma contract interface library is abstract type assembly",
literal:"true false wei gwei szabo finney ether seconds minutes hours days weeks years",
built_in:"self this super selfdestruct suicide now msg block tx abi blockhash gasleft assert require Error Panic sha3 sha256 keccak256 ripemd160 ecrecover addmod mulmod log0 log1 log2 log3 log4"
},O={className:"operator",begin:/[+\-!~*\/%<>&^|=]/
},C=/[A-Za-z_$][A-Za-z_$0-9]*/,N={className:"params",begin:/\(/,end:/\)/,
excludeBegin:!0,excludeEnd:!0,lexemes:C,keywords:p,
contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,a,s,b,"self"]},f={
begin:/\.\s*/,end:/[^A-Za-z0-9$_\.]/,excludeBegin:!0,excludeEnd:!0,keywords:{
built_in:"gas value selector address length push pop send transfer call callcode delegatecall staticcall balance code codehash wrap unwrap name creationCode runtimeCode interfaceId min max"
},relevance:2},y=e.inherit(e.TITLE_MODE,{begin:/[A-Za-z$_][0-9A-Za-z$_]*/,
lexemes:C,keywords:p}),w={className:"built_in",
begin:(E()?"(?<!\\$)\\b":"\\b")+"(gas|value|salt)(?=:)"};function x(e,a){return{
begin:(E()?"(?<!\\$)\\b":"\\b")+e+"\\.\\s*",end:/[^A-Za-z0-9$_\.]/,
excludeBegin:!1,excludeEnd:!0,lexemes:C,keywords:{built_in:e+" "+a},
contains:[f],relevance:10}}var h=c(e),v=e.inherit(h,{
contains:h.contains.concat([{begin:/\./,end:/[^A-Za-z0-9$.]/,excludeBegin:!0,
excludeEnd:!0,keywords:{built_in:"slot offset length address selector"},
relevance:2},{begin:/_/,end:/[^A-Za-z0-9$.]/,excludeBegin:!0,excludeEnd:!0,
keywords:{built_in:"slot offset"},relevance:2}])});return{aliases:["sol"],
keywords:p,lexemes:C,
contains:[a,s,_,m,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,b,w,O,{
className:"function",lexemes:C,
beginKeywords:"function modifier event constructor fallback receive error",
end:/[{;]/,excludeEnd:!0,
contains:[y,N,w,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE],illegal:/%/
},x("msg","gas value data sender sig"),x("block","blockhash coinbase difficulty gaslimit basefee number timestamp chainid"),x("tx","gasprice origin"),x("abi","decode encode encodePacked encodeWithSelector encodeWithSignature encodeCall"),x("bytes","concat"),f,{
className:"class",lexemes:C,beginKeywords:"contract interface library",end:"{",
excludeEnd:!0,illegal:/[:"\[\]]/,contains:[{beginKeywords:"is",lexemes:C
},y,N,w,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},{lexemes:C,
beginKeywords:"struct enum",end:"{",excludeEnd:!0,illegal:/[:"\[\]]/,
contains:[y,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},{
beginKeywords:"import",end:";",lexemes:C,keywords:"import from as",
contains:[y,a,s,_,m,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,O]},{
beginKeywords:"using",end:";",lexemes:C,keywords:"using for",
contains:[y,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,O]},{className:"meta",
beginKeywords:"pragma",end:";",lexemes:C,keywords:{
keyword:"pragma solidity experimental abicoder",
built_in:"ABIEncoderV2 SMTChecker v1 v2"},
contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,e.inherit(a,{
className:"meta-string"}),e.inherit(s,{className:"meta-string"})]},{
beginKeywords:"assembly",end:/\b\B/,
contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,e.inherit(v,{begin:"{",
end:"}",endsParent:!0,contains:v.contains.concat([e.inherit(v,{begin:"{",
end:"}",contains:v.contains.concat(["self"])})])})]}],illegal:/#/}}})());

// Ugly hack to reload HLJS
hljs.initHighlightingOnLoad();
31 changes: 31 additions & 0 deletions docs/src/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
# Polygon Ecosystem Token (POL)

![Test Status](https://github.com/github/docs/actions/workflows/test.yml/badge.svg)

The Polygon Ecosystem Token is intended as an upgrade to the [MATIC token](https://etherscan.io/address/0x7d1afa7b718fb893db30a3abc0cfc608aacfebb0). It consists of a [token contract](https://github.com/0xPolygon/pol-token/tree/main/src/PolygonEcosystemToken.sol), [migration contract](https://github.com/0xPolygon/pol-token/tree/main/src/PolygonMigration.sol), and an [emission manager contract](https://github.com/0xPolygon/pol-token/tree/main/src/DefaultEmissionManager.sol). Together, this set of contracts is proposed in [PIP-17](https://github.com/maticnetwork/Polygon-Improvement-Proposals/blob/main/PIPs/PIP-17.md) to Polygon Governance as a step forward in functionality for the polygon ecosystem.

## POL Token Contract

POL is broadly based on the MIT-licensed OpenZeppelin ERC-20 implementations which provide support for the default ERC-20 standard, along with some non-standard functions for allowance modifications. The implementation also provides support for [EIP-2612: Signature-Based Permit Approvals](https://eips.ethereum.org/EIPS/eip-2612)-style is supported).

The POL token contract is not upgradable.

[Source Code](https://github.com/0xPolygon/pol-token/tree/main/src/PolygonEcosystemToken.sol)

## Migration Contract

The migration contract allows 1-to-1 migrations between MATIC and POL using the `migrate` and `unmigrate` functions respectively. This migration contract is ownable, and the owner has the ability to disable the `ummigrate` functionality. For both actions, [EIP-2612 Permit](https://eips.ethereum.org/EIPS/eip-2612)-style is supported.

[Source Code](https://github.com/0xPolygon/pol-token/tree/main/src/PolygonMigration.sol)

## Emission Manager Contract

The role of the Emission Manager is to have the exclusive ability to mint new POL tokens. It has the ability to calculate token emissions based upon a yearly rate, and then dispurse them linearly to a configured target `StakeManager`. For safety, there is a cap on the number of tokens mintable per second as defined by [`mintPerSecondCap`](https://github.com/0xPolygon/pol-token/blob/main/src/PolygonEcosystemToken.sol#L16) on the token implementation.

A default implementation is included and this contract will be proxy upgradable by Polygon Governance.

[Source Code](https://github.com/0xPolygon/pol-token/tree/main/src/DefaultEmissionManager.sol)

---

Copyright (C) 2023 PT Services DMCC
12 changes: 12 additions & 0 deletions docs/src/SUMMARY.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Summary
- [Home](README.md)
# src
- [❱ interfaces](src/interfaces/README.md)
- [IDefaultEmissionManager](src/interfaces/IDefaultEmissionManager.sol/interface.IDefaultEmissionManager.md)
- [IPolygonEcosystemToken](src/interfaces/IPolygonEcosystemToken.sol/interface.IPolygonEcosystemToken.md)
- [IPolygonMigration](src/interfaces/IPolygonMigration.sol/interface.IPolygonMigration.md)
- [❱ lib](src/lib/README.md)
- [PowUtil](src/lib/PowUtil.sol/library.PowUtil.md)
- [DefaultEmissionManager](src/DefaultEmissionManager.sol/contract.DefaultEmissionManager.md)
- [PolygonEcosystemToken](src/PolygonEcosystemToken.sol/contract.PolygonEcosystemToken.md)
- [PolygonMigration](src/PolygonMigration.sol/contract.PolygonMigration.md)
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
# DefaultEmissionManager
[Git Source](https://github.com/0xPolygon/pol-token/blob/c05c8984ac856501829862c1f6d199208aa77a8e/src/DefaultEmissionManager.sol)

**Inherits:**
Ownable2StepUpgradeable, [IDefaultEmissionManager](/src/interfaces/IDefaultEmissionManager.sol/interface.IDefaultEmissionManager.md)

**Author:**
Polygon Labs (@DhairyaSethi, @gretzke, @qedk)

A default emission manager implementation for the Polygon ERC20 token contract on Ethereum L1

*The contract allows for a 1% mint *each* per year (compounded every year) to the stakeManager and treasury contracts*


## State Variables
### INTEREST_PER_YEAR_LOG2

```solidity
uint256 public constant INTEREST_PER_YEAR_LOG2 = 0.028569152196770894e18;
```


### START_SUPPLY

```solidity
uint256 public constant START_SUPPLY = 10_000_000_000e18;
```


### DEPLOYER

```solidity
address private immutable DEPLOYER;
```


### migration

```solidity
IPolygonMigration public immutable migration;
```


### stakeManager

```solidity
address public immutable stakeManager;
```


### treasury

```solidity
address public immutable treasury;
```


### token

```solidity
IPolygonEcosystemToken public token;
```


### startTimestamp

```solidity
uint256 public startTimestamp;
```


### __gap
*This empty reserved space is put in place to allow future versions to add new
variables without shifting down storage in the inheritance chain.
See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps*


```solidity
uint256[50] private __gap;
```


## Functions
### constructor


```solidity
constructor(address migration_, address stakeManager_, address treasury_);
```

### initialize


```solidity
function initialize(address token_, address owner_) external initializer;
```

### mint

Allows anyone to mint tokens to the stakeManager and treasury contracts based on current emission rates

*Minting is done based on totalSupply diffs between the currentTotalSupply (maintained on POL, which includes any
previous mints) and the newSupply (calculated based on the time elapsed since deployment)*


```solidity
function mint() external;
```

### inflatedSupplyAfter

Returns total supply from compounded emission after timeElapsed from startTimestamp (deployment)

*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*


```solidity
function inflatedSupplyAfter(uint256 timeElapsed) public pure returns (uint256 supply);
```
**Parameters**

|Name|Type|Description|
|----|----|-----------|
|`timeElapsed`|`uint256`|The time elapsed since startTimestamp|

**Returns**

|Name|Type|Description|
|----|----|-----------|
|`supply`|`uint256`|total supply from compounded emission after timeElapsed|


### getVersion

Returns the implementation version


```solidity
function getVersion() external pure returns (string memory);
```
**Returns**

|Name|Type|Description|
|----|----|-----------|
|`<none>`|`string`|Version string|


Loading

0 comments on commit 40fff90

Please sign in to comment.