Skip to content

Commit

Permalink
format
Browse files Browse the repository at this point in the history
  • Loading branch information
t4sk committed May 8, 2023
1 parent 86d6b5b commit 1bc0916
Show file tree
Hide file tree
Showing 5 changed files with 276 additions and 2 deletions.
118 changes: 118 additions & 0 deletions src/ERC721.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

import "./interfaces/IERC721.sol";

contract ERC721 is IERC721 {
event Transfer(address indexed from, address indexed to, uint256 indexed id);
event Approval(address indexed owner, address indexed spender, uint256 indexed id);
event ApprovalForAll(address indexed owner, address indexed operator, bool approved);

// Mapping from token ID to owner address
mapping(uint256 => address) internal _ownerOf;

// Mapping owner address to token count
mapping(address => uint256) internal _balanceOf;

// Mapping from token ID to approved address
mapping(uint256 => address) internal _approvals;

// Mapping from owner to operator approvals
mapping(address => mapping(address => bool)) public isApprovedForAll;

function supportsInterface(bytes4 interfaceId) external pure returns (bool) {
return interfaceId == type(IERC721).interfaceId || interfaceId == type(IERC165).interfaceId;
}

function ownerOf(uint256 id) external view returns (address owner) {
owner = _ownerOf[id];
require(owner != address(0), "token doesn't exist");
}

function balanceOf(address owner) external view returns (uint256) {
require(owner != address(0), "owner = zero address");
return _balanceOf[owner];
}

function setApprovalForAll(address operator, bool approved) external {
isApprovedForAll[msg.sender][operator] = approved;
emit ApprovalForAll(msg.sender, operator, approved);
}

function approve(address spender, uint256 id) external {
address owner = _ownerOf[id];
require(msg.sender == owner || isApprovedForAll[owner][msg.sender], "not authorized");

_approvals[id] = spender;

emit Approval(owner, spender, id);
}

function getApproved(uint256 id) external view returns (address) {
require(_ownerOf[id] != address(0), "token doesn't exist");
return _approvals[id];
}

function _isApprovedOrOwner(address owner, address spender, uint256 id) internal view returns (bool) {
return (spender == owner || isApprovedForAll[owner][spender] || spender == _approvals[id]);
}

function transferFrom(address from, address to, uint256 id) public {
require(from == _ownerOf[id], "from != owner");
require(to != address(0), "transfer to zero address");

require(_isApprovedOrOwner(from, msg.sender, id), "not authorized");

_balanceOf[from]--;
_balanceOf[to]++;
_ownerOf[id] = to;

delete _approvals[id];

emit Transfer(from, to, id);
}

function safeTransferFrom(address from, address to, uint256 id) external {
transferFrom(from, to, id);

require(
to.code.length == 0
|| IERC721Receiver(to).onERC721Received(msg.sender, from, id, "")
== IERC721Receiver.onERC721Received.selector,
"unsafe recipient"
);
}

function safeTransferFrom(address from, address to, uint256 id, bytes calldata data) external {
transferFrom(from, to, id);

require(
to.code.length == 0
|| IERC721Receiver(to).onERC721Received(msg.sender, from, id, data)
== IERC721Receiver.onERC721Received.selector,
"unsafe recipient"
);
}

function _mint(address to, uint256 id) internal {
require(to != address(0), "mint to zero address");
require(_ownerOf[id] == address(0), "already minted");

_balanceOf[to]++;
_ownerOf[id] = to;

emit Transfer(address(0), to, id);
}

function _burn(uint256 id) internal {
address owner = _ownerOf[id];
require(owner != address(0), "not minted");

_balanceOf[owner] -= 1;

delete _ownerOf[id];
delete _approvals[id];

emit Transfer(owner, address(0), id);
}
}
2 changes: 1 addition & 1 deletion src/Wallet.sol
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ pragma solidity ^0.8.18;
contract Wallet {
address payable public owner;

event Deposit(address account, uint amount);
event Deposit(address account, uint256 amount);

constructor() payable {
owner = payable(msg.sender);
Expand Down
124 changes: 124 additions & 0 deletions src/defi/ZeroCouponBond.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,124 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.18;

import "../interfaces/IERC20.sol";
import "../interfaces/IERC721.sol";
import "../ERC20.sol";
import "../ERC721.sol";
import "../Token.sol";

// Bond is bought at a discount
// Discount determines fixed interest

contract CollateralToken is Token("collateral", "col", 18) {}

contract Coin is Token("coin", "coin", 6) {}

contract Auth {
mapping(address => bool) public authorized;

modifier onlyAuthorized() {
require(authorized[msg.sender], "not authorized");
_;
}

function _setAuthorized(address account, bool auth) internal {
authorized[account] = auth;
}

function setAuthorized(address account, bool auth) external onlyAuthorized {
_setAuthorized(account, auth);
}
}

// NFT
interface IFixedYieldBond is IERC721 {
function mint(address account, uint256 fyAmount) external returns (uint256);
}

struct ZeroCouponBond {
address issuer;
uint256 debt;
uint256 maturity;
}

contract FixedYieldBond is IFixedYieldBond, ERC721, Auth {
constructor() {
_setAuthorized(msg.sender, true);
}

function mint(address account, uint256 fyAmount) external onlyAuthorized returns (uint256) {
// TODO: maturity
// TODO: id
uint256 id = 123;
_mint(account, id);
return id;
}

function burn() external {}
}

contract ZeroCouponBondMarket {
IERC20 public immutable coin;
IFixedYieldBond public immutable fyBond;

constructor(IERC20 _coin, IFixedYieldBond _fyBond) {
coin = _coin;
fyBond = _fyBond;
}

function sell(uint256 _nftId) external {
fyBond.transferFrom(msg.sender, address(this), _nftId);
}

// TODO: cancel

// TODO: Auction or AMM
function buy(uint256 _nftId) external {
uint256 price = 0;
address nftOwner;
uint256 fyAmount;
coin.transferFrom(msg.sender, nftOwner, fyAmount);
// TODO: can be resold?
fyBond.transferFrom(address(this), msg.sender, _nftId);
}
}

contract CollateralLock {
IERC20 public immutable collateral;
IERC20 public immutable coin;
IFixedYieldBond public immutable fyBond;

mapping(address => uint256) public collateralBalances;

constructor(IERC20 _collateral, IERC20 _coin, IFixedYieldBond _fyBond) {
collateral = _collateral;
coin = _coin;
fyBond = _fyBond;
}

function lock(uint256 colAmount) external {
collateral.transferFrom(msg.sender, address(this), colAmount);
collateralBalances[msg.sender] += colAmount;
}

function borrow(uint256 fyAmount) external returns (uint256) {
uint256 nftId = fyBond.mint(msg.sender, fyAmount);
return nftId;
}

function repay(uint256 fyAmount) external {
// TODO: fees after expiry
coin.transferFrom(msg.sender, address(this), fyAmount);
// TODO: calculate how much collateral to release
uint256 colAmount;
collateral.transfer(msg.sender, colAmount);
}

function withdraw() external {}

// TODO: liquidation AMM or auction
function liquidate() external {}
}

contract PriceOracle {}
32 changes: 32 additions & 0 deletions src/interfaces/IERC721.sol
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
// SPDX-License-Identifier: MIT
pragma solidity ^0.8.17;

interface IERC165 {
function supportsInterface(bytes4 interfaceID) external view returns (bool);
}

interface IERC721 is IERC165 {
function balanceOf(address owner) external view returns (uint256 balance);

function ownerOf(uint256 tokenId) external view returns (address owner);

function safeTransferFrom(address from, address to, uint256 tokenId) external;

function safeTransferFrom(address from, address to, uint256 tokenId, bytes calldata data) external;

function transferFrom(address from, address to, uint256 tokenId) external;

function approve(address to, uint256 tokenId) external;

function getApproved(uint256 tokenId) external view returns (address operator);

function setApprovalForAll(address operator, bool _approved) external;

function isApprovedForAll(address owner, address operator) external view returns (bool);
}

interface IERC721Receiver {
function onERC721Received(address operator, address from, uint256 tokenId, bytes calldata data)
external
returns (bytes4);
}
2 changes: 1 addition & 1 deletion test/Wallet.t.sol
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@ contract WalletTest is Test {
}

function testSendEth() public {
uint bal = address(wallet).balance;
uint256 bal = address(wallet).balance;

// deal
deal(address(1), 100);
Expand Down

0 comments on commit 1bc0916

Please sign in to comment.