Created
January 20, 2022 22:45
-
-
Save samlaf/12150c9cf6f4c33b818e728359b7be0a to your computer and use it in GitHub Desktop.
toy implementation of compound and cEth (rebasing tokens)
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
// SPDX-License-Identifier: GPL-3.0 | |
pragma solidity >=0.7.0 <0.9.0; | |
import "@openzeppelin/contracts/token/ERC20/IERC20.sol"; | |
import "@openzeppelin/contracts/access/Ownable.sol"; | |
import "hardhat/console.sol"; | |
contract cEth is IERC20, Ownable { | |
uint256 public totalStaticSupply; | |
mapping (address => uint256) public staticSupply; | |
uint256 public supplyMultiplier = 1; | |
function totalSupply() public view returns (uint256) { | |
return totalStaticSupply * supplyMultiplier; | |
} | |
function balanceOf(address account) public view returns (uint256) { | |
return staticSupply[account] * supplyMultiplier; | |
} | |
function transfer(address recipient, uint256 amount) public returns (bool) { | |
require(balanceOf(msg.sender) >= amount, "Insufficient funds"); | |
uint256 staticSupplyChange = amount / supplyMultiplier; | |
staticSupply[msg.sender] -= staticSupplyChange; | |
staticSupply[recipient] += staticSupplyChange; | |
return true; | |
} | |
// owner -> spender -> amount | |
mapping (address => mapping (address => uint256)) approvedAmounts; // not static! | |
function allowance(address owner, address spender) public view returns (uint256) { | |
return approvedAmounts[owner][spender]; | |
} | |
function approve(address spender, uint256 amount) public returns (bool) { | |
require(amount <= balanceOf(msg.sender), "Insufficient balance"); | |
approvedAmounts[msg.sender][spender] += amount; | |
return true; | |
} | |
function transferFrom(address sender, address recipient, uint256 amount) public returns (bool) { | |
require(amount <= approvedAmounts[sender][msg.sender], "Insufficient approved amount"); | |
uint256 staticSupplyChange = amount / supplyMultiplier; | |
staticSupply[sender] -= staticSupplyChange; | |
staticSupply[recipient] += staticSupplyChange; | |
approvedAmounts[sender][msg.sender] -= amount; | |
return true; | |
} | |
function mint(address account, uint256 amount) public { | |
console.log(account, amount); | |
uint256 staticSupplyChange = amount / supplyMultiplier; | |
staticSupply[account] += staticSupplyChange; | |
totalStaticSupply += staticSupplyChange; | |
} | |
function adjustSupplyMultiplier(uint256 x) public onlyOwner { | |
supplyMultiplier *= x; | |
} | |
} | |
contract compound is Ownable { | |
cEth public _ceth; | |
uint256 totalEthReserves; // includes borrowed amounts | |
mapping (address => uint256) public borrowedAmount; | |
uint256 interest_rate = 2.0; // fixed in time for now | |
constructor() { | |
_ceth = new cEth(); | |
} | |
function deposit() public payable { | |
require(msg.value > 0, "Must deposit a positive amount"); | |
_ceth.mint(msg.sender, msg.value); | |
totalEthReserves += msg.value; | |
} | |
// We only allow a single borrow per person. | |
// So if you need to borrow more, you need to first repay your original loan. | |
function borrow(uint256 amount) public { | |
require(amount < address(this).balance, "Insufficient funds in the pool"); | |
borrowedAmount[msg.sender] += amount; | |
(bool sent, ) = msg.sender.call{value: amount}(""); | |
require(sent, "Eth transfer failed"); | |
} | |
// right now we only allow repaying the entire borrowed amount | |
function repayAll() public payable { | |
console.log(msg.value, borrowedAmount[msg.sender] * interest_rate, interest_rate); | |
require(msg.value == borrowedAmount[msg.sender] * interest_rate); | |
uint256 newAmountOfEth = msg.value - borrowedAmount[msg.sender]; | |
uint256 newTotalEthReserves = totalEthReserves + newAmountOfEth; | |
// TODO: this doesn't work... no fractions in Solidity! | |
// have to find another way to do this.. | |
uint256 multiplier = newTotalEthReserves / totalEthReserves; | |
_ceth.adjustSupplyMultiplier(multiplier); | |
totalEthReserves = newTotalEthReserves; | |
borrowedAmount[msg.sender] = 0; | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment