-
Notifications
You must be signed in to change notification settings - Fork 34
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Create multi chain copies for on/off ramps, ARL & commit store (#772)
## Motivation Create multi chain copies for the below contracts: - `EVM2EVMOffRamp` -> `EVM2EVMMultiOffRamp` - `EVM2EVMOnRamp` -> `EVM2EVMMultiOnRamp` - `AggregateRateLimiter` -> `MultiAggregateRateLimiter` - `CommitStore` -> `MultiCommitStore` ## Solution New contracts are exact copies of the single chain ones. Some minor changes for CI purposes: - Removed some unused imports - Increased solhint max warnings --------- Co-authored-by: Evaldas Latoskinas <evaldas.latoskinas@smartcontract.com>
- Loading branch information
1 parent
07337eb
commit 71ae754
Showing
10 changed files
with
2,681 additions
and
29 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,5 @@ | ||
--- | ||
"@chainlink/contracts-ccip": minor | ||
--- | ||
|
||
create multi chain copies for on/off ramps, ARL & commit store |
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,93 @@ | ||
// SPDX-License-Identifier: BUSL-1.1 | ||
pragma solidity 0.8.19; | ||
|
||
import {IPriceRegistry} from "./interfaces/IPriceRegistry.sol"; | ||
|
||
import {OwnerIsCreator} from "./../shared/access/OwnerIsCreator.sol"; | ||
import {Client} from "./libraries/Client.sol"; | ||
import {RateLimiter} from "./libraries/RateLimiter.sol"; | ||
import {USDPriceWith18Decimals} from "./libraries/USDPriceWith18Decimals.sol"; | ||
|
||
/// @notice The aggregate rate limiter is a wrapper of the token bucket rate limiter | ||
/// which permits rate limiting based on the aggregate value of a group of | ||
/// token transfers, using a price registry to convert to a numeraire asset (e.g. USD). | ||
contract MultiAggregateRateLimiter is OwnerIsCreator { | ||
using RateLimiter for RateLimiter.TokenBucket; | ||
using USDPriceWith18Decimals for uint224; | ||
|
||
error PriceNotFoundForToken(address token); | ||
|
||
event AdminSet(address newAdmin); | ||
|
||
// The address of the token limit admin that has the same permissions as the owner. | ||
address internal s_admin; | ||
|
||
// The token bucket object that contains the bucket state. | ||
RateLimiter.TokenBucket private s_rateLimiter; | ||
|
||
/// @param config The RateLimiter.Config containing the capacity and refill rate | ||
/// of the bucket, plus the admin address. | ||
constructor(RateLimiter.Config memory config) { | ||
s_rateLimiter = RateLimiter.TokenBucket({ | ||
rate: config.rate, | ||
capacity: config.capacity, | ||
tokens: config.capacity, | ||
lastUpdated: uint32(block.timestamp), | ||
isEnabled: config.isEnabled | ||
}); | ||
} | ||
|
||
/// @notice Consumes value from the rate limiter bucket based on the token value given. | ||
function _rateLimitValue(uint256 value) internal { | ||
s_rateLimiter._consume(value, address(0)); | ||
} | ||
|
||
function _getTokenValue( | ||
Client.EVMTokenAmount memory tokenAmount, | ||
IPriceRegistry priceRegistry | ||
) internal view returns (uint256) { | ||
// not fetching validated price, as price staleness is not important for value-based rate limiting | ||
// we only need to verify the price is not 0 | ||
uint224 pricePerToken = priceRegistry.getTokenPrice(tokenAmount.token).value; | ||
if (pricePerToken == 0) revert PriceNotFoundForToken(tokenAmount.token); | ||
return pricePerToken._calcUSDValueFromTokenAmount(tokenAmount.amount); | ||
} | ||
|
||
/// @notice Gets the token bucket with its values for the block it was requested at. | ||
/// @return The token bucket. | ||
function currentRateLimiterState() external view returns (RateLimiter.TokenBucket memory) { | ||
return s_rateLimiter._currentTokenBucketState(); | ||
} | ||
|
||
/// @notice Sets the rate limited config. | ||
/// @param config The new rate limiter config. | ||
/// @dev should only be callable by the owner or token limit admin. | ||
function setRateLimiterConfig(RateLimiter.Config memory config) external onlyAdminOrOwner { | ||
s_rateLimiter._setTokenBucketConfig(config); | ||
} | ||
|
||
// ================================================================ | ||
// │ Access │ | ||
// ================================================================ | ||
|
||
/// @notice Gets the token limit admin address. | ||
/// @return the token limit admin address. | ||
function getTokenLimitAdmin() external view returns (address) { | ||
return s_admin; | ||
} | ||
|
||
/// @notice Sets the token limit admin address. | ||
/// @param newAdmin the address of the new admin. | ||
/// @dev setting this to address(0) indicates there is no active admin. | ||
function setAdmin(address newAdmin) external onlyAdminOrOwner { | ||
s_admin = newAdmin; | ||
emit AdminSet(newAdmin); | ||
} | ||
|
||
/// @notice a modifier that allows the owner or the s_tokenLimitAdmin call the functions | ||
/// it is applied to. | ||
modifier onlyAdminOrOwner() { | ||
if (msg.sender != owner() && msg.sender != s_admin) revert RateLimiter.OnlyCallableByAdminOrOwner(); | ||
_; | ||
} | ||
} |
Oops, something went wrong.