Yearn.금융 보안 검토

Quantstamp Labs
July 24, 2020

Introduction


Quantstamp completed its informal code review of Yearn Finance. Yearn Finance provides yield-maximizing opportunities for liquidity providers, and is intended to be governed in a decentralized manner. Due to the large number of contracts involved in the yEarn system, we limited our review to the most prominent contracts—those that hold funds or can distribute funds. We performed this review as a service to the community. Findings are divided by contract below.

Acknowledgements: We want to especially thank Devops199fan, Klim K, Angel, Michael Egorov, Samczsun, vasiliy, Will Price, Cooper Turley, Damir Bandalo and others in the community for reaching out, walking through the code, and gathering needed documentation, as well as Andre Cronje for creating this grand experiment in decentralization. We are looking forward to seeing how this develops.

We hope this is useful documentation to community members that seek to understand and improve yearn. We understand yearn is a work in progress undergoing rapid iteration, and so is this review, we hope it is helpful.

Overview

The code base for this review was relatively challenging due to the following reasons:


YearnRewards (1st pool) - yCurve LP tokens

The yearn pool stakes yCRV tokens from the Y pool on Curve Finance. The Y pool performs automatic yield-hunting for liquidity providers. It switches liquidity between Aave, Compound, and DyDx to provide the best yield among these platforms. Users of the yearn pool receive YFI tokens. 


Source:
https://etherscan.io/address/0x0001FB050Fe7312791bF6475b96569D83F695C9f 


This contract is a copy of the Synthetix Unipool contract, which was reviewed by Sigma Prime in Feb 2020. Their report can be found here:
https://github.com/sigp/public-audits/blob/master/synthetix/unipool/review.pdf.

The only difference is that Uniswap V1 token was changed to the yCRV token (Curve.fi yDAI/yUSDC/yUSDT/yTUSD (yDAI+yUSD...)) 0xdF5e0e81Dff6FAF3A7e52BA697820c5e32D806A8.

This contract does not have any governance logic in it.


YearnRewards (2nd pool) - Balancer BPT tokens

Pool #2 stakes pool tokens received when providing liquidity to a Balancer DAI-YFI pool. YFI is distributed to incentivize DAI-YFI liquidity. Users receive YFI tokens for providing this liquidity.


Source: https://etherscan.io/address/0x033E52f513F9B98e129381c6708F9faA2DEE5db5 

This contract is a copy of the Synthetix Unipool contract, which was reviewed by Sigma Prime in Feb 2020. Their report can be found here: https://github.com/sigp/public-audits/blob/master/synthetix/unipool/review.pdf

The only difference is that Uniswap V1 token was changed to the BPT token 0x60626db611a9957C1ae4Ac5b7eDE69e24A3B76c5.

This contract does not have any governance logic in it.


YearnGovernance (3rd pool) - Balancer BPT tokens

The Governance pool stakes pool tokens received when providing liquidity to a Balancer yCRV-YFI pool. Users receive YFI, and if they stake more than 1000 pool tokens, are eligible to vote on YFI governance proposals. 


Source:
https://etherscan.io/address/0x3a22df48d84957f907e67f4313e3d43179040d6e#code 

Owner and Governance are not multisig-wallet

Severity: High

  • [owner] Set the reward distribution address
  • [governance]
    • Transfer any token besides YFI, BPT and the reward token (feesPaidIn) to their own address, by calling seize
    • Set the breaker that will block all fee claims when withdrawing, voting and staking, by calling setBreaker
    • Set the reward token address
    • Set the governance address
    • Set the minimum amount needed for proposals
    • Set the number of blocks (period) after a proposal when one can vote
    • Set the amount of time the vote is locked

The RewardDistribution address decides what reward will be given for the next 7 days, not the governance address

Severity: Medium

The rewardDistribution address is not public and therefore its value cannot be read directly from the smart contract. However, looking at the transaction history of the smart contract it is visible that the rewardDistribution address was set in the 3rd transaction ever to be executed on this contract: https://etherscan.io/tx/0xe2b5ef06f80f3ba09992192bbcd2780d43c16da26f2e16b554d25565caa46423 and it was set to the address controlled by Andre, namely 0x2d407ddb06311396fe14d4b49da5f0471447d45c. The rewardDistribution address is the only address that is allowed to call the notifyRewardAmount function, which can set the following state variables:

  1. rewardRate
  2. lastUpdateTime
  3. periodFinish, which is 7 days from the time when this function is called

This notifyRewardAmount function was called on July 19th at 03:38:14 PM +UTC in this transaction https://etherscan.io/tx/0x14b861562694ca6ae06cebb3416dea62c149342bf9adfe9ff28e5180082047c0 with the reward parameter set to 10,000 YFI . This means that the periodFinish will be on July 26 at 03:38 PM +UTC. At this point in time the:

  • lastTimeRewardApplicable function will always return the periodFinish date, which will lead the (see next bullet)
  • rewardPerToken function to stop increasing the reward.

Voting 'period' and 'lock' values may differ

Severity: Medium

By default the period and lock state variables in the YearnGovernance contract have the same value of 17280 blocks (approximately 3 days), which is not a problem. However, the governance address can change these values independently such that they differ. If period > lock then stakers are allowed to withdraw their stake after lock blocks, then they can re-stake the same amount and double their votes for the same proposal. Here are the steps to execute this attack:

  1. Prerequisite: Governance address sets the period = 18000 and leaves lock = 17280.
  2. Alice creates a proposal (having a voting period = 18000)
  3. Bob, who already has a stake of 100, places his vote. His tokens are locked for 17280 blocks.
  4. After 17280 blocks, Bob’s tokens are unlocked and he withdraws them.
  5. Using a different address Bob places another stake using the same 100 tokens. Bob is now allowed to vote on Alice’s proposal again, which increases his vote count to 200 and locks his tokens for 17280 blocks.


Recommendation: Merge the lock variable with the period variable. It’s not clear why and if they will ever have different values.

A user can vote "For" and "Against" on the same proposal simultaneously

Severity: Medium

Community member Klim has brought up that a user can vote for and against simultaneously. We located the code segments in YearnGovernance, voteFor()and voteAgainst() functions and have confirmed the issue. While the functions check that if the user has voted for the same position before and accounts for the votes, they do not check if a user's vote has been accounted for the other stance and thus allows double voting. The issue is present in both functions.


Recommendation: We recommend adding a requirement statement and only allow the user to vote for one given stance.

YearnFeeRewards (4th pool) - stakes YFI for % of protocol fees 

The Fee Rewards pool allows users who have staked more than 1000 pool tokens in Pool #3 and also voted on a proposal to stake their YFI. By staking YFI, they receive rewards in the form of yCRV tokens. 

Source: https://etherscan.io/address/0xb01419E74D8a2abb1bbAD82925b19c36C191A701#code

Owner and Governance are not multisig-wallet

Severity: Medium

Description: Similarly to pool 3 above, the current owner and governance addresses are set to 0x2d407ddb06311396fe14d4b49da5f0471447d45c. This gives the address power to transfer tokens (other than YFI and yCRV) to itself.

Users have to voteLock recently to claim rewards

Severity: Informational

The getReward() function requires the user to have a certain amount of yGov staked balance and have been active in governance, i.e. to have voted recently at the time they are claiming the reward. This requirement is identical as the ones in the stake() function, however, it is unclear whether this is intended as it is not documented or communicated openly.


Recommendation: confirm if this is the intended behavior of the function and document the rationale to inform the users.


YFI Contract

Source: https://etherscan.io/address/0x0bc529c00c6401aef6d220be8c6ea1667f6ad93e#code

The governance address can add any address as a minter. That minter can mint tokens arbitrarily as there is no cap.


Recommendation: Cap value for minting should be decided by governance.

YearnRewards

Source: https://etherscan.io/address/0xcc9efea3ac5df6ad6a656235ef955fbfef65b862#code

YFI Tokens can be seized by the governance (yearn:Deployer) address

Severity: Medium

A total of 10.85475338406697 YFI tokens were seized (transferred out the contract) by the yearn:Deployer address (`0x2d407ddb06311396fe14d4b49da5f0471447d45c`) on the 21st of July 2020, at 12:19 UTC. This happened in 2 consecutive calls to the seize function shown in the 2 transactions below:

  1. https://etherscan.io/tx/0x97c27ddd7b1d8c3ab006e99bcee2753df6391ff08cfbe45f81a16e93f88de9e0 From Ygov.finance: RewardsTo yearn: Deployer For 1.085475338406696829 ($2,339.54)
  2. https://etherscan.io/tx/0xb2a1152ff01d7ea9da7f095c5a9b1c72e637f1569ecda528be7a01565a40c3d3 From Ygov.finance: RewardsTo yearn: Deployer For 9.769278045660271461 ($21,055.82)

The entire amount of YFI was then transferred to the DistributeYFI contract located here https://etherscan.io/address/0x812ac0eaeb422efa44eac670aa2246a25ecfa017#code 

This contract has then distributed this amount non-uniformly in this transaction: https://etherscan.io/tx/0x210ad532a54eeb4fe6e007342ee72459097fb7f4e9b77ff5f090349566f4d586 to 17 addresses as indicated (hardcoded) in the `distribute()` function of the DistributeYFI contract:

  1. yfi.safeTransfer(0x28b88cfD875C883cDb61938C97B8d1baabf31c88,4084730714199977);
  2. yfi.safeTransfer(0x3F47A66aDA01491c3d364599e5bcBf80A1a67092,1405800000000000000);
  3. yfi.safeTransfer(0x5ade40e345817B739b91c6B4615eFCE87F9D7c57,1000000000000000);
  4. yfi.safeTransfer(0x6c6145d05Cd02B40403fd739f7B9B24fc8d8C410,2000000000000000);
  5. yfi.safeTransfer(0xc7D2fdE79bDAe639115607A5bddd1596058E9c29,100000000000000);
  6. yfi.safeTransfer(0xd6b806f51d41947B6C8465363De90941a81FD8Bd,85800000000000000);
  7. yfi.safeTransfer(0x4A915B337B38f4755b39f2801D4Df2901A1432CD,75500000000000000);
  8. yfi.safeTransfer(0xbA766A08f0a126Ed43B2699F722d2063e5fBb308,4282600000000000000);
  9. yfi.safeTransfer(0x5398850A9399Da87624874704FEAa8A9C6C4089B,10000000000000000);
  10. yfi.safeTransfer(0x93aa8C9A50EFa30Bb28cE0AD12516686c963472a,2416900000000000000);
  11. yfi.safeTransfer(0xf853184415AC2312844E77Cc7BaBda372e8F56aF,257000000000000000);
  12. yfi.safeTransfer(0xd53C9Fedcc95187307908D659846a443cb1e7350,122100000000000000);
  13. yfi.safeTransfer(0xCC1cc238f0D0de0bB82cD1F36Ea988D8EB4489AB,243200000000000000);
  14. yfi.safeTransfer(0xDda8901508211dfd3a2A912fEb0b913a6558c113,1006600000000000000);
  15. yfi.safeTransfer(0x1AE3A0366C8F540C9f31cfC18A23b7E4AC9D4d8D,289700000000000000);
  16. yfi.safeTransfer(0xdA581d5E0c21f59E681ADe7747F477D44e4E6FD4,634668653352768313);
  17. yfi.safeTransfer(0xbff3BdC458D94C9Ca36230bE24838e778305A954,17700000000000000);
These addresses burned these exact amounts of YFI tokens before by calling the claim function of the YearnRewards contract, for which they received aDAI (Aave interest bearing DAI) in exchange. It is not entirely clear why they were given back the YFI tokens later. Those addresses do not seem to have returned the aDAI in this transaction history: https://etherscan.io/tokentxns?a=0xcc9efea3ac5df6ad6a656235ef955fbfef65b862

We believe this is related to the fact that some manual operations still need to be performed by the yearn: Deployer admin key.

TimelockGovernance 

Severity: Informational

Source: https://etherscan.io/address/0x026d4b8d693f6c446782c2c61ee357ec561dfb61#code 

The updateTargetGovernance and updateThisGovernance functions are not access controlled in any way. Anyone can call these functions. The update period is hardcoded to 3 days (17280 blocks) and cannot be updated. The addMinter function cannot be called by TimelockGovernance.

APR oracle 

Source: https://etherscan.io/address/0x97FF4A1b787ADe6b94cca95b61F79417c673331D#code 

APR calculation sometimes takes 365 days, other times 366

Severity: Informational

Description: For Compound, the contract calculates APR based on a 365-day calendar; for DyDx, it does so using a 366 baseline. Both are approximations, but 365 seems more accurate.


Heavy use of magic numbers

Severity: Informational

Description: The contract makes heavy use of undocumented numerical constants (magic numbers), which requires readers and auditors alike to reverse engineer the underlying context. Examples:
  • In getCompoundAPR: 2102400. After a closer look, it stands for the blocks per year on compound:
  • 1 block per ~ 15sec -> 4 blocks per minute
  • 4 blocks per minute -> 240 blocks per hour
  • 5760 blocks per day
  • 5760 blocks per day -> 2102400 blocks per year (365 days)
  • The constant 2102400 is then used to calculate Compounds’ APR. Note that results may differ from Compound unless the latter keeps this constant hardcoded in their contracts (currently the case). See below.



  • In getDyDxAPR, 31622400 - stands for the number of seconds in a 366 day year.


No official documentation on DyDx APR calculation

Severity: Low

Description: DyDx does not provide any official documentation on how to calculate the supply APR for an underlying token. The developer of this APR Oracle even acknowledges that---see his Medium post “How we built on-chain APR for Ethereum DeFi”. Thus, it could be the case that the current implementation does not actually match DyDx’s true APR. Nonetheless, the implemented logic seems correct. 


Privileged Roles - Key Person Risk

Severity: Medium/High

Description: The contract contains many restricted functions (as they should be); thus, they can only be called by the address who deployed the contract (currently, the oracle address, which is the same as the contract owner: 0x284b672380a4b5e4d7ccfcc0541a1d0a78c37f8c). There is a risk that if its key gets compromised, the entire Oracle becomes unusable as it could be incorrectly configured by means of its set-like functions.


Unused Functions

Severity: Undetermined

Description: The Oracle contains some functions that do not seem to be used anywhere in the given contracts we had access to. However, we cannot claim that these functions are not indeed used (e.g., it could be the case that we did not get all contracts that participate in this platform). Among those functions that are not called, we found functions that change the Oracle’s price for a given token, as well as its liquidity.


No sanity check of input address parameters

Severity: Low

Description: All set-like functions that take a contract address as a parameter do not check if the given address is different from 0x0, nor that it points to a contract. Thus, 0x0 and EOA addresses can be accidentally set.



Disclaimer

This informal security review is applicable to the current version of contracts as of July 24, 2020 10PM UTC. Quantstamp is aware of the announcement by yearn.finance on its plan to deploy v2 contracts in the next 3-4 days (https://medium.com/iearn/yearn-finance-v2-af2c6a6a3613). The v2 contracts are not yet all available and have not been included as part of this security review.


퀀트스탬프 랩스
2020년 7월 24일

소개


Quantstamp 연말연시 금융의 비공식 코드 검토를 완료했습니다. Yearn Finance는 유동성 공급자에게 수익률 극대화 기회를 제공하며 분산 된 방식으로 관리될 것입니다. yEarn 시스템에 관련된 많은 계약으로 인해, 우리는 가장 눈에 띄는 계약으로 검토를 제한했습니다 - 자금을 보유하거나 자금을 분배 할 수있는 계약. 우리는 지역 사회에 대한 서비스로이 검토를 수행했습니다. 결과는 아래 계약으로 나뉩니다.

인정: 특히 Devops199fan, Klim K, Angel, 마이클 에고로프, 삼츠순, vasiliy, 윌 프라이스, 쿠퍼 터리, 다미르 반달로 및 지역 사회의 다른 사람들에게 도달하고, 코드를 통과하고, 필요한 문서를 수집한 것에 대해 감사하고 싶습니다. 우리는 이것이 어떻게 발전하는지 기대하고 있습니다.

우리는 이것이 갈망을 이해하고 개선하기 위해 노력하는 지역 사회 구성원에게 유용한 문서가되기를 바랍니다. 우리는 갈망이 빠른 반복을 겪고 있는 진행 중인 작업임을 이해하며, 이 리뷰도 도움이 되기를 바랍니다.

개요

이 검토의 코드 기반은 다음과 같은 이유로 인해 상대적으로 어려웠습니다.


이어리워드(1위 풀) - y곡선 LP 토큰

곡선 금융에 Y 풀에서 갈망 풀 지분 yCRV 토큰. Y 풀은 유동성 공급자를 위한 자동 수익률 사냥을 수행합니다. Aave, 화합물 및 DyDx 간의 유동성을 전환하여 이러한 플랫폼 중 에서 최상의 수익을 제공합니다. 갈망 풀의 사용자는 YFI 토큰을 받습니다. 


출처:
https://etherscan.io/address/0x0001FB050Fe7312791bF6475b96569D83F695C9f 


이 계약은 2020년 2월 시그마 프라임이 검토한 Synthetix Unipool 계약의 사본입니다. 그들의 보고서는 여기에서 찾을 수 있습니다.
https://github.com/sigp/public-audits/blob/master/synthetix/unipool/review.pdf.

유일한 차이점은 유니스왑 V1 토큰이 yCRV 토큰(Curve.fi yDAI/yUSDC/yUSDT/yTUSDT/yTUSD(yDAI+yUSD...)으로 변경되었다는 것입니다) 0xdF5e0e81Dff6FAF3A7A7A7A7A7a752BA69720c5e32D806A88806A8.

이 계약에는 거버넌스 논리가 없습니다.


이어리워드(2번째 풀) - 밸런서 BPT 토큰

밸런스러 DAI-YFI 풀에 유동성을 제공할 때 받은 풀 #2 스테이크 풀 토큰. YFI는 DAI-YFI 유동성을 장려하기 위해 배포됩니다. 사용자는 이 유동성을 제공하기 위해 YFI 토큰을 받습니다.


출처: https://etherscan.io/address/0x033E52f513F9B98e129381c6708F9faA2DEE5db5 

이 계약은 2020년 2월 시그마 프라임이 검토한 Synthetix Unipool 계약의 사본입니다. 그들의 보고서는 여기에서 찾을 수 있습니다: https://github.com/sigp/public-audits/blob/master/synthetix/unipool/review.pdf

유일한 차이점은 유니스왑 V1 토큰이 BPT 토큰 0x60626db611a9957C1ae4Ac5b7eDE69e24A3B76c5로 변경되었다는 것입니다.

이 계약에는 거버넌스 논리가 없습니다.


연도 거버넌스 (3 풀) - 밸러버 BPT 토큰

밸런서 yCRV-YFI 풀에 유동성을 제공할 때 받은 거버넌스 풀 스테이크 풀 토큰입니다. 사용자는 YFI를 받고 1,000개 이상의 풀 토큰을 지분하는 경우 YFI 거버넌스 제안에 투표할 수 있습니다. 


출처:
https://etherscan.io/address/0x3a22df48d84957f907e67f4313e3d43179040d6e#code 

소유자 와 거버넌스는 멀티 시그 지갑이 아닙니다

심각도: 높음

  • 【소유자】 보상 분배 주소 설정
  • [거버넌스]
    • YFI, BPT 및 보상 토큰 이외의 토큰을 전송합니다(수수료 지불인) 자신의 주소로, 전화로 탈취
    • 인출, 투표 및 스터팅 시 모든 수수료 청구를 차단하는 차단기를 호출하여 설정 세트브레이커
    • 보상 토큰 주소 설정
    • 거버넌스 주소 설정
    • 제안에 필요한 최소 금액 설정
    • 블록 수 설정 (기간) 투표할 수 있는 제안 후
    • 투표가 잠기는 시간 설정

RewardDistribution 주소는 거버넌스 주소가 아닌 향후 7일 동안 어떤 보상을 받을지 결정합니다.

심각도: 중간

Tthe 보상배포 주소는 공개되지 않으므로 해당 값은 스마트 계약에서 직접 읽을 수 없습니다. 그러나 스마트 계약의 거래 내역을 살펴보면 보상배포 주소는 이 계약에서 실행될 3번째 트랜잭션에서 설정되었습니다. https://etherscan.io/tx/0xe2b5ef06f80f3ba09992192bbcd2780d43c16da26f2e16b554d25565caa46423 그리고 그것은 안드레에 의해 제어 주소로 설정되었습니다, 즉 0x2d407ddb06311396fe14db49da5f0471477d45c. Tthe 보상배포 주소는 호출할 수 있는 유일한 주소입니다. 알림리워드리Amount 다음 상태 변수를 설정할 수 있는 함수는 다음과 같은 경우를 설정합니다.

  1. 보상평가
  2. 마지막 업데이트 시간
  3. 기간 완료이 함수를 호출한 시점으로부터 7일

알림리워드리Amount 함수는 7월 19일 03:38:14 PM +UTC에서 10,000 YFI로 설정된 보상 매개 변수와 함께 https://etherscan.io/tx/0x14b861562694ca6ae06cebb3416dea62c149342bf9adfe9ff28e5180082047c0 호출되었습니다. 즉, 기간 완료 7월 26일 오후 03:38 +UTC에 발표됩니다. 이 시점에서 다음을 수행하십시오.

  • 지난 타임리워드 적용 가능 함수는 항상 기간 완료 날짜, 이는 리드 (다음 글머리 기호 참조)
  • 보상퍼토큰 보상 증가를 중지하는 기능.

투표 '기간'과 '잠금' 값은 다를 수 있습니다.

심각도: 중간

기본적으로 기간잠금 YearnGovernance 계약의 상태 변수는 17280 블록(약 3일)의 동일한 값을 가지며 이는 문제가 되지 않습니다. 그러나 거버넌스 주소는 이러한 값을 다르게 변경할 수 있습니다. 경우 기간 > 잠금 그런 다음 응시자는 후 자신의 지분을 철회 할 수 있습니다 잠금 블록, 그들은 같은 금액을 다시 지분과 같은 제안에 대한 자신의 투표를 두 배로 할 수 있습니다. 이 공격을 실행하는 단계는 다음과 같습니다.

  1. 전제 조건: 거버넌스 주소는 기간 = 18000 잎과 잎 잠금 = 17280.
  2. Alice는 제안서를 만듭니다(투표 기간 = 18000)
  3. 이미 100의 지분을 가지고 있는 밥은 자신의 표를 놓습니다. 그의 토큰은 17280 블록에 잠겨 있습니다.
  4. 17280 블록 후, Bob의 토큰은 잠금 해제되고 그는 그들을 철회합니다.
  5. Bob은 다른 주소를 사용하여 동일한 100개의 토큰을 사용하여 다른 지분을 배치합니다. 밥은 이제 앨리스의 제안에 다시 투표 할 수 있습니다, 이는 그의 투표 수를 증가 200 17280 블록에 대한 자신의 토큰을 잠그고.


권장 사항: 잠금 변수와 기간 변수. 왜, 그리고 다른 가치를 가질지는 분명하지 않습니다.

사용자는 동일한 제안에 대해 동시에 "For" 및 "For"로 투표할 수 있습니다.

심각도: 중간

커뮤니티 회원 Klim은 사용자가 동시에 투표할 수 있다고 제기했습니다. 코드 세그먼트를 연도 거버넌스, 투표포()투표반대() 기능을 하고 문제를 확인했습니다. 함수는 사용자가 이전에 동일한 직책에 투표하고 투표를 고려한 경우 사용자의 투표가 다른 입장에 대해 설명되었는지 확인하지 않으므로 이중 투표를 허용합니다. 문제는 두 함수 모두에 있습니다.


권장 사항: 요구 사항 명세서를 추가하고 사용자가 주어진 입장에 대해서만 투표할 수 있도록 하는 것이 좋습니다.

YearnFeeRewards (4 번째 풀) - 프로토콜 수수료의 %에 대한 지분 YFI 

수수료 보상 풀은 풀 #3 1,000개 이상의 풀 토큰을 베팅한 유저가 YFI를 지분하는 제안에 투표할 수 있습니다. YFI를 복용하면 yCRV 토큰 형태로 보상을 받습니다. 

출처: https://etherscan.io/address/0xb01419E74D8a2abb1bbAD82925b19c36C191A701#code

소유자 와 거버넌스는 멀티 시그 지갑이 아닙니다

심각도: 중간

설명: 위의 풀 3과 유사하게 현재 소유자거 버 넌 스 주소는 0x2d407ddb06311396fe14db49da5f0471477d45c. 이렇게 하면 주소가 토큰(YFI 및 yCRV 제외)을 자체적으로 전송할 수 있습니다.

사용자는 보상을 주장하기 위해 최근 투표록을해야합니다

심각도: 정보

Tthe 겟리워드() 함수는 사용자가 일정량의 yGov 지분 잔액을 가져야 하며 거버넌스에서 활발히 활동해 왔으며, 즉 보상을 청구할 당시 최근에 투표해야 합니다. 이 요구 사항은 스테이크() 그러나 이 기능이 문서화되지 않았거나 공개적으로 전달되지 않았기 때문에 의도된 것인지는 불분명합니다.


권장 사항: 이것이 함수의 의도된 동작인지 확인하고 사용자에게 알릴 근거를 문서화합니다.


YFI 계약

출처: https://etherscan.io/address/0x0bc529c00c6401aef6d220be8c6ea1667f6ad93e#code

Tthe 거 버 넌 스 주소는 모든 주소를 minter로 추가할 수 있습니다. 그 minter는 캡이 없기 때문에 임의로 토큰을 조폐 할 수 있습니다.


권장 사항: 채굴에 대한 상한선 값은 거버넌스에 의해 결정되어야 합니다.

연도리리

출처: https://etherscan.io/address/0xcc9efea3ac5df6ad6a656235ef955fbfef65b862#code

YFI 토큰은 거버넌스(연도:배포자) 주소로 압수할 수 있습니다.

심각도: 중간

총 10.8547533840697 YFI 토큰은 120일 20일 10일 120시 10분('0x2d407ddb0631396fe14b49d49d49d495c')에 의해 압수되었다. 이는 2회 연속 호출에서 일어났습니다. 탈취 아래 2 트랜잭션에 표시된 기능:

  1. https://etherscan.io/tx/0x97c27ddd7b1d8c3ab006e99bcee2753df6391ff08cfbe45f81a16e93f88de9e0 Ygov.finance에서: 보상에 갈망: 배포자 1.08547533840696829 ($2,339.54)
  2. https://etherscan.io/tx/0xb2a1152ff01d7ea9da7f095c5a9b1c72e637f1569ecda528be7a01565a40c3d3 Ygov.finance에서: 보상에 갈망: 배포자 9.76927804560271461 ($21,055.82)

YFI의 전체 금액은 여기에있는 배포YFI 계약으로 전송https://etherscan.io/address/0x812ac0eaeb422efa44eac670aa2246a25ecfa017#code 

그런 다음 이 계약은 이 거래에서 이 금액을 균일하게 배포했습니다: 배포YFI 계약의 '배포()' 함수에서 표시된(하드코딩)에 https://etherscan.io/tx/0x210ad532a54eeb4fe6e007342ee72459097fb7f4e9b77ff5f090349566f4d586 주소17개주소로 https://etherscan.io/tx/0x210ad532a54eeb4fe6e007342ee72459097fb7f4e9b77ff5f090349566f4d586.

  1. yfi.safeTransfer (0x28b88cfD875C883cDb61938 C97B8d1baabf31c888,4084730714199977);
  2. yfi.safeTransfer (0x3F47A66aDA01491c364599e5bcBf80A167092,140580000000000000000000000000000000);
  3. yfi.safeTransfer (0x5ade40e345817B739b91c6B4615eFCE87F9D7c57,10000000000000000);
  4. yfi.safeTransfer (0x6c6145d05Cd02B40403fd739f7B9B24fc8d8C410,20000000000000000);
  5. yfi.safeTransfer (0xc7D2fdE79bAe639115607A5bd1596058E9c29,10000000000000000);
  6. yfi.safeTransfer (0xd6b806f5141947B6C8465363De90941a81FD8BD,85800000000000000000);
  7. yfi.safeTransfer (0x4A915B37B37B38f4755b39f2801D4Df2901A1432CD, 75500000000000000000000);
  8. yfi.safeTransfer (0xbA766A08f0a126Ed43B2699F722d2063e5fBb308,428260000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
  9. yfi.safeTransfer (0x5398850A939Da87624774704FEA8A8A8A9C6C40899B,10000000000000000);
  10. yfi.safeTransfer (0x93aa8C9A50EFa30Bb28cE0AD12516686c963472a,24169000000000000000000000000000000000);
  11. yfi.safeTransfer (0xf853184415AC231284E77Cc7BaBda372e8F56aF56aF,2570000000000000000000000);
  12. yfi.safeTransfer (0xd53C9Fedcc95187307908D659846a43cb1e7350,122100000000000000000000000);
  13. yfi.safeTransfer (0xCC1cc1cc238f0D0d0d0d0b82cD1F36Ea988D8EB4489AB, 243200000000000000000000000);
  14. yfi.safeTransfer (0xDda890150821dfd3a2A912fEb0b913a658c113,10060000000000000000000000000000000000);
  15. yfi.safeTransfer (0x1AE3A0366C8F540C9f31cfC18A23b7E4AC9D4d8D8D8D,28970000000000000000000000000);
  16. yfi.safeTransfer (0xdA581d5E0c21f59E681ADe77477777D44EFD4FD4,6346865352768313;
  17. yfi.safeTransfer (0xbff3BdC458D94C9Ca36230bE24838e778305A954,1770000000000000000000000);
이러한 주소는 YFI 토큰의 정확한 금액을 불태워 주장 의 기능 연도리리 계약, 그들은 대가로 aDAI (Aave 이자 베어링 DAI)를받은. 그들이 나중에 YFI 토큰을 다시 받은 이유가 완전히 명확하지 않습니다. 이러한 주소는 이 트랜잭션 기록에서 aDAI를 반환하지 않은 것 같습니다 https://etherscan.io/tokentxns?a=0xcc9efea3ac5df6ad6a656235ef955fbfef65b862.

배포자 관리자 키: 일부 수동 작업이 여전히 수행되어야 한다는 사실과 관련이 있다고 생각합니다.

타임록 거버넌스 

심각도: 정보

출처: https://etherscan.io/address/0x026d4b8d693f6c446782c2c61ee357ec561dfb61#code 

Tthe 업데이트타겟거버넌스업데이트이 거버넌스 함수는 어떤 식으로든 제어되는 액세스권한이 없습니다. 누구나 이러한 함수를 호출할 수 있습니다. 업데이트 기간은 3일(17280블록)으로 하드코딩되며 업데이트할 수 없습니다. Tthe 추가Minter 함수를 호출할 수 없습니다. 타임록 거버넌스.

APR 오라클 

출처: https://etherscan.io/address/0x97FF4A1b787ADe6b94cca95b61F79417c673331D#code 

APR 계산은 때때로 365 일, 다른 시간은 366걸립니다

심각도: 정보

설명: 화합물의 경우 계약은 365일 달력에 따라 APR을 계산합니다. DyDx의 경우 366 기준선을 사용하여 수행합니다. 둘 다 근사치이지만 365는 더 정확해 보입니다.


매직 넘버의 과다 사용

심각도: 정보

설명: 이 계약은 문서화되지 않은 수치 상수(매직 넘버)를 많이 사용하므로 독자와 감사자가 모두 기본 컨텍스트를 리버스 엔지니어링해야 합니다. 예제:
  • 에서 GetCompoundAPR: 2102400. 자세히 살펴, 그것은 화합물에 연간 블록을 의미 :
  • 분당 ~ 15초 -> 4블록당 1블록
  • 분당 4블록 -시간당 240블록 >
  • 하루 5760블록
  • 하루 5760블록 -> 연간 210만2400블록(365일)
  • 상수 2102400은 화합물의 APR을 계산하는 데 사용됩니다. 후자가 계약(현재 의 경우)에서 이 일정한 하드코딩을 유지하지 않는 한 결과가 화합물과 다를 수 있습니다. 아래를 참조하십시오.



  • 에서 getDyDxAPR, 31622400 - 366 일 년 초수를 의미합니다.


DyDx APR 계산에 대한 공식 문서가 없습니다.

심각도: 낮음

설명: DyDx는 기본 토큰에 대한 공급 APR을 계산하는 방법에 대한 공식 문서를 제공하지 않습니다. 이 APR 오라클의 개발자는 심지어 그의 중간 게시물을 참조하십시오 --- 인정"우리는 이더리움 DeFi에 대한 체인 APR을 구축하는 방법". 따라서 현재 구현이 DyDx의 실제 APR과 실제로 일치하지 않는 경우가 있을 수 있습니다. 그럼에도 불구하고 구현된 논리는 정확해 보입니다. 


특권 역할 - 핵심 인물 위험

심각도: 중간/높음

설명: 계약에는 많은 제한된 함수가 포함되어 있습니다(예상대로); 따라서 계약을 배포한 주소에서만 호출할 수 있습니다(현재 오라클 계약 소유자와 동일한 주소: 0x284b672380a4b5e47ccfcc0541a1d0a78c37f8c). 키가 손상되면 설정과 같은 기능을 통해 잘못 구성될 수 있으므로 전체 오라클을 사용할 수 없게 될 위험이 있습니다.


사용되지 않는 기능

심각도: 미정

설명: 오라클에는 우리가 액세스한 특정 계약의 어느 곳에서도 사용되지 않는 몇 가지 기능이 포함되어 있습니다. 그러나 이러한 기능이 실제로 사용되지 않는다고 주장할 수는 없습니다(예: 이 플랫폼에 참여하는 모든 계약을 받지 않은 경우일 수 있음). 호출되지 않는 기능 중, 우리는 주어진 토큰에 대한 오라클의 가격을 변경하는 기능뿐만 아니라 유동성을 발견했다.


입력 주소 매개 변수의 정신 확인 없음

심각도: 낮음

설명: 계약 주소를 매개 변수로 하는 모든 설정과 같은 함수는 지정된 주소가 0x0과 다른지 또는 계약을 가리키는지 확인하지 않습니다. 따라서 0x0 및 EOA 주소를 실수로 설정할 수 있습니다.



면책 조항

이 비공식 보안 검토는 2020년 7월 24일 오후 10시 UTC 현재 계약에 적용됩니다. Quantstamp 다음 3-4 일 (https://medium.com/iearn/yearn-finance-v2-af2c6a6a3613)에 v2 계약을 배포 할 계획에 대한 yearn.finance의 발표를 알고 있습니다. v2 계약은 아직 모두 사용할 수 없으며 이 보안 검토의 일부로 포함되지 않았습니다.


November 11, 2020

Quantstamp Community Update - October 2020

‍Audit of Ethereum 2.0 client Teku, blockchain insurance, Open DeFi, virtual events, and more media coverage... here’s what happened at Quantstamp in October.‍

November 5, 2020

Why Bitcoin is Capturing Enterprise Attention

MicroStrategy made headlines this summer as the first publicly-traded company to buy Bitcoin as part of its capital allocation strategy. Since then, other companies have followed suit. Learn how current economic conditions and the unique properties of Bitcoin have driven these decisions.

October 28, 2020

Formally Verifying Hedera Hashgraph's Stablecoin Framework

Quantstamp created and formally verified a specification for Hedera Hashgraph stablecoins. This simplifies the process of creating safe stablecoins and also makes easier for partners to safely integrate them.

October 27, 2020

Quantstamp Completes Audit of 2nd ETH 2.0 Implementation

Quantstamp has now completed its audit of Teku, the Ethereum 2.0 client developed by ConsenSys. Quantstamp also audited Prysm by Prysmatic Labs.