if __name__ == '__main__': gitbook_url = 'https://docs.zerolend.xyz'# Replace with the GitBook URL output_file = 'documentation.md'# Desired output markdown file
main(gitbook_url, output_file)
Replace above official document url to whatever you need.After modify it to your own url, run the following python script.
1
python3 gitbook_scraper.py
After successlly execute the python script you’ll see the documentation.md on your root directory.
Feed the markdown file to AI
Let’s take claude.ai as example.
Copy the generated flowchart to online mermaid website.
view the flowchart online
Jump to website https://mermaid.live/ , paste the copyed flowchart code to it.
Why we need this ?
As we know, Web3 security competitions are time-limited. Participants who grasp the entire system quickly gain an advantage in identifying more vulnerabilities. With the help of AI we can generate flowchart in minitues. Furthermore, we have a summary of the entire project. I’m not entirely convinced that AI will replace auditors in the near future, but I am certain that those who don’t utilize AI will be left behind.
The LayerZero Endpoint is an immutable smart contract that implements a standardized interface for Omnichain Applications (OApps) to manage security configurations and seamlessly send and receive messages.
Message Library
Each MessageLib is an immutable verification library that OApp owners can configure their application to use. The protocol enforces the contract owner’s unique OApp Configuration before sending and receiving messages.
Message Packet
The Message Packet standardizes the format and size of messages that are sent between different blockchains:
1 2 3 4 5 6 7 8 9
struct Packet { uint64 nonce; // the nonce of the message in the pathway uint32 srcEid; // the source endpoint ID address sender; // the sender address uint32 dstEid; // the destination endpoint ID bytes32 receiver; // the receiving address bytes32 guid; // a global unique identifier bytes message; // the message payload }
Security Stack (DVNs)
Security Stack (DVNs) is used to check the payloadHash emitted for message integrity. There are two number here:
required Decentralized Verifier Networks(DVNs)
optional Decentralized Verifier Networks(DVNs)
Executors
Executors is used to invoke target chain lzReceive function in the Endpoint contract once the message payload is verified.
Methods
_lzSend
the function your application must implement to send an omnichain message.
_lzReceive
the function to receive an omnichain message
_lzCompose
Since each composable call is created as a separate message packet via lzCompose, this pattern can be extended for as many steps as your application needs (B1 -> B2 -> B3, etc).
Message Execution Options
LayerZero provides robust Message Execution Options, which allow you to specify arbitrary logic as part of the message transaction, such as the gas amount and msg.value the Executor pays for message delivery, the order of message execution, or dropping an amount of gas to a destination address.
quote
estimate of how much gas a message will cost to be sent and received
price data pushlisher submit data to pyth’s oracel program
pyth’s oracel program combines all price data and compute the final price based on it’s own algorithm
pyth transfer price data from pythnet to mutiple target chains eg,:evm,bnb,arbiturm
hermes(web service) listens to price update.
price consumer get the latest price from hermes(web service),verify the lastest price data on chain via oracel program on each chain,the program then return the price once price data is valid
Pyth Methods On EVM Table
Method
Need check publishTime
Most recent price
getPrice
✗
✓
getPriceUnsafe
✓
✗
getPriceNoOlderThan
✗
✗
getEmaPrice
✗
✗
getEmaPriceUnsafe
✓
✗
getEmaPriceNoOlderThan
✗
✗
getUpdateFee
✗
✗
getValidTimePeriod
✗
✗
parsePriceFeedUpdate
✗
✗
parsePriceFeeUpdateUnique
✗
✗
updatePriceFeeds
✗
✓
updatePriceFeedsIfNecessary
✗
✗
Pyth Methods On EVM
getPrice
arguments:
price feed id
getPrice() revert due to the price has not been update within getValidTimePeriod() seconds which is typically 1 minute.
1 2 3
EVM call reverted with exception:
StalePrice()
let’s take eth/usd as example, the return price is 291769250000, and the price is 2917.69250000 usd. The only argument is price feed id which is a 32-byte id written as a hexadecimal string.For eth/usd it’s 0xff61491a931112ddf1bd8147cd1b641375f79f5825126d665480874634fd0ace. You can get the full list from https://pyth.network/developers/price-feed-ids page.
The input arguments and return data format for getPriceUnsafe() are identical to those of the getPrice() function. However, the key distinction lies in their behavior: getPriceUnsafe() may return a price from an arbitrary point in the past, potentially outdated. Consequently, the responsibility falls on the caller or price consumer to ensure the returned data meets their recency requirements. This involves comparing the current block.timestamp with the returned publishTime to verify that the price update is sufficiently recent for their specific use case.
getPriceNoOlderThan
arguments:
price feed id
age
This function reverts with a PriceFeedNotFound error if the requested feed id has never received a price update. Calling updatePriceFeed to fix this issue.
getEmaPrice
arguments:
price feed id
Get the latest exponentially-weighted moving average (EMA) price and confidence interval for the requested price feed id.
price feed id This function may return a price from arbitrarily far in the past Get the latest exponentially-weighted moving average (EMA) price and confidence interval for the requested price feed id.
getEmaPriceNoOlderTham
arguments:
price feed id
age Get the latest exponentially-weighted moving average (EMA) price and confidence interval for the requested price feed id The caller provides an age argument that specifies how old the price can be.The call can be revert due to StalePriceError.
getUpdateFee
arguments:
updateData
Note that updataData is retrieved from Hermes REST API.
1 2 3 4 5
EVM call succeeded with result:
{ feeAmount: 1, }
getValidTimePeriod
Get the default valid time period in seconds. Above some getting function revert if current on-chain price is older than this period.
1 2 3 4 5
EVM call succeeded with result:
{ validTimePeriod: 60, }
parsePriceFeedUpdates
arguments:
updateData* hex[]
priceIds* bytes32[]
minPublishTime* uint64
maxPublishTime* uint64
fee* wei
Parse updateData and return the price feeds for the given priceIds within, if they are all published between minPublishTime and maxPublishTime (minPublishTime <= publishTime <= maxPublishTime). Please note that this function not returned the most recent price,instead it returned a price for fixed time(minPublishTime <= publishTime <= maxPublishTime). If caller need a most recent price they should call updatePriceFeeds followed by getPrice or one of its variants.
Unlike updatePriceFeeds, calling this function will not update the on-chain price
parsePriceFeedUpdatesUnique.
arguments:
updateData* hex[]
priceIds* bytes32[]
minPublishTime* uint64
maxPublishTime* uint64
fee* wei
the price update is the earliest update after the minPublishTime.
Update the on-chain price feeds using the provided updateData Caller first retrieve a latest price from Hermes REST API,and then invoke this function to update the on-chain price if this price is more recent than on-chain price,otherwise the provided update will be ignored.
updatePriceFeedsIfNecessary
arguments:
updateData* hex[]
priceIds* bytes32[]
publishTimes* uint64[]
fee* wei
Update the on-chain price feeds using the provided updateData if the on-chain data is not sufficiently fresh. The caller provides two matched arrays, priceIds and publishTimes. This function applies the update if there exists an index i such that priceIds[i]’s last publishTime is before than publishTimes[i]. Callers should typically pass publishTimes[i] to be equal to the publishTime of the corresponding price id in updateData. If this condition is not satisfied, the call will revert with a NoFreshUpdate error.
As we can see, the protocol uses the time period from lastConfig to the present to calculate the released amount. However, consider a scenario where the start time is set in the future.
root cause protocol assume start time is equal to the configuration time.
2.Expired maturities longer than FixedLib.INTERVAL with unaccrued earnings may be arbitraged and/or might lead to significant bad debt creation
when calculate latestMaturity use block.timestamp - (block.timestamp % FixedLib.INTERVAL) which can lead to a replay more than 1 INTERVAL not accounted. root cause block.timestamp - (block.timestamp % FixedLib.INTERVAL) has a time range.
1.SettleLongPremium is incorrectly implemented: premium should be deducted instead of added
summary
1 2 3 4 5
// current available assets belonging to PLPs (updated after settlement) excluding any premium paid int256 updatedAssets = int256(uint256(s_poolAssets)) - swappedAmount;
// add premium to be paid/collected on position close > int256 tokenToPay = -realizedPremium;
In the code, the int type is used for numbers, and the sign of the subtrahend is used to control whether the final result is an increase or a decrease.
root cause
As a result, an error in the sign of the input parameters leads to the final operation being contrary to the expectation.
learned
When we use the int type, we need to pay special attention to the sign of the values
When deployNewPool is called it uses the spot price of the pool, which can be manipulated through a flashloan and thus could return a highly inaccurate result.
root cause
uses spot price
learned
spot price can be manipulated through a flashloan, try to use TWAP price instead.
2._validatePositionList() does not check for duplicate tokenIds, allowing attackers to bypass solvency checks
summary
The user can pass in an array of tokenIds, but there is no check for duplicates.
root cause
no check for duplicates
learned
Think about if pass in array need to be checked for duplicates.
3.Removed liquidity can overflow when calling SemiFungiblePositionManager.mintTokenizedPosition function
summary
1 2 3 4 5 6
if (!isBurn) { // we can't remove more liquidity than we add in the first place, so this can't overflow unchecked { removedLiquidity += chunkLiquidity; } }
options can be repeatly which can lead to removedLiquidity sum up mutiple times.
root cause
unchecked block overflow
learned
need to double check the unchecked block make sure it can not be overflow
4.Wrong leg chunkKey calculation in haircutPremia function
summary
when loop tokenId , uses always the index 0 when calculating the leg chunkKey instead of using the actual leg index
root cause
logic error
learned
pay more attention to the logic.
5.Panoptic pool can be non-profitable by specific Uniswap governance
summary
The developers only considered the current range of Uniswap fees, but these fees may change through governance, affecting the existing logic.
root cause
fee may changes in the future.
learned
It is necessary to consider the impact of governance on the current fees.
1.DAO unable to withdraw their funds due to Convex admin action
summary
The administrator can cause a DoS (Denial of Service) in the protocol by passing malicious parameters
root cause
according to docs : admin’s action is RESTRICTED
learned
When a role’s behavior is RESTRICTED, it is necessary to examine the consequences of any suspicious actions
2.Inadequate Allowance Handling in convertAndForward Function of OCT_DAO & OCT_YDL
summary
stricted allowance assertion check lead to transaction failed
root cause
protocol suffers from inadequate handling of token allowances for the 1inch router,however they are not reset afterward.
learned
take care of the allowance assertion check
3.cannot forward extra rewards from both OCY_Convex to OCT_YDL
summary
1 2
- if (rewardAmount > 0) { IERC20(rewardContract).safeTransfer(OCT_YDL, rewardAmount); } + if (rewardAmount > 0) { IBaseRewardPool_OCY_Convex_C(rewardContract).rewardToken().safeTransfer(OCT_YDL, rewardAmount); }
root cause
use safeTransfer in a none erc20 contract
learned
4.ZivoeYDL::earningsTrancheuse() always assumes that daysBetweenDistributions have passed, which might not be the case
summary
The protocol relies on keepers to call distributeYield. However, there is no guarantee that the keeper will make the call immediately.
root cause
The calculation of the APY depends on block.timestamp.
learned
When the calculation of APY depends on the timestamp, ensure it is called immediately
5.ZivoeYDL::distributeYield yield distribution is flash-loan manipulatable
summary
distributeYield is depends on totalSupply, however totalSupply can be manipulable through a flashloan.A 1-transaction inflated staked amount allows to inflate stakers distribution at the loss of vesters distribution
root cause
distributeYield amount is calculated with totalSupply
6.distributeYield() calls earningsTrancheuse() with outdated emaSTT & emaJTT while calculating senior & junior tranche yield distributions
summary
The earningsTrancheuse function uses emaSTT and emaJTT to calculate earnings, and then updates the latest emaSTT and emaJTT. It is recommended to update the latest values first and then use them to calculate earnings.
root cause
the value is not lastest need to be updated.
7.User cannot withdraw stakingToken due to incorrect calculation of _totalSupply
summary
When the user revokes a stake, the total amount is subtracted instead of the currently withdrawable amount, leading to an overflow DoS.
One of the key differences between Blast L2 and other Layer 2 solutions is that in Blast L2, ETH functions as a native rebasing token.
1.1 what is rebasing token?
A rebasing token in the Ethereum Virtual Machine (EVM) context is a type of cryptocurrency whose supply automatically adjusts, or rebases periodically to maintain a target price or peg. This mechanism is designed to achieve certain economic goals, such as price stability or controlled inflation/deflation.
1.2 why blast l2 ?
Blast users and smart contracts can earn ~4% from beacon chain staking yield
Blast redirects sequencer fees to the dapps that induced them
2.three options for yield modes
Smart contract must interact with 0x4300000000000000000000000000000000000002 to change their gas mode.
2.1 Void (DEFAULT)
Void is default yield modes for smart contract which deploy on blast l2. The balance of smart contract never changes, no yield is earned . Any normal dapp can be deploy on blast without any changes. Thus if you already have smart contract you can just move it to blast.
2.2 Automatic
Since eth is native rebasing on blast l2 , if deposit 1 eth into smart contract, the contract’s balance will grow to 1.04 ETH in a year.
2.3 Claimable
For claimable mode, if deposit 1 eth into smart contract , the contract’s balance will emain at 1 eth even after a year. We can implement two functions to claim yield:
claimYield
claimAllYield
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19
interface IBlast{ // See IBlast interface source code below }
function claimYield(address recipient, uint256 amount) external { //This function is public meaning anyone can claim the yield IBlast(0x43...02).claimYield(address(this), recipient, amount); }
function claimAllYield(address recipient) external { //This function is public meaning anyone can claim the yield IBlast(0x43...02).claimAllYield(address(this), recipient); } }
Refer to the definetion of merkle tree on wikipedia:https://en.wikipedia.org/wiki/Merkle_tree In cryptography and computer science, a hash tree or Merkle tree is a tree in which every “leaf” node is labelled with the cryptographic hash of a data block, and every node that is not a leaf (called a branch, inner node, or inode) is labelled with the cryptographic hash of the labels of its child nodes. A hash tree allows efficient and secure verification of the contents of a large data structure. A hash tree is a generalization of a hash list and a hash chain. As we know, an airdrop may contain numerous eligible addresses. Storing all these addresses would incur significant gas fees. Instead, we can simply store the Merkle root, which is a 32-byte value. If you’re not a Solidity developer, grasping the basics of Merkle trees can be challenging. That’s why we’ve developed a tool called oneclicktoken. It simplifies the process of generating Merkle tree roots and, furthermore, enables the creation of ERC20 tokens with just a click. You won’t need any prior knowledge of web3, Solidity, or the ERC20 standard At this early stage of our project, we’d like to highlight some of the features and supported chains
1.1 supported chains:
base
sepolia(test)
More Coming…
1.2 features:
generate merkle root from google spread sheet
generate ERC20 token
Premint
Mintable
Pauseable
VerifyContract(if you need)
2.How to generate merkle tree root from an online google spread
To extract the unique ID from a Google Sheets URL, you can locate the string of characters following the /d/ and preceding the /edit in the URL. For example, in the given URL, the unique ID is 1jVX3j-TlLtI3VJ-27DuOuZuCM3x6_zf9W5tI6k67TvQ.
Next, to identify the specific sheet within the spreadsheet, navigate to the bottom left corner of the Google Sheets interface, where a list of sheets is displayed. From there, you can determine the name of the sheet you need to access. In the provided URL, the sheet name is sheet1.
Once you have obtained the unique ID and sheet name, you can proceed to our tool website, oneclicktoken . There, input the required parameters and click the Calculate button. This will generate the Merkle tree root and provide a download URL for the Merkle tree JSON file.
3.How to generate ERC20 with airdrop using a single click?
token name
token symbol
premint amount(1 == 1 ether token)
contract owner(deployer is the default owner)
merkle root(if you need an airdrop) Once you have obtained above params, navigate to our webiste oneclicktoken input the required parameters and click the deploy button , then you can deploy your custom ERC20 token to target chains. If you need to test your token you can deploy it to sepolia testnet first it’s free.
Our project is in the very early stages, so you might encounter some issues while using it. If you need assistance, please don’t hesitate to reach out to me through the following channels. Additionally, if you require a custom airdrop website or need assistance building a custom Solidity contract, feel free to contact me.
1.getBunniTokenPrice wrongly returns the total price of all tokens
The function getBunniTokenPrice() is supposed to return the price of 1 Bunni token (1 share) like all other feeds, but it doesn't. It returns the total price of all minted tokens/shares for a specific pool (total value of position's reserves) which is wrong.
2.Possible incorrect price for tokens in Balancer stable pool due to amplification parameter update
3.Incorrect StablePool BPT price calculation
`getProtocolOwnedLiquidityOhm` is in scope , but any user can invoke deposit to add assets, deposit is not in scope.need to check those out of scope functions.
4.getReservesByCategory() when useSubmodules =true and submoduleReservesSelector=bytes4(0) will revert
when add not check parameters lead to some category can't get Reserves
5.Price calculation can be manipulated by intentionally reverting some of price feeds
when use uniswap and balancer to calculate price, both price feed can revert due to re-enter lead to user can manipulate price.
use selfdestruct can send eth to any contract,even contract not implement receive{}
1.Bidder can use donations to get VerbsToken from auction that already ended.
protocol use address(this).balance to check if bid amount is bigger than current eth value in contract , attacker can send eth to protocol to bypass above check. need to take care of address(this).balance check.
2.Incorrect amounts of ETH are transferred to the DAO treasury in ERC20TokenEmitter::buyToken(), causing a value leak in every transaction
need to track eth
3.VerbsToken.tokenURI() is vulnerable to JSON injection attacks
4.encodedData argument of hashStruct is not calculated perfectly for EIP712 singed messages in CultureIndex.sol
1.Attacker can reenter to mint all the collection supply
when mint ERC721 token,protocol invoke minter’s onERC721Received function can lead to re-entrancy issue.
2.Attacker can drain all ETH from AuctionDemo when block.timestamp == auctionEndTime
3.Adversary can block claimAuction() due to push-strategy to transfer assets to multiple bidders
claimAuction() implements a push-strategy instead of a pull-strategy for returning the bidders funds. protocol invoke user’s address to send eth,user can implement revert on receive{} function to brick the process.
4.Multiple mints can brick any form of salesOption 3 mintings
1.Weighted pool spot price calculation is incorrect
Notional calculate the spot price of Weighted pool using the balances of token. Which need to be upscaled according to the balancer but Notional doesn’t.
Not farmilar with balancer wighted pool.
2.Single-sided instead of proportional exit is performed during emergency exit
Single-sided instead of proportional exit is performed during emergency exit, which could lead to a loss of assets during emergency exit and vault restoration.
Comment should use proportionally withdraw but used single token out , pay more attention on comments.
3.Native ETH not received when removing liquidity from Curve V2 pools
Not farmilar with Curve V2 pool removing LP.
4.Different spot prices used during the comparison
5.Incorrect invariant used for Balancer’s composable pools
Not farmilar with balancer need to check balancer contract next time.
6.Fewer than expected LP tokens if the pool is imbalanced during vault restoration
The vault restoration function intends to perform a proportional deposit
OHM aims to fill the gap between fiat stablecoins and volatile crypto assets, providing relative stability and scalability in a fully autonomous way with no off-chain dependencies OHM:0x64aa3364f17a4d01c6f1751fd97c2bd3d7e7f1d5
he Treasury represents all assets owned and controlled by the protocol
Protocol Owned Liquidity
Dex
Uniswap v3 pool OHM/wETH
RBS
Provide OHM/DAI LP
Range Bound Stability
Cooler Loans
Cooler Loans is a decentralized lending facility that allows OHM (Olympus) token holders to borrow DAI by using their gOHM (governance OHM) tokens as collateral.
1.FULL_RESTRICTED Stakers can bypass restriction through approvals
The openzeppelin ERC4626 contract allows approved address to withdraw and redeem on behalf of another address so far there is an approval。
Encountering an unfamiliar EIP requires a thorough understanding of its code before proceeding with the subsequent audit.
2.Soft Restricted Staker Role can withdraw stUSDe for USDe
The code does not satisfy that condition, when a holder has the SOFT_RESTRICTED_STAKER_ROLE, they can exchange their stUSDe for USDe using StakedUSDeV2。
When faced with strictly limiting conditions, it is essential to consider whether there are any possible ways to bypass them through various means.
3.users still forced to follow previously set cooldownDuration even when cooldown is off (set to zero) before unstaking
The main issue with this question is that when setting global parameters, the impact on previous users was not taken into consideration
4.Malicious users can front-run to cause a denial of service (DoS) for StakedUSDe due to MinShares checks
This issue arises from the fact that the first user of the vault can have a certain impact on subsequent users. Therefore, it is important to be mindful of the effects of the initial configuration when handling shares.
<address>.codehash != bytes32(0) check is insufficient to determine if an address has existing code
An account is considered empty when it has no code and zero nonce and zero balance.
if anyone transfers 1 wei to an address, .codehash will return keccak256("") instead of bytes32(0)
Fix for this is easier than suggested - just change from x.codehash != bytes32(0) to x.code.length != 0
2.Borrower has no way to update maxTotalSupply of market or close market
Developer define a function but no way to interact with it
3.When withdrawalBatchDuration is set to zero lenders can withdraw more then allocated to a batch
wirte a full test
4.Any address can withdraw from markets contrary
function access control
5.Borrower can drain all funds of a sanctioned lender
1.protocol use CREATE3 that’s not avaliable in the Zksync Era.
2.two modifer not cover block.timestamp == allocationEndTime.
1 2 3 4 5 6 7 8 9 10 11 12 13
function _checkOnlyActiveAllocation() internal view { if (allocationStartTime > block.timestamp || block.timestamp > allocationEndTime) { revert ALLOCATION_NOT_ACTIVE(); } }
/// @notice Checks if the allocation has ended and reverts if not. /// @dev This will revert if the allocation has not ended. function _checkOnlyAfterAllocation() internal view { if (block.timestamp < allocationEndTime) { revert ALLOCATION_NOT_ENDED(); } }
When block.timestamp == allocationEndTime none of above modifers revert.
3.Manager vote every recipient to update his state once reacted the threshold
Since we have serval states protocol not check if user have already reacted the threshold.
4._distribute amount not correctly calculated.
5.missing access modifer
6.Can not create a pool by cloning strategies on zkSync network
Can not create pool by cloning strategies on zkSync network because of different behaviors from EVM instructions between zkSync and Ethereum
7.RFPSimpleStrategy milestones can be set multiple times
1
if (upcomingMilestone != 0) revert MILESTONES_ALREADY_SET();
the value of upcomingMilestone not be updated after set milestones lead to manager can set milestones mutiple times.
8.fundPool does not work with fee-on-transfer token
1.Chain support chain cannot be removed or cleared in bridge contracts.
Contracts provide a way to add support for a chain; however, they do not provide a way to delete it. When a contract offers an addition method, it’s important to consider whether it should also provide a deletion method
2.Contract use msg.sender as remote chain receiver when bridge token.
AA wallet like safe has different wallet address on different chains. This vulnerability requires us to be familiar with some commonly used third-party tools in order to discover it
3.Two different transactions can result in the same txnHash value, thus breaking the approval process of transaction minting
Consider whether the keys in similar mappings are always unique?
4.Admin can’t burn tokens from blocklisted addresses because of a check in _beforeTokenTransfer
The burn operation prematurely calls the beforeTransfer function, but beforeTransfer needs to check if the address is blocked, which hinders the successful execution of the burn
Percentage of xETH in the Curve pool is between REBALANCE_UP_THRESHOLD and REBALANCE_DOWN_THRESHOLD. Rebalance operations are allowed When percentage of xETH is out of range.But the amount of xETH not checked which could lead to Percentage out of range after rebalance.
2.Invalid Validation
The value of the check does not match the expectation
3.ERC20
zero amount token transfer can cause DOS.
4.ERC20
check allowance == 0 should only use in initial or resetting to zero.
5.ERC20
when totalSupply() == 0
6.ERC20
bc of xETH.balanceOf(address(this)),staker can inflate the exchange rate by transferring tokens directly to the contract
7.MEV bot
uncorrect calculate slippage value.
8.Context
an array has add but no remove function.
9.ERC20
transfer token to target contract but can’t withdraw
The recipient of the flash loan will burn a certain amount of tokens as a fee. The recipient can be set to an arbitrary user who impelement receiver.onFlashLoan function.
In certain token-consuming operations, it’s necessary to consider whether only oneself is able to perform this action
2.Context
3.Common
Incorrectly implemented modifiers.
Always check modifiers revert?
4.Upgradable
Logic contact constructor should not update storage variable,cuz it will not be reflected in the proxy’s state.Instead we need use initializer function.
5.Precision Lost
user share can be burned cuz _EUSDAmount.mul(_totalShares).div(totalMintedEUSD) to zero.
6.Context
When using conditional statements, verify whether the values on the left and right sides of the equation meet the expected criteria.
7.Context
threshold value if different from the explanation in the document.
8.Dos
use IVault(pool).vaultType() vaultType can’t be a internel variable.
9.Math(M4)
when calculate token per second use wrong total amount.
As we know , blockchains are self-contained worlds.Smart contract can’t get information by invoking api like we do in web2.At the same time,centralized data providers are also not very reliable.For example,we need to know the price ETH/USDC when we swaping on defi like uniswap.Can we trust one single centralized data provider?The answer is obvious.So we need some decentralized data providers.Oracel act as an message bridge between blockchain and off-chain data provider.
why do SMART CONTRACTS need oracle?
To achieve deterministic execution, blockchains limit nodes to reaching consensus on simple binary (true/false) questions using only data stored on the blockchain itself.If blockchain get information from external data provider it would be impossible to achieve determinism.Different blockchain node maybe return different executes result.To solve those problems we create oracles.Oracle smart contract taking information from off-chain sources and then store the information on the blockchain.Since information stored on-chain is unalterable and publicly available, Ethereum nodes can safely use the oracle imported off-chain data to compute state changes without breaking consensus
how to use chainlink data feed oracle?
Let’s dive into an example,assume that we need to get the BTC/USD price on our smart contract. Chainlink provide data feed server on several networks.
Ethereum Mainnet
Sepolia Testnet
Gogerli Testnet
We gonna test the data feed server on goerli testnet by foundry tool.
First we need to import chainlink contract interface @chainlink/contracts/src/v0.8/interfaces/AggregatorV3Interface.sol.
Secondly,let’s init the smart contract using a specify target smart contract address which we copy from chainlink official document website.
Lastly,we just need invoke latestRoundData function which return the current price about BTC/USD.
function getLatestData() public view returns (int) { // prettier-ignore ( /* uint80 roundID */, int answer, /*uint startedAt*/, /*uint timeStamp*/, /*uint80 answeredInRound*/ ) = dataFeed.latestRoundData(); return answer; } }
we can use forge create command to deploy the contract.And then we invoke the getLatestData function via cast call command.Trust me you’ll get some return like this:
If you are using Chainlink Data Feeds on L2 networks like Arbitrum, Optimism, and Metis, you must also check the latest answer from the L2 Sequencer Uptime Feed to ensure that the data is accurate in the event of an L2 sequencer outage