Skip to content

Commit f9fc158

Browse files
committed
wample
1 parent 5cf7289 commit f9fc158

File tree

8 files changed

+1438
-68
lines changed

8 files changed

+1438
-68
lines changed

.gitignore

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -78,4 +78,7 @@ node_modules
7878
#Buidler files
7979
cache
8080
artifacts
81-
.openzeppelin
81+
.openzeppelin
82+
83+
# env
84+
.env

.nvmrc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
12
1+
16

.solhint.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,6 @@
44
"rules": {
55
"prettier/prettier": "error",
66
"not-rely-on-time": "off",
7-
"max-line-length": ["error", 100]
7+
"max-line-length": ["error", 105]
88
}
99
}

contracts/WAMPL.sol

Lines changed: 215 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,215 @@
1+
// SPDX-License-Identifier: GPL-3.0-or-later
2+
3+
pragma solidity 0.8.4;
4+
5+
import {IERC20} from "@openzeppelin/contracts/token/ERC20/IERC20.sol";
6+
7+
import {SafeERC20} from "@openzeppelin/contracts/token/ERC20/utils/SafeERC20.sol";
8+
import {ERC20} from "@openzeppelin/contracts/token/ERC20/ERC20.sol";
9+
import {ERC20Permit} from "@openzeppelin/contracts/token/ERC20/extensions/draft-ERC20Permit.sol";
10+
11+
/**
12+
* @title WAMPL (Wrapped AMPL).
13+
*
14+
* @dev A fixed-balance ERC-20 wrapper for the AMPL rebasing token.
15+
*
16+
* Users deposit AMPL into this contract and are minted wAMPL.
17+
*
18+
* Each account's wAMPL balance represents the fixed percentage ownership
19+
* of AMPL's market cap.
20+
*
21+
* For example: 100K wAMPL => 1% of the AMPL market cap
22+
* when the AMPL supply is 100M, 100K wAMPL will be redeemable for 1M AMPL
23+
* when the AMPL supply is 500M, 100K wAMPL will be redeemable for 5M AMPL
24+
* and so on.
25+
*
26+
* We call wAMPL the "wrapper" token and AMPL the "underlying" or "wrapped" token.
27+
*/
28+
contract WAMPL is ERC20, ERC20Permit {
29+
using SafeERC20 for IERC20;
30+
31+
//--------------------------------------------------------------------------
32+
// Constants
33+
34+
/// @dev The maximum wAMPL supply.
35+
uint256 public constant MAX_WAMPL_SUPPLY = 10000000 * (10**18);
36+
37+
//--------------------------------------------------------------------------
38+
// Attributes
39+
40+
/// @dev The reference to the AMPL token.
41+
address private immutable _ampl;
42+
43+
//--------------------------------------------------------------------------
44+
45+
/// @param ampl The AMPL ERC20 token address.
46+
/// @param name_ The wAMPL ERC20 name.
47+
/// @param symbol_ The wAMPL ERC20 symbol.
48+
constructor(
49+
address ampl,
50+
string memory name_,
51+
string memory symbol_
52+
) ERC20(name_, symbol_) ERC20Permit(name_) {
53+
_ampl = ampl;
54+
}
55+
56+
//--------------------------------------------------------------------------
57+
// WAMPL write methods
58+
59+
/// @notice Transfers AMPLs from {msg.sender} and mints wAMPLs.
60+
///
61+
/// @param amples The amount of AMPLs to deposit.
62+
/// @return The number of wAMPLs minted.
63+
function deposit(uint256 amples) external returns (uint256) {
64+
uint256 wamples = _ampleToWample(amples, _queryAMPLSupply());
65+
66+
IERC20(_ampl).safeTransferFrom(_msgSender(), address(this), amples);
67+
68+
_mint(_msgSender(), wamples);
69+
70+
return wamples;
71+
}
72+
73+
/// @notice Transfers AMPLs from {msg.sender} and mints wAMPLs,
74+
/// to the specified beneficiary.
75+
///
76+
/// @param to The beneficiary wallet.
77+
/// @param amples The amount of AMPLs to deposit.
78+
/// @return The number of wAMPLs minted.
79+
function depositTo(address to, uint256 amples) external returns (uint256) {
80+
uint256 wamples = _ampleToWample(amples, _queryAMPLSupply());
81+
82+
IERC20(_ampl).safeTransferFrom(_msgSender(), address(this), amples);
83+
84+
_mint(to, wamples);
85+
86+
return wamples;
87+
}
88+
89+
/// @notice Burns wAMPLs from {msg.sender} and transfers AMPLs back.
90+
///
91+
/// @param amples The amount of AMPLs to withdraw.
92+
/// @return The number of burnt wAMPLs.
93+
function withdraw(uint256 amples) external returns (uint256) {
94+
uint256 wamples = _ampleToWample(amples, _queryAMPLSupply());
95+
96+
_burn(_msgSender(), wamples);
97+
98+
IERC20(_ampl).safeTransfer(_msgSender(), amples);
99+
100+
return wamples;
101+
}
102+
103+
/// @notice Burns wAMPLs from {msg.sender} and transfers AMPLs back,
104+
/// to the specified beneficiary.
105+
///
106+
/// @param to The beneficiary wallet.
107+
/// @param amples The amount of AMPLs to withdraw.
108+
/// @return The number of burnt wAMPLs.
109+
function withdrawTo(address to, uint256 amples) external returns (uint256) {
110+
uint256 wamples = _ampleToWample(amples, _queryAMPLSupply());
111+
112+
_burn(_msgSender(), wamples);
113+
114+
IERC20(_ampl).safeTransfer(to, amples);
115+
116+
return wamples;
117+
}
118+
119+
/// @notice Burns all wAMPLs from {msg.sender} and transfers AMPLs back.
120+
///
121+
/// @return The number of burnt wAMPLs.
122+
function withdrawAll() external returns (uint256) {
123+
uint256 wamples = balanceOf(_msgSender());
124+
125+
uint256 amples = _wampleToAmple(wamples, _queryAMPLSupply());
126+
127+
_burn(_msgSender(), wamples);
128+
129+
IERC20(_ampl).safeTransfer(_msgSender(), amples);
130+
131+
return wamples;
132+
}
133+
134+
/// @notice Burns all wAMPLs from {msg.sender} and transfers AMPLs back,
135+
/// to the specified beneficiary.
136+
///
137+
/// @param to The beneficiary wallet.
138+
/// @return The number of burnt wAMPLs.
139+
function withdrawAllTo(address to) external returns (uint256) {
140+
uint256 wamples = balanceOf(_msgSender());
141+
142+
uint256 amples = _wampleToAmple(wamples, _queryAMPLSupply());
143+
144+
_burn(_msgSender(), wamples);
145+
146+
IERC20(_ampl).safeTransfer(to, amples);
147+
148+
return wamples;
149+
}
150+
151+
//--------------------------------------------------------------------------
152+
// WAMPL view methods
153+
154+
/// @return The address of the underlying "wrapped" token ie) AMPL.
155+
function underlying() external view returns (address) {
156+
return _ampl;
157+
}
158+
159+
/// @return The total AMPLs held by this contract.
160+
function totalUnderlying() external view returns (uint256) {
161+
return _queryUnderlyingBalance();
162+
}
163+
164+
/// @param owner The account address.
165+
/// @return The AMPL balance redeemable by the owner.
166+
function balanceOfUnderlying(address owner) external view returns (uint256) {
167+
return _wampleToAmple(balanceOf(owner), _queryAMPLSupply());
168+
}
169+
170+
/// @param amples The amount of AMPL tokens.
171+
/// @return The amount of wAMPL tokens mintable.
172+
function underlyingToWrapper(uint256 amples) external view returns (uint256) {
173+
return _ampleToWample(amples, _queryAMPLSupply());
174+
}
175+
176+
/// @param wamples The amount of wAMPL tokens.
177+
/// @return The amount of AMPL tokens redeemable.
178+
function wrapperToUnderlying(uint256 wamples) external view returns (uint256) {
179+
return _wampleToAmple(wamples, _queryAMPLSupply());
180+
}
181+
182+
//--------------------------------------------------------------------------
183+
// Private methods
184+
185+
/// @dev Queries the current total supply of AMPL.
186+
function _queryAMPLSupply() private view returns (uint256) {
187+
return IERC20(_ampl).totalSupply();
188+
}
189+
190+
/// @dev Queries the AMPL balance of this contract.
191+
function _queryUnderlyingBalance() private view returns (uint256) {
192+
return IERC20(_ampl).balanceOf(address(this));
193+
}
194+
195+
//--------------------------------------------------------------------------
196+
// Pure methods
197+
198+
/// @dev Converts AMPLs to wAMPL amount.
199+
function _ampleToWample(uint256 amples, uint256 totalAMPLSupply)
200+
private
201+
pure
202+
returns (uint256)
203+
{
204+
return (amples * MAX_WAMPL_SUPPLY) / totalAMPLSupply;
205+
}
206+
207+
/// @dev Converts wAMPLs amount to AMPLs.
208+
function _wampleToAmple(uint256 wamples, uint256 totalAMPLSupply)
209+
private
210+
pure
211+
returns (uint256)
212+
{
213+
return (wamples * totalAMPLSupply) / MAX_WAMPL_SUPPLY;
214+
}
215+
}

hardhat.config.ts

Lines changed: 18 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -3,29 +3,41 @@ import { HardhatUserConfig } from 'hardhat/config'
33
import '@nomiclabs/hardhat-ethers'
44
import '@nomiclabs/hardhat-waffle'
55
import '@openzeppelin/hardhat-upgrades'
6-
import "@nomiclabs/hardhat-etherscan";
6+
import '@nomiclabs/hardhat-etherscan'
77
import 'solidity-coverage'
88
import 'hardhat-gas-reporter'
99

1010
require('./scripts/deploy')
1111

1212
export default {
1313
etherscan: {
14-
apiKey: process.env.ETHERSCAN_API_KEY
14+
apiKey: process.env.ETHERSCAN_API_KEY,
1515
},
1616
networks: {
17+
hardhat: {
18+
initialBaseFeePerGas: 0,
19+
},
1720
rinkeby: {
18-
url: `https://rinkeby.infura.io/v3/${process.env.INFURA_SECRET}`
21+
url: `https://rinkeby.infura.io/v3/${process.env.INFURA_SECRET}`,
1922
},
2023
kovan: {
21-
url: `https://kovan.infura.io/v3/${process.env.INFURA_SECRET}`
24+
url: `https://kovan.infura.io/v3/${process.env.INFURA_SECRET}`,
2225
},
2326
mainnet: {
24-
url: `https://mainnet.infura.io/v3/${process.env.INFURA_SECRET}`
25-
}
27+
url: `https://mainnet.infura.io/v3/${process.env.INFURA_SECRET}`,
28+
},
2629
},
2730
solidity: {
2831
compilers: [
32+
{
33+
version: '0.8.4',
34+
settings: {
35+
optimizer: {
36+
enabled: true,
37+
runs: 200,
38+
},
39+
},
40+
},
2941
{
3042
version: '0.7.6',
3143
settings: {

package.json

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
"profile": "REPORT_GAS=true yarn hardhat test test/unit/*.ts",
2424
"coverage": "yarn hardhat coverage --testfiles 'test/unit/*.ts'",
2525
"format": "yarn prettier --config .prettierrc --write '**/*.ts' 'contracts/**/*.sol'",
26-
"lint": "yarn solhint 'contracts/**/*.sol'"
26+
"lint": "yarn format && yarn solhint 'contracts/**/*.sol'"
2727
},
2828
"pre-commit": [
2929
"format",
@@ -42,7 +42,7 @@
4242
"ethereum-waffle": "^3.2.1",
4343
"ethereumjs-util": "^7.0.7",
4444
"ethers": "5.0.18",
45-
"hardhat": "^2.0.6",
45+
"hardhat": "^2.6.1",
4646
"pre-commit": "^1.2.2",
4747
"prettier": "^2.1.1",
4848
"prettier-plugin-solidity": "^1.0.0-alpha.57",
@@ -52,9 +52,10 @@
5252
"solidity-coverage": "^0.7.13",
5353
"stochasm": "^0.5.0",
5454
"ts-node": "^9.0.0",
55-
"typescript": "^4.0.2"
55+
"typescript": "^4.0.2",
56+
"hardhat-gas-reporter": "^1.0.4"
5657
},
5758
"dependencies": {
58-
"hardhat-gas-reporter": "^1.0.4"
59+
"@openzeppelin/contracts": "^4.3.0"
5960
}
6061
}

0 commit comments

Comments
 (0)