-
Notifications
You must be signed in to change notification settings - Fork 42
Add v2 verify routes #73
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
62c5f08
5b54ade
8e87a37
7e3d986
a098c3f
8900ffd
4bb7564
35057a6
fae108b
cba867c
7625556
9cd1693
498b363
84e3b71
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -44,13 +44,27 @@ pub mod verify; | |
|
||
pub(crate) type Result<T, E = EtherscanError> = std::result::Result<T, E>; | ||
|
||
/// The URL for the etherscan V2 API without the chainid param set. | ||
pub const ETHERSCAN_V2_API_BASE_URL: &str = "https://api.etherscan.io/v2/api?chainid="; | ||
|
||
/// The Etherscan.io API version 1 - classic verifier, one API per chain, 2 - new multichain | ||
/// verifier | ||
#[derive(Clone, Default, Debug, PartialEq, Copy)] | ||
pub enum EtherscanApiVersion { | ||
#[default] | ||
V1, | ||
V2, | ||
} | ||
|
||
/// The Etherscan.io API client. | ||
#[derive(Clone, Debug)] | ||
pub struct Client { | ||
/// Client that executes HTTP requests | ||
client: reqwest::Client, | ||
/// Etherscan API key | ||
api_key: Option<String>, | ||
/// Etherscan API version | ||
etherscan_api_version: EtherscanApiVersion, | ||
/// Etherscan API endpoint like <https://api(-chain).etherscan.io/api> | ||
etherscan_api_url: Url, | ||
/// Etherscan base endpoint like <https://etherscan.io> | ||
|
@@ -99,6 +113,16 @@ impl Client { | |
Client::builder().with_api_key(api_key).chain(chain)?.build() | ||
} | ||
|
||
/// Create a new client with the correct endpoint with the chain and chosen API v2 version | ||
pub fn new_v2_from_env(chain: Chain) -> Result<Self> { | ||
mattsse marked this conversation as resolved.
Show resolved
Hide resolved
|
||
let api_key = std::env::var("ETHERSCAN_API_KEY")?; | ||
Client::builder() | ||
.with_api_version(EtherscanApiVersion::V2) | ||
.with_api_key(api_key) | ||
.chain(chain)? | ||
.build() | ||
Comment on lines
+118
to
+123
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. then this can just call new ad with_version(v2) There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. A little confused as to where this would be called -- within the builder or skip the builder entirely and use |
||
} | ||
|
||
/// Create a new client with the correct endpoints based on the chain and API key | ||
/// from the default environment variable defined in [`Chain`]. | ||
pub fn new_from_env(chain: Chain) -> Result<Self> { | ||
|
@@ -155,6 +179,11 @@ impl Client { | |
self | ||
} | ||
|
||
/// Returns the configured etherscan api version. | ||
pub fn etherscan_api_version(&self) -> &EtherscanApiVersion { | ||
&self.etherscan_api_version | ||
} | ||
|
||
pub fn etherscan_api_url(&self) -> &Url { | ||
&self.etherscan_api_url | ||
} | ||
|
@@ -279,6 +308,8 @@ pub struct ClientBuilder { | |
api_key: Option<String>, | ||
/// Etherscan API endpoint like <https://api(-chain).etherscan.io/api> | ||
etherscan_api_url: Option<Url>, | ||
/// Etherscan API version (v2 is new verifier version, v1 is the default) | ||
etherscan_api_version: EtherscanApiVersion, | ||
/// Etherscan base endpoint like <https://etherscan.io> | ||
etherscan_url: Option<Url>, | ||
/// Path to where ABI files should be cached | ||
|
@@ -303,14 +334,29 @@ impl ClientBuilder { | |
) -> (reqwest::Result<Url>, reqwest::Result<Url>) { | ||
(api.into_url(), url.into_url()) | ||
} | ||
let (etherscan_api_url, etherscan_url) = chain | ||
let (default_etherscan_api_url, etherscan_url) = chain | ||
.named() | ||
.ok_or_else(|| EtherscanError::ChainNotSupported(chain))? | ||
.etherscan_urls() | ||
.map(urls) | ||
.ok_or_else(|| EtherscanError::ChainNotSupported(chain))?; | ||
|
||
self.with_chain_id(chain).with_api_url(etherscan_api_url?)?.with_url(etherscan_url?) | ||
// V2 etherscan default API urls are different – this handles that case. | ||
let etherscan_api_url = if self.etherscan_api_version == EtherscanApiVersion::V2 { | ||
let chain_id = chain.id(); | ||
Url::parse(&format!("{ETHERSCAN_V2_API_BASE_URL}{chain_id}")) | ||
.map_err(|_| EtherscanError::Builder("Bad URL Parse".into()))? | ||
} else { | ||
default_etherscan_api_url? | ||
}; | ||
|
||
self.with_chain_id(chain).with_api_url(etherscan_api_url)?.with_url(etherscan_url?) | ||
} | ||
|
||
/// Configures the etherscan api version | ||
pub fn with_api_version(mut self, api_version: EtherscanApiVersion) -> Self { | ||
self.etherscan_api_version = api_version; | ||
self | ||
} | ||
|
||
/// Configures the etherscan url | ||
|
@@ -370,14 +416,24 @@ impl ClientBuilder { | |
/// - `etherscan_api_url` | ||
/// - `etherscan_url` | ||
pub fn build(self) -> Result<Client> { | ||
let ClientBuilder { client, api_key, etherscan_api_url, etherscan_url, cache, chain_id } = | ||
self; | ||
let ClientBuilder { | ||
client, | ||
api_key, | ||
etherscan_api_version, | ||
etherscan_api_url, | ||
etherscan_url, | ||
cache, | ||
chain_id, | ||
} = self; | ||
|
||
let client = Client { | ||
client: client.unwrap_or_default(), | ||
api_key, | ||
etherscan_api_url: etherscan_api_url | ||
.clone() | ||
.ok_or_else(|| EtherscanError::Builder("etherscan api url".to_string()))?, | ||
// Set default API version to V1 if missing | ||
etherscan_api_version, | ||
etherscan_url: etherscan_url | ||
.ok_or_else(|| EtherscanError::Builder("etherscan url".to_string()))?, | ||
cache, | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1 +1 @@ | ||
{"expiry":1741879991,"data":[{"type":"constructor","inputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"deposit","inputs":[{"name":"pubkey","type":"bytes","internalType":"bytes"},{"name":"withdrawal_credentials","type":"bytes","internalType":"bytes"},{"name":"signature","type":"bytes","internalType":"bytes"},{"name":"deposit_data_root","type":"bytes32","internalType":"bytes32"}],"outputs":[],"stateMutability":"payable"},{"type":"function","name":"get_deposit_count","inputs":[],"outputs":[{"name":"","type":"bytes","internalType":"bytes"}],"stateMutability":"view"},{"type":"function","name":"get_deposit_root","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"supportsInterface","inputs":[{"name":"interfaceId","type":"bytes4","internalType":"bytes4"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"pure"},{"type":"event","name":"DepositEvent","inputs":[{"name":"pubkey","type":"bytes","indexed":false,"internalType":"bytes"},{"name":"withdrawal_credentials","type":"bytes","indexed":false,"internalType":"bytes"},{"name":"amount","type":"bytes","indexed":false,"internalType":"bytes"},{"name":"signature","type":"bytes","indexed":false,"internalType":"bytes"},{"name":"index","type":"bytes","indexed":false,"internalType":"bytes"}],"anonymous":false}]} | ||
{"expiry":1742116310,"data":[{"type":"constructor","inputs":[],"stateMutability":"nonpayable"},{"type":"function","name":"deposit","inputs":[{"name":"pubkey","type":"bytes","internalType":"bytes"},{"name":"withdrawal_credentials","type":"bytes","internalType":"bytes"},{"name":"signature","type":"bytes","internalType":"bytes"},{"name":"deposit_data_root","type":"bytes32","internalType":"bytes32"}],"outputs":[],"stateMutability":"payable"},{"type":"function","name":"get_deposit_count","inputs":[],"outputs":[{"name":"","type":"bytes","internalType":"bytes"}],"stateMutability":"view"},{"type":"function","name":"get_deposit_root","inputs":[],"outputs":[{"name":"","type":"bytes32","internalType":"bytes32"}],"stateMutability":"view"},{"type":"function","name":"supportsInterface","inputs":[{"name":"interfaceId","type":"bytes4","internalType":"bytes4"}],"outputs":[{"name":"","type":"bool","internalType":"bool"}],"stateMutability":"pure"},{"type":"event","name":"DepositEvent","inputs":[{"name":"pubkey","type":"bytes","indexed":false,"internalType":"bytes"},{"name":"withdrawal_credentials","type":"bytes","indexed":false,"internalType":"bytes"},{"name":"amount","type":"bytes","indexed":false,"internalType":"bytes"},{"name":"signature","type":"bytes","indexed":false,"internalType":"bytes"},{"name":"index","type":"bytes","indexed":false,"internalType":"bytes"}],"anonymous":false}]} |
Large diffs are not rendered by default.
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,109 @@ | ||
// SPDX-License-Identifier: MIT | ||
pragma solidity 0.8.17; | ||
|
||
/// @title IProtocolRewards | ||
/// @notice The interface for deposits & withdrawals for Protocol Rewards | ||
interface IProtocolRewards { | ||
/// @notice Rewards Deposit Event | ||
/// @param creator Creator for NFT rewards | ||
/// @param createReferral Creator referral | ||
/// @param mintReferral Mint referral user | ||
/// @param firstMinter First minter reward recipient | ||
/// @param zora ZORA recipient | ||
/// @param from The caller of the deposit | ||
/// @param creatorReward Creator reward amount | ||
/// @param createReferralReward Creator referral reward | ||
/// @param mintReferralReward Mint referral amount | ||
/// @param firstMinterReward First minter reward amount | ||
/// @param zoraReward ZORA amount | ||
event RewardsDeposit( | ||
address indexed creator, | ||
address indexed createReferral, | ||
address indexed mintReferral, | ||
address firstMinter, | ||
address zora, | ||
address from, | ||
uint256 creatorReward, | ||
uint256 createReferralReward, | ||
uint256 mintReferralReward, | ||
uint256 firstMinterReward, | ||
uint256 zoraReward | ||
); | ||
|
||
/// @notice Deposit Event | ||
/// @param from From user | ||
/// @param to To user (within contract) | ||
/// @param reason Optional bytes4 reason for indexing | ||
/// @param amount Amount of deposit | ||
/// @param comment Optional user comment | ||
event Deposit(address indexed from, address indexed to, bytes4 indexed reason, uint256 amount, string comment); | ||
|
||
/// @notice Withdraw Event | ||
/// @param from From user | ||
/// @param to To user (within contract) | ||
/// @param amount Amount of deposit | ||
event Withdraw(address indexed from, address indexed to, uint256 amount); | ||
|
||
/// @notice Cannot send to address zero | ||
error ADDRESS_ZERO(); | ||
|
||
/// @notice Function argument array length mismatch | ||
error ARRAY_LENGTH_MISMATCH(); | ||
|
||
/// @notice Invalid deposit | ||
error INVALID_DEPOSIT(); | ||
|
||
/// @notice Invalid signature for deposit | ||
error INVALID_SIGNATURE(); | ||
|
||
/// @notice Invalid withdraw | ||
error INVALID_WITHDRAW(); | ||
|
||
/// @notice Signature for withdraw is too old and has expired | ||
error SIGNATURE_DEADLINE_EXPIRED(); | ||
|
||
/// @notice Low-level ETH transfer has failed | ||
error TRANSFER_FAILED(); | ||
|
||
/// @notice Generic function to deposit ETH for a recipient, with an optional comment | ||
/// @param to Address to deposit to | ||
/// @param to Reason system reason for deposit (used for indexing) | ||
/// @param comment Optional comment as reason for deposit | ||
function deposit(address to, bytes4 why, string calldata comment) external payable; | ||
|
||
/// @notice Generic function to deposit ETH for multiple recipients, with an optional comment | ||
/// @param recipients recipients to send the amount to, array aligns with amounts | ||
/// @param amounts amounts to send to each recipient, array aligns with recipients | ||
/// @param reasons optional bytes4 hash for indexing | ||
/// @param comment Optional comment to include with mint | ||
function depositBatch(address[] calldata recipients, uint256[] calldata amounts, bytes4[] calldata reasons, string calldata comment) external payable; | ||
|
||
/// @notice Used by Zora ERC-721 & ERC-1155 contracts to deposit protocol rewards | ||
/// @param creator Creator for NFT rewards | ||
/// @param creatorReward Creator reward amount | ||
/// @param createReferral Creator referral | ||
/// @param createReferralReward Creator referral reward | ||
/// @param mintReferral Mint referral user | ||
/// @param mintReferralReward Mint referral amount | ||
/// @param firstMinter First minter reward | ||
/// @param firstMinterReward First minter reward amount | ||
/// @param zora ZORA recipient | ||
/// @param zoraReward ZORA amount | ||
function depositRewards( | ||
address creator, | ||
uint256 creatorReward, | ||
address createReferral, | ||
uint256 createReferralReward, | ||
address mintReferral, | ||
uint256 mintReferralReward, | ||
address firstMinter, | ||
uint256 firstMinterReward, | ||
address zora, | ||
uint256 zoraReward | ||
) external payable; | ||
|
||
/// @notice Withdraw protocol rewards | ||
/// @param to Withdraws from msg.sender to this address | ||
/// @param amount amount to withdraw | ||
function withdraw(address to, uint256 amount) external; | ||
} |
Uh oh!
There was an error while loading. Please reload this page.