Treasury Contract는 라운드의 확장 및 축소 상태를 결정하고 KAI의 신규 발행, bKAI 상환 등 중앙은행과 같은 중심적인 역할을 합니다.
[주요 역할]
PriceOracle에서 제공되는 KAI의 가격에 따른 확장/축소 상태 결정
확장/축소/부스트 결과에 따른 에어드랍 비율 결정
확장 상태에서 KAI 신규 발행 및 분배
bKAI 상환을 위한 KAI 보유 및 지급
다음은 확장 상태에서 KAI 추가 발행을 위해 Mint 하는 Code 입니다.
function allocateSeigniorage() external onlyOneBlock checkCondition checkEpoch checkOperator {
_updateKAIPrice();
previousRoundKAIPrice = getKAIPrice(); // KAI 가격을 얻어옴
uint256 kaiSupply = IERC20(kai).totalSupply().sub(seigniorageSaved);
if (round < bootstrapRounds) { // 초기 21라운드는 3% 고정
_sendToBoardRoom(kaiSupply.mul(bootstrapSupplyExpansionPercent).div(10000));
} else {
if (previousRoundKAIPrice > kaiPriceOne) { // KAI 가격이 $1 초과하면 확장
uint256 bkaiSupply = IERC20(bkai).totalSupply();
uint256 _percentage = previousRoundKAIPrice.sub(kaiPriceOne).mul(seigniorageExpansionRate).div(10000);
uint256 _savedForBKAI;
uint256 _savedForBoardRoom;
// bKAI 의 발행량 이상으로 Treasury 가 KAI 를 보유한 경우 일반적인 확장 진행
if (seigniorageSaved >= bkaiSupply.mul(bkaiDepletionFloorPercent).div(10000))
uint256 _mse = maxSupplyExpansionPercent.mul(1e14);
if (_percentage > _mse) {
_percentage = _mse;
}
_savedForBoardRoom = kaiSupply.mul(_percentage).div(1e18);
} else {
// bKAI 의 발행량 만큼 Treasury 가 보유하고 있지 않다면, 이는 Debt Phase 로 전환되어 더 많은 KAI 가 Treasury 에 적립됨
_percentage = maxSupplyExpansionPercentInDebtPhase.mul(1e14);
uint256 _seigniorage = kaiSupply.mul(_percentage).div(1e18);
_savedForBoardRoom = _seigniorage.mul(seigniorageExpansionFloorPercent).div(10000);
_savedForBKAI = _seigniorage.sub(_savedForBoardRoom);
if (mintingFactorForPayingDebt > 0) {
_savedForBKAI = _savedForBKAI.mul(mintingFactorForPayingDebt).div(10000);
}
}
if (_savedForBoardRoom > 0) {
// 보드룸으로 KAI 생성 요청
_sendToBoardRoom(_savedForBoardRoom);
}
if (_savedForBKAI > 0) {
seigniorageSaved = seigniorageSaved.add(_savedForBKAI);
IKAIAsset(kai).mint(address(this), _savedForBKAI);
emit TreasuryFunded(now, _savedForBKAI);
}
}
}
// 바이백 펀드 KAI 생성
if (previousRoundKAIPrice > kaiPriceOne) {
uint256 _buyBackRate = previousRoundKAIPrice.sub(kaiPriceOne).mul(buyBackFundExpansionRate).div(10000);
uint256 _maxBuyBackRate = maxBuyBackFundExpansion.mul(1e14);
if (_buyBackRate > _maxBuyBackRate) {
_buyBackRate = _maxBuyBackRate;
}
uint256 _savedForBuyBackFund = kaiSupply.mul(_buyBackRate).div(1e18);
if (_savedForBuyBackFund > 0) {
IKAIAsset(kai).mint(address(buyBackFund), _savedForBuyBackFund);
emit BuyBackFunded(now, _savedForBuyBackFund);
}
}
if (allocateSeigniorageSalary > 0) {
IKAIAsset(kai).mint(address(admin), allocateSeigniorageSalary);
}
}
Mint된 후 _sendToBoardRoom function 을 통해 Boardroom Contract 및 Team Fund에게 KAI가 분배됩니다.
function _sendToBoardRoom(uint256 _amount) internal {
IKAIAsset(kai).mint(address(this), _amount);
// 10%의 물량은 팀펀드로 적립되며, 해당 물량은 마케팅 및 운영비로 사용됨
if (teamFundSharedPercent > 0) {
uint256 _teamFundSharedAmount = _amount.mul(teamFundSharedPercent).div(10000);
IERC20(kai).transfer(teamFund, _teamFundSharedAmount);
emit TeamFundFunded(now, _teamFundSharedAmount);
_amount = _amount.sub(_teamFundSharedAmount);
}
IERC20(kai).safeApprove(boardroom, 0);
IERC20(kai).safeApprove(boardroom, _amount);
// 보드룸에 나머지 물량을 보내서 단일예치자들에게 배분
IBoardroom(boardroom).allocateSeigniorage(_amount);
emit BoardroomFunded(now, _amount);
}
Boardroom Contract
0x931579Fa23580CB2214fBE89aB487f6AEDE8a352
Boardroom Contract는 sKAI 단일 예치를 관리하고 확장 상태에서 Treasury Contract로 부터 받은 KAI를 sKAI 단일 예치 사용자에게 분배하는 일반 은행과 같은 역할을 합니다.
[주요 역할]
sKAI 단일 예치
추가 발행된 KAI 분배
발행된 vKAI 분배
BBFund Contract - Buyback Fund
0x451033434Fb739a538DA0a77d3DcA23Bf0801255
bKAI를 통한 KAI의 $ 1 페깅 알고리즘의 보완 장치로 다음 라운드 예상 가격(TWAP)이 $ 1미만일때 KAI를 바이백해서 가격을 안정화할 수 있습니다. KAI 유통량 및 바이백 펀드 현황에 따라 바이백된 KAI가 소각될 수 있습니다.