Created
March 10, 2025 06:52
-
-
Save RareSkills/5419beb9f7b06d4b4bb79473d3257d2c to your computer and use it in GitHub Desktop.
This file contains hidden or 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
| // this contract is buggy, don't use in production! | |
| pragma solidity 0.8.28; | |
| import {IERC20Errors} from "@openzeppelin/contracts/interfaces/draft-IERC6093.sol"; | |
| import {IERC20} from "@openzeppelin/contracts/interfaces/IERC20.sol"; | |
| contract RebasingERC20 is IERC20Errors, IERC20 { | |
| uint256 private _totalShares; | |
| mapping(address => uint256) private _shares; | |
| mapping(address owner => mapping(address spender => uint256 allowance)) public allowance; | |
| // transfering tokens to this contract causes a rebase upward | |
| receive() external payable {} | |
| function mint(address to) external payable { | |
| _totalShares += msg.value; | |
| _shares[to] += msg.value; | |
| emit Transfer(address(0), to, msg.value); | |
| } | |
| function burn(address from, uint256 amount) external { | |
| _spendAllowanceOrBlock(from, msg.sender, amount); | |
| _shares[from] -= balanceToShares(amount); | |
| _totalShares -= balanceToShares(amount); | |
| emit Transfer(from, address(0), amount); | |
| } | |
| function balanceToShares(uint256 amount) internal view returns (uint256) { | |
| if (address(this).balance == 0) { | |
| return 0; | |
| } | |
| return amount * _totalShares / address(this).balance; | |
| } | |
| function totalSupply() public view returns (uint256) { | |
| return address(this).balance; | |
| } | |
| function balanceOf(address account) public view returns (uint256) { | |
| if (address(this).balance == 0 || _totalShares == 0) { | |
| return 0; | |
| } | |
| return _shares[account] * address(this).balance / _totalShares; | |
| } | |
| function transfer(address to, uint256 amount) external returns (bool) { | |
| transferFrom(msg.sender, to, amount); | |
| return true; | |
| } | |
| function transferFrom(address from, address to, uint256 amount) public returns (bool) { | |
| require(to != address(0), ERC20InvalidReceiver(to)); | |
| _spendAllowanceOrBlock(from, msg.sender, amount); | |
| uint256 shareTransfer = balanceToShares(amount); | |
| _shares[from] -= shareTransfer; | |
| _shares[to] += shareTransfer; | |
| emit Transfer(from, to, amount); | |
| return true; | |
| } | |
| function approve(address spender, uint256 amount) external returns (bool) { | |
| allowance[msg.sender][spender] = amount; | |
| emit Approval(msg.sender, spender, amount); | |
| return true; | |
| } | |
| function _spendAllowanceOrBlock(address owner, address spender, uint256 amount) internal { | |
| if (owner != msg.sender && allowance[owner][spender] != type(uint256).max) { | |
| uint256 currentAllowance = allowance[owner][spender]; | |
| require(currentAllowance >= amount, ERC20InsufficientAllowance(spender, currentAllowance, amount)); | |
| allowance[owner][spender] = currentAllowance - amount; | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment