Skip to content

Commit 71dabcf

Browse files
committed
code review comments
1 parent 638ebdb commit 71dabcf

File tree

5 files changed

+60
-31
lines changed

5 files changed

+60
-31
lines changed

contracts/ACash.sol

Lines changed: 37 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -31,11 +31,20 @@ contract ACash is ERC20, Initializable, Ownable {
3131
// calculates bond price
3232
IPricingStrategy public pricingStrategy;
3333

34+
// Yield applied on each tranche
35+
// tranche yields is specific to the parent bond's class identified by its config hash
36+
// a bond's class is the combination of the {collateralToken, trancheRatios}
37+
// specified as a fixed point number with YIELD_DECIMALS
38+
mapping(bytes32 => uint256[]) private _trancheYields;
39+
3440
// bondQueue is a queue of Bonds, which have an associated number of seniority-based tranches.
3541
AddressQueue.Queue public bondQueue;
3642

37-
// system only keeps bonds which mature further out than the `tolarableBondMaturiy` in the queue
38-
uint256 private _tolarableBondMaturiy;
43+
// the minimum maturity time in seconds for a bond below which it gets removed from the bond queue
44+
uint256 private _minQueueMaturiySec;
45+
46+
// the maximum maturity time in seconds for a bond above which it can't get added into the bond queue
47+
uint256 private _maxQueueMaturiySec;
3948

4049
//---- ERC-20 parameters
4150
uint8 private immutable _decimals;
@@ -44,6 +53,9 @@ contract ACash is ERC20, Initializable, Ownable {
4453
// They can only be rolled over and not burnt
4554
mapping(ITranche => bool) trancheIcebox;
4655

56+
// constants
57+
uint256 public constant YIELD_DECIMALS = 6;
58+
4759
constructor(
4860
string memory name,
4961
string memory symbol,
@@ -84,11 +96,16 @@ contract ACash is ERC20, Initializable, Ownable {
8496

8597
uint256 mintAmt = 0;
8698
for (uint256 i = 0; i < trancheCount; i++) {
99+
uint256 trancheYield = _trancheYields[bondIssuer.configHash(mintingBond)][i];
100+
if(trancheYield == 0){
101+
continue;
102+
}
103+
87104
(ITranche t, ) = mintingBond.tranches(i);
88105
t.safeTransferFrom(_msgSender(), address(this), trancheAmts[i]);
89106

90107
// get bond price, ie amount of SPOT for trancheAmts[i] amount of t tranches
91-
mintAmt += pricingStrategy.getTranchePrice(t, trancheAmts[i]);
108+
mintAmt += (pricingStrategy.getTranchePrice(t, trancheAmts[i]) * trancheYield) / (10**YIELD_DECIMALS);
92109
}
93110

94111
int256 fee = feeStrategy.computeMintFee(mintAmt);
@@ -102,8 +119,9 @@ contract ACash is ERC20, Initializable, Ownable {
102119
// push new bond into the queue
103120
function advanceMintBond(IBondController newBond) public {
104121
require(address(newBond) != bondQueue.head(), "New bond already in queue");
105-
require(bondIssuer.isInstance(address(newBond)), "Expect new bond to be minted by the minter");
106-
require(newBond.maturityDate() > tolarableBondMaturiyDate(), "New bond matures too soon");
122+
require(bondIssuer.isInstance(newBond), "Expect new bond to be minted by the minter");
123+
require(newBond.maturityDate() > minQueueMaturityDate(), "New bond matures too soon");
124+
require(newBond.maturityDate() <= maxQueueMaturityDate(), "New bond matures too late");
107125

108126
bondQueue.enqueue(address(newBond));
109127
}
@@ -114,7 +132,7 @@ contract ACash is ERC20, Initializable, Ownable {
114132
while (true) {
115133
IBondController latestBond = IBondController(bondQueue.tail());
116134

117-
if (address(latestBond) == address(0) || latestBond.maturityDate() > tolarableBondMaturiyDate()) {
135+
if (address(latestBond) == address(0) || latestBond.maturityDate() > minQueueMaturityDate()) {
118136
break;
119137
}
120138

@@ -168,12 +186,21 @@ contract ACash is ERC20, Initializable, Ownable {
168186
feeStrategy = feeStrategy_;
169187
}
170188

171-
function setTolarableBondMaturiy(uint256 tolarableBondMaturiy) external onlyOwner {
172-
_tolarableBondMaturiy = tolarableBondMaturiy;
189+
function setTolarableBondMaturiy(uint256 minQueueMaturiySec, uint256 maxQueueMaturiySec) external onlyOwner {
190+
_minQueueMaturiySec = minQueueMaturiySec;
191+
_maxQueueMaturiySec = maxQueueMaturiySec;
192+
}
193+
194+
function setTrancheYields(bytes32 configHash, uint256[] memory yields) external onlyOwner {
195+
_trancheYields[configHash] = yields;
196+
}
197+
198+
function minQueueMaturityDate() public view returns (uint256) {
199+
return block.timestamp + _minQueueMaturiySec;
173200
}
174201

175-
function tolarableBondMaturiyDate() public view returns (uint256) {
176-
return block.timestamp + _tolarableBondMaturiy;
202+
function maxQueueMaturityDate() public view returns (uint256) {
203+
return block.timestamp + _maxQueueMaturiySec;
177204
}
178205

179206
/*

contracts/BondIssuer.sol

Lines changed: 14 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@ pragma solidity ^0.8.0;
22

33
import { IBondFactory } from "./interfaces/button-wood/IBondFactory.sol";
44
import { IBondIssuer } from "./interfaces/IBondIssuer.sol";
5+
import { IBondController } from "./interfaces/button-wood/IBondController.sol";
56

67
// A minter periodically mints a specified class of bonds or config
78
// a config is uniquely identified by {collateralToken, trancheRatios and duration}
@@ -22,9 +23,10 @@ contract BondIssuer is IBondIssuer {
2223
uint256 public lastIssueWindowTimestamp;
2324

2425
IBondIssuer.BondConfig public config;
26+
bytes32 private _configHash;
2527

2628
// mapping of minted bonds
27-
mapping(address => bool) mintedBonds;
29+
mapping(IBondController => bool) public issuedBonds;
2830

2931
constructor(
3032
IBondFactory bondFactory_,
@@ -37,16 +39,24 @@ contract BondIssuer is IBondIssuer {
3739
minIssueTimeInterval = minIssueTimeInterval_; // 1 week
3840
issueWindowOffset = issueWindowOffset_; // 7200, 2AM UTC
3941
bondDuration = bondDuration_; // 4 weeks
42+
4043
config = config_;
44+
_configHash = keccak256(abi.encode(config_.collateralToken, config_.trancheRatios));
4145

4246
lastIssueWindowTimestamp = 0;
4347
}
4448

4549
// checks if bond has been minted using this minter
46-
function isInstance(address bond) external view override returns (bool) {
47-
return mintedBonds[bond];
50+
function isInstance(IBondController bond) external view override returns (bool) {
51+
return issuedBonds[bond];
52+
}
53+
54+
// returns the config hash of a given bond if issued by this issuer
55+
function configHash(IBondController bond) external view override returns (bytes32) {
56+
return issuedBonds[bond] ? _configHash : bytes32(0);
4857
}
4958

59+
// issues new bond
5060
function issue() external override {
5161
require(
5262
lastIssueWindowTimestamp + minIssueTimeInterval < block.timestamp,
@@ -61,7 +71,7 @@ contract BondIssuer is IBondIssuer {
6171
lastIssueWindowTimestamp + bondDuration
6272
);
6373

64-
mintedBonds[bond] = true;
74+
issuedBonds[IBondController(bond)] = true;
6575

6676
emit BondIssued(bond);
6777
}

contracts/FeeStrategy.sol

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,8 +18,8 @@ contract FeeStrategy is Ownable, IFeeStrategy {
1818

1919
// expected mint token to be have the same number of decimals as the fee token
2020
function computeMintFee(uint256 mintAmt) external view override returns (int256) {
21-
# TODO use https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/math/SafeCast.sol
22-
# Todo: check all math for overflow reverts
21+
// TODO use https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/math/SafeCast.sol
22+
// Todo: check all math for overflow reverts
2323
return (int256(mintAmt) * mintFeePct) / int256(10**PCT_DECIMALS);
2424
}
2525

contracts/PricingStrategy.sol

Lines changed: 2 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -7,24 +7,17 @@ import { IPricingStrategy } from "./interfaces/IPricingStrategy.sol";
77
import { IBondIssuer } from "./interfaces/IBondIssuer.sol";
88

99
contract PricingStrategy is Ownable, IPricingStrategy {
10-
uint256 public constant PCT_DECIMALS = 6;
1110
uint256 public constant PRICE_DECIMALS = 18;
1211

13-
// todo: add setters
14-
// tranche yields is specific to the parent bond's class identified by its config hash
15-
// a bond's class is the combination of the {collateralToken, trancheRatios}
16-
mapping(bytes32 => uint256[]) private _trancheYields;
17-
1812
struct TrancheConfig {
1913
IBondController bond;
2014
uint256[] trancheRatios;
2115
uint256 seniorityIDX;
2216
}
2317

24-
// tranche_price => yield * price_fn(tranche) * tranche_amount
18+
// tranche_price => price_fn(tranche) * tranche_amount
2519
function getTranchePrice(ITranche t, uint256 trancheAmt) external view override returns (uint256) {
26-
uint256 yieldFactor = (getTrancheYield(t) * computeTranchePrice(t)) / (10**PRICE_DECIMALS);
27-
return (yieldFactor * trancheAmt) / (10**PCT_DECIMALS);
20+
return (computeTranchePrice(t) * trancheAmt) / (10**PRICE_DECIMALS);
2821
}
2922

3023
// Tranche pricing function goes here:
@@ -34,11 +27,6 @@ contract PricingStrategy is Ownable, IPricingStrategy {
3427
return (10**PRICE_DECIMALS);
3528
}
3629

37-
function getTrancheYield(ITranche t) private view returns (uint256) {
38-
TrancheConfig memory c = getTrancheConfig(t);
39-
return _trancheYields[keccak256(abi.encode(c.bond.collateralToken(), c.trancheRatios))][c.seniorityIDX];
40-
}
41-
4230
// NOTE: this is very gas intensive
4331
// rebuilding the tranche's pricing parameters though the parent bond
4432
// Alternatively the bond issuer can map the tranche to these parameters for efficient recovery

contracts/interfaces/IBondIssuer.sol

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,5 @@
1+
import { IBondController } from "./button-wood/IBondController.sol";
2+
13
interface IBondIssuer {
24
struct BondConfig {
35
address collateralToken;
@@ -8,5 +10,7 @@ interface IBondIssuer {
810

911
function issue() external;
1012

11-
function isInstance(address bond) external view returns (bool);
13+
function isInstance(IBondController bond) external view returns (bool);
14+
15+
function configHash(IBondController bond) external view returns (bytes32);
1216
}

0 commit comments

Comments
 (0)