|慢雾:DeFi 当红项目 YAM 闪电折戟,一行代码如何蒸发数亿美元?( 三 )


function uniswapV2Call( address sender, uint256 amount0, uint256 amount1, bytes memory data ) public { // enforce that it is coming from uniswap require(msg.sender == uniswap_pair, ''bad msg.sender''); // enforce that this contract called uniswap require(sender == address(this), ''bad origin''); (UniVars memory uniVars) = abi.decode(data, (UniVars)); YAMTokenInterface yam = YAMTokenInterface(yamAddress); if (uniVars.amountFromReserves > 0) { // transfer from reserves and mint to uniswap yam.transferFrom(reservesContract, uniswap_pair, uniVars.amountFromReserves); if (uniVars.amountFromReservesuniVars.yamsToUni) { // if the amount from reserves > yamsToUni, we have fully paid for the yCRV tokens // thus this number would be 0 so no need to mint yam.mint(uniswap_pair, uniVars.yamsToUni.sub(uniVars.amountFromReserves)); } } else { // mint to uniswap yam.mint(uniswap_pair, uniVars.yamsToUni); } // mint unsold to mintAmount //SlowMist// 将多余的 YAM 代币分发给 reserves 合约 if (uniVars.mintToReserves > 0) { yam.mint(reservesContract, uniVars.mintToReserves); } // transfer reserve token to reserves if (isToken0) { SafeERC20.safeTransfer(IERC20(reserveToken), reservesContract, amount1); emit TreasuryIncreased(amount1, uniVars.yamsToUni, uniVars.amountFromReserves, uniVars.mintToReserves); } else { SafeERC20.safeTransfer(IERC20(reserveToken), reservesContract, amount0); emit TreasuryIncreased(amount0, uniVars.yamsToUni, uniVars.amountFromReserves, uniVars.mintToReserves); } }分析到这里 , 一个完整的rebase流程就完成了 , 你可能看得很懵 , 我们用简单的流程图简化下:
|慢雾:DeFi 当红项目 YAM 闪电折戟,一行代码如何蒸发数亿美元?
本文插图

也就是说 , 每次的rebase , 如果有多余的 YAM 代币 , 这些代币将会流到 reserves 合约中 , 那这和社区治理的关系是什么呢?
通过分析项目代码 , 发现治理相关的逻辑在 YAMGovernorAlpha.sol 中 , 其中发起提案的函数为 propose , 具体代码如下:
function propose( address[] memory targets, uint[] memory values, string[] memory signatures, bytes[] memory calldatas, string memory description ) public returns (uint256) { //SlowMist// 校验提案发起者的票数占比 require(yam.getPriorVotes(msg.sender, sub256(block.number, 1)) > proposalThreshold, ''GovernorAlpha::propose: proposer votes below proposal threshold''); require(targets.length == values.length && targets.length == signatures.length && targets.length == calldatas.length, ''GovernorAlpha::propose: proposal function information arity mismatch''); require(targets.length != 0, ''GovernorAlpha::propose: must provide actions''); require(targets.lengthproposalMaxOperations, ''GovernorAlpha::propose: too many actions''); uint256 latestProposalId = latestProposalIds[msg.sender]; if (latestProposalId != 0) { ProposalState proposersLatestProposalState = state(latestProposalId); require(proposersLatestProposalState != ProposalState.Active, ''GovernorAlpha::propose: one live proposal per proposer, found an already active proposal''); require(proposersLatestProposalState != ProposalState.Pending, ''GovernorAlpha::propose: one live proposal per proposer, found an already pending proposal''); } uint256 startBlock = add256(block.number, votingDelay); uint256 endBlock = add256(startBlock, votingPeriod); proposalCount++; Proposal memory newProposal = Proposal({ id: proposalCount, proposer: msg.sender, eta: 0, targets: targets, values: values, signatures: signatures, calldatas: calldatas, startBlock: startBlock, endBlock: endBlock, forVotes: 0, againstVotes: 0, canceled: false, executed: false }); proposals[newProposal.id] = newProposal; latestProposalIds[newProposal.proposer] = newProposal.id; emit ProposalCreated( newProposal.id, msg.sender, targets, values, signatures, calldatas, startBlock, endBlock, description ); return newProposal.id; }通过分析代码 , 可以发现在发起提案时 , 需要提案发起人拥有一定额度的票权利 , 这个值必须大于 proposalThreshold 计算得来的值 , 具体代码如下:
function proposalThreshold public view returns (uint256) { return SafeMath.div(yam.initSupply, 100); } // 1% of YAM也就是说提案发起人的票权必须大于 initSupply 的 1% 才能发起提案 。 那 initSupply 受什么影响呢?答案是 YAM 代币的 mint 函数 , 代码如下:


推荐阅读