Skip to content

Commit 40fff90

Browse files
authored
Merge pull request #29 from 0xPolygon/feat/QoL
Deployment Logging + Docs
2 parents 299c420 + d9990fb commit 40fff90

File tree

25 files changed

+1106
-11
lines changed

25 files changed

+1106
-11
lines changed

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,7 @@
44
/coverage
55
lcov.info
66
.DS_Store
7+
broadcast/
8+
.env
9+
10+
output/31337.json

.nvmrc

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
18.16.0

README.md

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,27 @@ A default implementation is included and this contract will be proxy upgradable
2626

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

29+
## Development
30+
31+
# Setup
32+
33+
- Install foundry: https://book.getfoundry.sh/getting-started/installation
34+
- Install Dependencies: `forge install`
35+
- Build: `forge build`
36+
- Test: `forge test`
37+
38+
# Deployment
39+
40+
1. Ensure .env file is set, `cp .env.example`
41+
2. Populate Enviornment variables: `source .env`
42+
43+
3. We use a forge script to deploy the contracts, and have an additional extract.js script to store a JSON file with
44+
45+
- (mainnet): `forge script script/Deploy.s.sol --broadcast --verify --rpc-url $RPC_URL --private-key $PRIVATE_KEY --etherscan-api-key $ETHERSCAN_API_KEY`
46+
- (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`
47+
48+
4. Run `node script/util/extract.js` to extract deployment information from forge broadcast output (broadcast/latest-run.json specifically).
49+
2950
---
3051

3152
Copyright (C) 2023 PT Services DMCC

docs/.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
book/

docs/book.css

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
table {
2+
margin: 0 auto;
3+
border-collapse: collapse;
4+
width: 100%;
5+
}
6+
7+
table td:first-child {
8+
width: 15%;
9+
}
10+
11+
table td:nth-child(2) {
12+
width: 25%;
13+
}

docs/book.toml

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
[book]
2+
src = "src"
3+
title = ""
4+
5+
[output.html]
6+
no-section-label = true
7+
additional-js = ["solidity.min.js"]
8+
additional-css = ["book.css"]
9+
git-repository-url = "https://github.com/0xPolygon/pol-token"
10+
11+
[output.html.fold]
12+
enable = true

docs/solidity.min.js

Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
hljs.registerLanguage("solidity",(()=>{"use strict";function e(){try{return!0
2+
}catch(e){return!1}}
3+
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|\$)/
4+
;e()&&(a=a.source.replace(/\\b/g,"(?<!\\$)\\b"));var s={className:"number",
5+
begin:a,relevance:0},n={
6+
keyword:"assembly let function if switch case default for leave break continue u256 jump jumpi stop return revert selfdestruct invalid",
7+
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",
8+
literal:"true false"},i={className:"string",
9+
begin:/\bhex'(([0-9a-fA-F]{2}_?)*[0-9a-fA-F]{2})?'/},t={className:"string",
10+
begin:/\bhex"(([0-9a-fA-F]{2}_?)*[0-9a-fA-F]{2})?"/};function r(e){
11+
return e.inherit(e.APOS_STRING_MODE,{begin:/(\bunicode)?'/})}function l(e){
12+
return e.inherit(e.QUOTE_STRING_MODE,{begin:/(\bunicode)?"/})}var o={
13+
SOL_ASSEMBLY_KEYWORDS:n,baseAssembly:e=>{
14+
var a=r(e),o=l(e),c=/[A-Za-z_$][A-Za-z_$0-9.]*/,d=e.inherit(e.TITLE_MODE,{
15+
begin:/[A-Za-z$_][0-9A-Za-z$_]*/,lexemes:c,keywords:n}),u={className:"params",
16+
begin:/\(/,end:/\)/,excludeBegin:!0,excludeEnd:!0,lexemes:c,keywords:n,
17+
contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,a,o,s]},_={
18+
className:"operator",begin:/:=|->/};return{keywords:n,lexemes:c,
19+
contains:[a,o,i,t,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,s,_,{
20+
className:"function",lexemes:c,beginKeywords:"function",end:"{",excludeEnd:!0,
21+
contains:[d,u,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,_]}]}},
22+
solAposStringMode:r,solQuoteStringMode:l,HEX_APOS_STRING_MODE:i,
23+
HEX_QUOTE_STRING_MODE:t,SOL_NUMBER:s,isNegativeLookbehindAvailable:e}
24+
;const{baseAssembly:c,solAposStringMode:d,solQuoteStringMode:u,HEX_APOS_STRING_MODE:_,HEX_QUOTE_STRING_MODE:m,SOL_NUMBER:b,isNegativeLookbehindAvailable:E}=o
25+
;return e=>{for(var a=d(e),s=u(e),n=[],i=0;i<32;i++)n[i]=i+1
26+
;var t=n.map((e=>8*e)),r=[];for(i=0;i<=80;i++)r[i]=i
27+
;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={
28+
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",
29+
literal:"true false wei gwei szabo finney ether seconds minutes hours days weeks years",
30+
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"
31+
},O={className:"operator",begin:/[+\-!~*\/%<>&^|=]/
32+
},C=/[A-Za-z_$][A-Za-z_$0-9]*/,N={className:"params",begin:/\(/,end:/\)/,
33+
excludeBegin:!0,excludeEnd:!0,lexemes:C,keywords:p,
34+
contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,a,s,b,"self"]},f={
35+
begin:/\.\s*/,end:/[^A-Za-z0-9$_\.]/,excludeBegin:!0,excludeEnd:!0,keywords:{
36+
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"
37+
},relevance:2},y=e.inherit(e.TITLE_MODE,{begin:/[A-Za-z$_][0-9A-Za-z$_]*/,
38+
lexemes:C,keywords:p}),w={className:"built_in",
39+
begin:(E()?"(?<!\\$)\\b":"\\b")+"(gas|value|salt)(?=:)"};function x(e,a){return{
40+
begin:(E()?"(?<!\\$)\\b":"\\b")+e+"\\.\\s*",end:/[^A-Za-z0-9$_\.]/,
41+
excludeBegin:!1,excludeEnd:!0,lexemes:C,keywords:{built_in:e+" "+a},
42+
contains:[f],relevance:10}}var h=c(e),v=e.inherit(h,{
43+
contains:h.contains.concat([{begin:/\./,end:/[^A-Za-z0-9$.]/,excludeBegin:!0,
44+
excludeEnd:!0,keywords:{built_in:"slot offset length address selector"},
45+
relevance:2},{begin:/_/,end:/[^A-Za-z0-9$.]/,excludeBegin:!0,excludeEnd:!0,
46+
keywords:{built_in:"slot offset"},relevance:2}])});return{aliases:["sol"],
47+
keywords:p,lexemes:C,
48+
contains:[a,s,_,m,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,b,w,O,{
49+
className:"function",lexemes:C,
50+
beginKeywords:"function modifier event constructor fallback receive error",
51+
end:/[{;]/,excludeEnd:!0,
52+
contains:[y,N,w,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE],illegal:/%/
53+
},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,{
54+
className:"class",lexemes:C,beginKeywords:"contract interface library",end:"{",
55+
excludeEnd:!0,illegal:/[:"\[\]]/,contains:[{beginKeywords:"is",lexemes:C
56+
},y,N,w,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},{lexemes:C,
57+
beginKeywords:"struct enum",end:"{",excludeEnd:!0,illegal:/[:"\[\]]/,
58+
contains:[y,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE]},{
59+
beginKeywords:"import",end:";",lexemes:C,keywords:"import from as",
60+
contains:[y,a,s,_,m,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,O]},{
61+
beginKeywords:"using",end:";",lexemes:C,keywords:"using for",
62+
contains:[y,e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,O]},{className:"meta",
63+
beginKeywords:"pragma",end:";",lexemes:C,keywords:{
64+
keyword:"pragma solidity experimental abicoder",
65+
built_in:"ABIEncoderV2 SMTChecker v1 v2"},
66+
contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,e.inherit(a,{
67+
className:"meta-string"}),e.inherit(s,{className:"meta-string"})]},{
68+
beginKeywords:"assembly",end:/\b\B/,
69+
contains:[e.C_LINE_COMMENT_MODE,e.C_BLOCK_COMMENT_MODE,e.inherit(v,{begin:"{",
70+
end:"}",endsParent:!0,contains:v.contains.concat([e.inherit(v,{begin:"{",
71+
end:"}",contains:v.contains.concat(["self"])})])})]}],illegal:/#/}}})());
72+
73+
// Ugly hack to reload HLJS
74+
hljs.initHighlightingOnLoad();

docs/src/README.md

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
# Polygon Ecosystem Token (POL)
2+
3+
![Test Status](https://github.com/github/docs/actions/workflows/test.yml/badge.svg)
4+
5+
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.
6+
7+
## POL Token Contract
8+
9+
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).
10+
11+
The POL token contract is not upgradable.
12+
13+
[Source Code](https://github.com/0xPolygon/pol-token/tree/main/src/PolygonEcosystemToken.sol)
14+
15+
## Migration Contract
16+
17+
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.
18+
19+
[Source Code](https://github.com/0xPolygon/pol-token/tree/main/src/PolygonMigration.sol)
20+
21+
## Emission Manager Contract
22+
23+
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.
24+
25+
A default implementation is included and this contract will be proxy upgradable by Polygon Governance.
26+
27+
[Source Code](https://github.com/0xPolygon/pol-token/tree/main/src/DefaultEmissionManager.sol)
28+
29+
---
30+
31+
Copyright (C) 2023 PT Services DMCC

docs/src/SUMMARY.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
# Summary
2+
- [Home](README.md)
3+
# src
4+
- [❱ interfaces](src/interfaces/README.md)
5+
- [IDefaultEmissionManager](src/interfaces/IDefaultEmissionManager.sol/interface.IDefaultEmissionManager.md)
6+
- [IPolygonEcosystemToken](src/interfaces/IPolygonEcosystemToken.sol/interface.IPolygonEcosystemToken.md)
7+
- [IPolygonMigration](src/interfaces/IPolygonMigration.sol/interface.IPolygonMigration.md)
8+
- [❱ lib](src/lib/README.md)
9+
- [PowUtil](src/lib/PowUtil.sol/library.PowUtil.md)
10+
- [DefaultEmissionManager](src/DefaultEmissionManager.sol/contract.DefaultEmissionManager.md)
11+
- [PolygonEcosystemToken](src/PolygonEcosystemToken.sol/contract.PolygonEcosystemToken.md)
12+
- [PolygonMigration](src/PolygonMigration.sol/contract.PolygonMigration.md)
Lines changed: 150 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,150 @@
1+
# DefaultEmissionManager
2+
[Git Source](https://github.com/0xPolygon/pol-token/blob/c05c8984ac856501829862c1f6d199208aa77a8e/src/DefaultEmissionManager.sol)
3+
4+
**Inherits:**
5+
Ownable2StepUpgradeable, [IDefaultEmissionManager](/src/interfaces/IDefaultEmissionManager.sol/interface.IDefaultEmissionManager.md)
6+
7+
**Author:**
8+
Polygon Labs (@DhairyaSethi, @gretzke, @qedk)
9+
10+
A default emission manager implementation for the Polygon ERC20 token contract on Ethereum L1
11+
12+
*The contract allows for a 1% mint *each* per year (compounded every year) to the stakeManager and treasury contracts*
13+
14+
15+
## State Variables
16+
### INTEREST_PER_YEAR_LOG2
17+
18+
```solidity
19+
uint256 public constant INTEREST_PER_YEAR_LOG2 = 0.028569152196770894e18;
20+
```
21+
22+
23+
### START_SUPPLY
24+
25+
```solidity
26+
uint256 public constant START_SUPPLY = 10_000_000_000e18;
27+
```
28+
29+
30+
### DEPLOYER
31+
32+
```solidity
33+
address private immutable DEPLOYER;
34+
```
35+
36+
37+
### migration
38+
39+
```solidity
40+
IPolygonMigration public immutable migration;
41+
```
42+
43+
44+
### stakeManager
45+
46+
```solidity
47+
address public immutable stakeManager;
48+
```
49+
50+
51+
### treasury
52+
53+
```solidity
54+
address public immutable treasury;
55+
```
56+
57+
58+
### token
59+
60+
```solidity
61+
IPolygonEcosystemToken public token;
62+
```
63+
64+
65+
### startTimestamp
66+
67+
```solidity
68+
uint256 public startTimestamp;
69+
```
70+
71+
72+
### __gap
73+
*This empty reserved space is put in place to allow future versions to add new
74+
variables without shifting down storage in the inheritance chain.
75+
See https://docs.openzeppelin.com/contracts/4.x/upgradeable#storage_gaps*
76+
77+
78+
```solidity
79+
uint256[50] private __gap;
80+
```
81+
82+
83+
## Functions
84+
### constructor
85+
86+
87+
```solidity
88+
constructor(address migration_, address stakeManager_, address treasury_);
89+
```
90+
91+
### initialize
92+
93+
94+
```solidity
95+
function initialize(address token_, address owner_) external initializer;
96+
```
97+
98+
### mint
99+
100+
Allows anyone to mint tokens to the stakeManager and treasury contracts based on current emission rates
101+
102+
*Minting is done based on totalSupply diffs between the currentTotalSupply (maintained on POL, which includes any
103+
previous mints) and the newSupply (calculated based on the time elapsed since deployment)*
104+
105+
106+
```solidity
107+
function mint() external;
108+
```
109+
110+
### inflatedSupplyAfter
111+
112+
Returns total supply from compounded emission after timeElapsed from startTimestamp (deployment)
113+
114+
*interestRatePerYear = 1.02; 2% per year
115+
approximate the compounded interest rate using x^y = 2^(log2(x)*y)
116+
where x is the interest rate per year and y is the number of seconds elapsed since deployment divided by 365 days in seconds
117+
log2(interestRatePerYear) = 0.028569152196770894 with 18 decimals, as the interest rate does not change, hard code the value*
118+
119+
120+
```solidity
121+
function inflatedSupplyAfter(uint256 timeElapsed) public pure returns (uint256 supply);
122+
```
123+
**Parameters**
124+
125+
|Name|Type|Description|
126+
|----|----|-----------|
127+
|`timeElapsed`|`uint256`|The time elapsed since startTimestamp|
128+
129+
**Returns**
130+
131+
|Name|Type|Description|
132+
|----|----|-----------|
133+
|`supply`|`uint256`|total supply from compounded emission after timeElapsed|
134+
135+
136+
### getVersion
137+
138+
Returns the implementation version
139+
140+
141+
```solidity
142+
function getVersion() external pure returns (string memory);
143+
```
144+
**Returns**
145+
146+
|Name|Type|Description|
147+
|----|----|-----------|
148+
|`<none>`|`string`|Version string|
149+
150+

0 commit comments

Comments
 (0)