Source Code
Overview
ETH Balance
0 ETH
Eth Value
$0.00Latest 25 from a total of 791 transactions
| Transaction Hash |
Method
|
Block
|
From
|
|
To
|
||||
|---|---|---|---|---|---|---|---|---|---|
| Publish Fee | 24423211 | 24 days ago | IN | 0 ETH | 0.00001814 | ||||
| Update Fee | 24423205 | 24 days ago | IN | 0 ETH | 0.00028524 | ||||
| Publish Fee | 24421349 | 24 days ago | IN | 0 ETH | 0.0000411 | ||||
| Update Fee | 24421343 | 24 days ago | IN | 0 ETH | 0.00047093 | ||||
| Publish Fee | 24419480 | 24 days ago | IN | 0 ETH | 0.0000275 | ||||
| Update Fee | 24419474 | 24 days ago | IN | 0 ETH | 0.00034511 | ||||
| Publish Fee | 24417612 | 25 days ago | IN | 0 ETH | 0.0000213 | ||||
| Update Fee | 24417607 | 25 days ago | IN | 0 ETH | 0.00018527 | ||||
| Publish Fee | 24415725 | 25 days ago | IN | 0 ETH | 0.0000537 | ||||
| Update Fee | 24415719 | 25 days ago | IN | 0 ETH | 0.00018692 | ||||
| Publish Fee | 24413862 | 25 days ago | IN | 0 ETH | 0.00028778 | ||||
| Update Fee | 24413853 | 25 days ago | IN | 0 ETH | 0.00035344 | ||||
| Publish Fee | 24411994 | 25 days ago | IN | 0 ETH | 0.00002539 | ||||
| Update Fee | 24411988 | 25 days ago | IN | 0 ETH | 0.00021833 | ||||
| Publish Fee | 24410123 | 26 days ago | IN | 0 ETH | 0.00000931 | ||||
| Update Fee | 24410117 | 26 days ago | IN | 0 ETH | 0.00021745 | ||||
| Publish Fee | 24408279 | 26 days ago | IN | 0 ETH | 0.0000166 | ||||
| Update Fee | 24408274 | 26 days ago | IN | 0 ETH | 0.00044464 | ||||
| Publish Fee | 24406433 | 26 days ago | IN | 0 ETH | 0.00001926 | ||||
| Update Fee | 24406427 | 26 days ago | IN | 0 ETH | 0.00089107 | ||||
| Publish Fee | 24404556 | 26 days ago | IN | 0 ETH | 0.00002093 | ||||
| Update Fee | 24404550 | 26 days ago | IN | 0 ETH | 0.00037139 | ||||
| Publish Fee | 24402672 | 27 days ago | IN | 0 ETH | 0.00002584 | ||||
| Update Fee | 24402666 | 27 days ago | IN | 0 ETH | 0.00040597 | ||||
| Publish Fee | 24400786 | 27 days ago | IN | 0 ETH | 0.00003191 |
View more zero value Internal Transactions in Advanced View mode
Advanced mode:
Loading...
Loading
Loading...
Loading
Cross-Chain Transactions
Loading...
Loading
Contract Name:
FeeManagerV3_v2
Compiler Version
v0.8.26+commit.8a97fa7a
Optimization Enabled:
Yes with 100 runs
Other Settings:
cancun EvmVersion
Contract Source Code (Solidity Standard Json-Input format)
// SPDX-License-Identifier: AGPL-3.0
pragma solidity ^0.8.24;
import {ECDSA} from "@solady/utils/ECDSA.sol";
import {Ownable} from "@solady/auth/Ownable.sol";
import {IHalo2Verifier} from "./interface/IHalo2Verifier.sol";
import {IPoolSwapFeeHelperV2} from "./interface/IPoolSwapFeeHelperV2.sol";
/**
* @title FeeManagerV3_v2 (For Balancer V2 PoolSwapFeeHelper)
* @notice Governs the fee management of Balancer pools with verification-based dynamic fee calculation with the PoolSwapFeeHelper
* @dev Key change with FeeManager.sol each deployment of a FeeManager is responsible for a given token pair
*/
contract FeeManagerV3_v2 is Ownable {
// Immutable
// Description of the FeeManager
string public description;
// Swap Fee Helper Address
IPoolSwapFeeHelperV2 public swapFeeHelper;
// lit network public key, important note! Burn the PKP NFT after the lit action is created to ensure that the program is immutable
// Otherwise the public key can run a different program
address public litPublicKey;
// EZKL Halo2Verifier Address
IHalo2Verifier public verifier;
// Scaling Factors for EZKL Halo2Verifier to Balancer Vault
uint256 public scalingFactorDiv;
uint256 public scalingFactorMul;
// signature expiry threshold time
uint256 public signatureExpiryThreshold;
// Mutable
uint256 public dynamicFee;
// Events
event FeeUpdated(uint256 swapFeePercentage);
event PoolUpdated(bytes32 indexed poolId, uint256 swapFeePercentage);
// Errors
error VerificationFailed();
error InvalidPool();
error SignatureExpired();
error SignatureFailed();
/**
* @notice Constructor to initialize the FeeManager contract
* @param _description description of the FeeManager
* @param _swapFeeHelper The swap fee helper address
* @param _litPublicKey lit public key. important note! Burn the PKP NFT after the lit action is created to ensure that the program is immutable
* @param _verifier EZKL's Halo2Verifier for verifying proofs
* @param _scalingFactorDiv scaling factor to divide by, to fit instances to FixedPoint.ONE
* @param _scalingFactorMul scaling factor to multiply by, to fit instances to FixedPoint.ONE
*/
constructor(
string memory _description,
address _swapFeeHelper,
address _litPublicKey,
address _verifier,
uint256 _scalingFactorDiv,
uint256 _scalingFactorMul,
uint256 _signatureExpiryThreshold
) {
_initializeOwner(msg.sender);
description = _description;
swapFeeHelper = IPoolSwapFeeHelperV2(_swapFeeHelper);
litPublicKey = _litPublicKey;
verifier = IHalo2Verifier(_verifier);
scalingFactorDiv = _scalingFactorDiv;
scalingFactorMul = _scalingFactorMul;
signatureExpiryThreshold = _signatureExpiryThreshold;
}
function updateSwapFeeHelper(address _swapFeeHelper) public onlyOwner {
swapFeeHelper = IPoolSwapFeeHelperV2(_swapFeeHelper);
}
function updateLitPublicKey(address _litPublicKey) public onlyOwner {
litPublicKey = _litPublicKey;
}
function updateVerifier(address _verifier) public onlyOwner {
verifier = IHalo2Verifier(_verifier);
}
function updateSignatureExpiryThreshold(uint256 _signatureExpiryThreshold) public onlyOwner {
signatureExpiryThreshold = _signatureExpiryThreshold;
}
function updateScalingFactors(uint256 _scalingFactorDiv, uint256 _scalingFactorMul) public onlyOwner {
scalingFactorDiv = _scalingFactorDiv;
scalingFactorMul = _scalingFactorMul;
}
/**
* @notice Updates the dynamicFee on the FeeManager
* @param proof ZK proof of the dynamic fee calculation
* @param inputData data for the inputData
* @param timestamp Timestamp of the data
* @param dynamicFeeUnscaled Unscaled dynamic fee value, this should be the last element of the instances in the proof file
* @param signature Signature of the dynamic fee calculation
*/
function updateFee(
bytes calldata proof,
uint256[] calldata inputData,
uint256 timestamp,
uint256 dynamicFeeUnscaled,
bytes memory signature
) external {
// Check if Signature has expired to prevent replay attacks
// Leave unchecked as timestamp + signatureExpiryThreshold is unlikely to overflow
// an invalid timestamp would fail verification anyway
unchecked {
if (block.timestamp > (timestamp + signatureExpiryThreshold)) {
revert SignatureExpired();
}
}
// check input data sig
address recovered = ECDSA.recover(keccak256(abi.encode(inputData, timestamp)), signature);
// Check if the keys match
if (recovered != litPublicKey) {
revert SignatureFailed();
}
// build instances array with dynamicFeeUnscaled as the last element
uint256 inputDataLength = inputData.length;
uint256[] memory instances = new uint256[](inputDataLength + 1);
assembly {
// pointer to first element in instances
let dest := add(instances, 0x20)
// copy len * 32 bytes from calldata array payload to memory
calldatacopy(dest, inputData.offset, mul(inputDataLength, 0x20))
// write the trailing dynamicFeeUnscaled
mstore(add(dest, mul(inputDataLength, 0x20)), dynamicFeeUnscaled)
}
// Verify the proof using the Halo2Verifier
if (!verifier.verifyProof(proof, instances)) {
revert VerificationFailed();
}
// Calculate scaled dynamicFee, we round to 5dp which is 0.00001e18 = 1e13 this is because solvers on Paraswap cannot process too many dp
// note 100% is 1e18 as given in FixedPoint.ONE
// note we add 5e12 to round
dynamicFee = ((((dynamicFeeUnscaled * scalingFactorMul) / scalingFactorDiv) + 5e12) / 1e13) * 1e13;
emit FeeUpdated(dynamicFee);
}
/**
* @notice Publishes the dynamicFee by calling setStaticSwapFeePercentage on the swap fee helper
* Pools need to have set the FeeManager contract as swap fee manager
* @param poolIds array of pool ids
*/
function publishFee(bytes32[] calldata poolIds) external {
// Load variables here to reduce SLOADs
uint256 poolsLength = poolIds.length;
uint256 fee = dynamicFee;
for (uint256 i = 0; i < poolsLength;) {
swapFeeHelper.setSwapFeePercentage(poolIds[i], fee);
emit PoolUpdated(poolIds[i], fee);
unchecked {
// Unlikely for poolsLength to overflow, so we leave unchecked to save gas
++i;
}
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
/// @notice Gas optimized ECDSA wrapper.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/utils/ECDSA.sol)
/// @author Modified from Solmate (https://github.com/transmissions11/solmate/blob/main/src/utils/ECDSA.sol)
/// @author Modified from OpenZeppelin (https://github.com/OpenZeppelin/openzeppelin-contracts/blob/master/contracts/utils/cryptography/ECDSA.sol)
///
/// @dev Note:
/// - The recovery functions use the ecrecover precompile (0x1).
/// - As of Solady version 0.0.68, the `recover` variants will revert upon recovery failure.
/// This is for more safety by default.
/// Use the `tryRecover` variants if you need to get the zero address back
/// upon recovery failure instead.
/// - As of Solady version 0.0.134, all `bytes signature` variants accept both
/// regular 65-byte `(r, s, v)` and EIP-2098 `(r, vs)` short form signatures.
/// See: https://eips.ethereum.org/EIPS/eip-2098
/// This is for calldata efficiency on smart accounts prevalent on L2s.
///
/// WARNING! Do NOT directly use signatures as unique identifiers:
/// - The recovery operations do NOT check if a signature is non-malleable.
/// - Use a nonce in the digest to prevent replay attacks on the same contract.
/// - Use EIP-712 for the digest to prevent replay attacks across different chains and contracts.
/// EIP-712 also enables readable signing of typed data for better user safety.
/// - If you need a unique hash from a signature, please use the `canonicalHash` functions.
library ECDSA {
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CONSTANTS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev The order of the secp256k1 elliptic curve.
uint256 internal constant N = 0xfffffffffffffffffffffffffffffffebaaedce6af48a03bbfd25e8cd0364141;
/// @dev `N/2 + 1`. Used for checking the malleability of the signature.
uint256 private constant _HALF_N_PLUS_1 =
0x7fffffffffffffffffffffffffffffff5d576e7357a4501ddfe92f46681b20a1;
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CUSTOM ERRORS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev The signature is invalid.
error InvalidSignature();
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* RECOVERY OPERATIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Recovers the signer's address from a message digest `hash`, and the `signature`.
function recover(bytes32 hash, bytes memory signature) internal view returns (address result) {
/// @solidity memory-safe-assembly
assembly {
for { let m := mload(0x40) } 1 {
mstore(0x00, 0x8baa579f) // `InvalidSignature()`.
revert(0x1c, 0x04)
} {
switch mload(signature)
case 64 {
let vs := mload(add(signature, 0x40))
mstore(0x20, add(shr(255, vs), 27)) // `v`.
mstore(0x60, shr(1, shl(1, vs))) // `s`.
}
case 65 {
mstore(0x20, byte(0, mload(add(signature, 0x60)))) // `v`.
mstore(0x60, mload(add(signature, 0x40))) // `s`.
}
default { continue }
mstore(0x00, hash)
mstore(0x40, mload(add(signature, 0x20))) // `r`.
result := mload(staticcall(gas(), 1, 0x00, 0x80, 0x01, 0x20))
mstore(0x60, 0) // Restore the zero slot.
mstore(0x40, m) // Restore the free memory pointer.
// `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
if returndatasize() { break }
}
}
}
/// @dev Recovers the signer's address from a message digest `hash`, and the `signature`.
function recoverCalldata(bytes32 hash, bytes calldata signature)
internal
view
returns (address result)
{
/// @solidity memory-safe-assembly
assembly {
for { let m := mload(0x40) } 1 {
mstore(0x00, 0x8baa579f) // `InvalidSignature()`.
revert(0x1c, 0x04)
} {
switch signature.length
case 64 {
let vs := calldataload(add(signature.offset, 0x20))
mstore(0x20, add(shr(255, vs), 27)) // `v`.
mstore(0x40, calldataload(signature.offset)) // `r`.
mstore(0x60, shr(1, shl(1, vs))) // `s`.
}
case 65 {
mstore(0x20, byte(0, calldataload(add(signature.offset, 0x40)))) // `v`.
calldatacopy(0x40, signature.offset, 0x40) // Copy `r` and `s`.
}
default { continue }
mstore(0x00, hash)
result := mload(staticcall(gas(), 1, 0x00, 0x80, 0x01, 0x20))
mstore(0x60, 0) // Restore the zero slot.
mstore(0x40, m) // Restore the free memory pointer.
// `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
if returndatasize() { break }
}
}
}
/// @dev Recovers the signer's address from a message digest `hash`,
/// and the EIP-2098 short form signature defined by `r` and `vs`.
function recover(bytes32 hash, bytes32 r, bytes32 vs) internal view returns (address result) {
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40) // Cache the free memory pointer.
mstore(0x00, hash)
mstore(0x20, add(shr(255, vs), 27)) // `v`.
mstore(0x40, r)
mstore(0x60, shr(1, shl(1, vs))) // `s`.
result := mload(staticcall(gas(), 1, 0x00, 0x80, 0x01, 0x20))
// `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
if iszero(returndatasize()) {
mstore(0x00, 0x8baa579f) // `InvalidSignature()`.
revert(0x1c, 0x04)
}
mstore(0x60, 0) // Restore the zero slot.
mstore(0x40, m) // Restore the free memory pointer.
}
}
/// @dev Recovers the signer's address from a message digest `hash`,
/// and the signature defined by `v`, `r`, `s`.
function recover(bytes32 hash, uint8 v, bytes32 r, bytes32 s)
internal
view
returns (address result)
{
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40) // Cache the free memory pointer.
mstore(0x00, hash)
mstore(0x20, and(v, 0xff))
mstore(0x40, r)
mstore(0x60, s)
result := mload(staticcall(gas(), 1, 0x00, 0x80, 0x01, 0x20))
// `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
if iszero(returndatasize()) {
mstore(0x00, 0x8baa579f) // `InvalidSignature()`.
revert(0x1c, 0x04)
}
mstore(0x60, 0) // Restore the zero slot.
mstore(0x40, m) // Restore the free memory pointer.
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* TRY-RECOVER OPERATIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
// WARNING!
// These functions will NOT revert upon recovery failure.
// Instead, they will return the zero address upon recovery failure.
// It is critical that the returned address is NEVER compared against
// a zero address (e.g. an uninitialized address variable).
/// @dev Recovers the signer's address from a message digest `hash`, and the `signature`.
function tryRecover(bytes32 hash, bytes memory signature)
internal
view
returns (address result)
{
/// @solidity memory-safe-assembly
assembly {
for { let m := mload(0x40) } 1 {} {
switch mload(signature)
case 64 {
let vs := mload(add(signature, 0x40))
mstore(0x20, add(shr(255, vs), 27)) // `v`.
mstore(0x60, shr(1, shl(1, vs))) // `s`.
}
case 65 {
mstore(0x20, byte(0, mload(add(signature, 0x60)))) // `v`.
mstore(0x60, mload(add(signature, 0x40))) // `s`.
}
default { break }
mstore(0x00, hash)
mstore(0x40, mload(add(signature, 0x20))) // `r`.
pop(staticcall(gas(), 1, 0x00, 0x80, 0x40, 0x20))
mstore(0x60, 0) // Restore the zero slot.
// `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
result := mload(xor(0x60, returndatasize()))
mstore(0x40, m) // Restore the free memory pointer.
break
}
}
}
/// @dev Recovers the signer's address from a message digest `hash`, and the `signature`.
function tryRecoverCalldata(bytes32 hash, bytes calldata signature)
internal
view
returns (address result)
{
/// @solidity memory-safe-assembly
assembly {
for { let m := mload(0x40) } 1 {} {
switch signature.length
case 64 {
let vs := calldataload(add(signature.offset, 0x20))
mstore(0x20, add(shr(255, vs), 27)) // `v`.
mstore(0x40, calldataload(signature.offset)) // `r`.
mstore(0x60, shr(1, shl(1, vs))) // `s`.
}
case 65 {
mstore(0x20, byte(0, calldataload(add(signature.offset, 0x40)))) // `v`.
calldatacopy(0x40, signature.offset, 0x40) // Copy `r` and `s`.
}
default { break }
mstore(0x00, hash)
pop(staticcall(gas(), 1, 0x00, 0x80, 0x40, 0x20))
mstore(0x60, 0) // Restore the zero slot.
// `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
result := mload(xor(0x60, returndatasize()))
mstore(0x40, m) // Restore the free memory pointer.
break
}
}
}
/// @dev Recovers the signer's address from a message digest `hash`,
/// and the EIP-2098 short form signature defined by `r` and `vs`.
function tryRecover(bytes32 hash, bytes32 r, bytes32 vs)
internal
view
returns (address result)
{
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40) // Cache the free memory pointer.
mstore(0x00, hash)
mstore(0x20, add(shr(255, vs), 27)) // `v`.
mstore(0x40, r)
mstore(0x60, shr(1, shl(1, vs))) // `s`.
pop(staticcall(gas(), 1, 0x00, 0x80, 0x40, 0x20))
mstore(0x60, 0) // Restore the zero slot.
// `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
result := mload(xor(0x60, returndatasize()))
mstore(0x40, m) // Restore the free memory pointer.
}
}
/// @dev Recovers the signer's address from a message digest `hash`,
/// and the signature defined by `v`, `r`, `s`.
function tryRecover(bytes32 hash, uint8 v, bytes32 r, bytes32 s)
internal
view
returns (address result)
{
/// @solidity memory-safe-assembly
assembly {
let m := mload(0x40) // Cache the free memory pointer.
mstore(0x00, hash)
mstore(0x20, and(v, 0xff))
mstore(0x40, r)
mstore(0x60, s)
pop(staticcall(gas(), 1, 0x00, 0x80, 0x40, 0x20))
mstore(0x60, 0) // Restore the zero slot.
// `returndatasize()` will be `0x20` upon success, and `0x00` otherwise.
result := mload(xor(0x60, returndatasize()))
mstore(0x40, m) // Restore the free memory pointer.
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* HASHING OPERATIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Returns an Ethereum Signed Message, created from a `hash`.
/// This produces a hash corresponding to the one signed with the
/// [`eth_sign`](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_sign)
/// JSON-RPC method as part of EIP-191.
function toEthSignedMessageHash(bytes32 hash) internal pure returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
mstore(0x20, hash) // Store into scratch space for keccak256.
mstore(0x00, "\x00\x00\x00\x00\x19Ethereum Signed Message:\n32") // 28 bytes.
result := keccak256(0x04, 0x3c) // `32 * 2 - (32 - 28) = 60 = 0x3c`.
}
}
/// @dev Returns an Ethereum Signed Message, created from `s`.
/// This produces a hash corresponding to the one signed with the
/// [`eth_sign`](https://ethereum.org/en/developers/docs/apis/json-rpc/#eth_sign)
/// JSON-RPC method as part of EIP-191.
/// Note: Supports lengths of `s` up to 999999 bytes.
function toEthSignedMessageHash(bytes memory s) internal pure returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
let sLength := mload(s)
let o := 0x20
mstore(o, "\x19Ethereum Signed Message:\n") // 26 bytes, zero-right-padded.
mstore(0x00, 0x00)
// Convert the `s.length` to ASCII decimal representation: `base10(s.length)`.
for { let temp := sLength } 1 {} {
o := sub(o, 1)
mstore8(o, add(48, mod(temp, 10)))
temp := div(temp, 10)
if iszero(temp) { break }
}
let n := sub(0x3a, o) // Header length: `26 + 32 - o`.
// Throw an out-of-offset error (consumes all gas) if the header exceeds 32 bytes.
returndatacopy(returndatasize(), returndatasize(), gt(n, 0x20))
mstore(s, or(mload(0x00), mload(n))) // Temporarily store the header.
result := keccak256(add(s, sub(0x20, n)), add(n, sLength))
mstore(s, sLength) // Restore the length.
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CANONICAL HASH FUNCTIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
// The following functions return the hash of the signature in its canonicalized format,
// which is the 65-byte `abi.encodePacked(r, s, uint8(v))`, where `v` is either 27 or 28.
// If `s` is greater than `N / 2` then it will be converted to `N - s`
// and the `v` value will be flipped.
// If the signature has an invalid length, or if `v` is invalid,
// a uniquely corrupt hash will be returned.
// These functions are useful for "poor-mans-VRF".
/// @dev Returns the canonical hash of `signature`.
function canonicalHash(bytes memory signature) internal pure returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
let l := mload(signature)
for {} 1 {} {
mstore(0x00, mload(add(signature, 0x20))) // `r`.
let s := mload(add(signature, 0x40))
let v := mload(add(signature, 0x41))
if eq(l, 64) {
v := add(shr(255, s), 27)
s := shr(1, shl(1, s))
}
if iszero(lt(s, _HALF_N_PLUS_1)) {
v := xor(v, 7)
s := sub(N, s)
}
mstore(0x21, v)
mstore(0x20, s)
result := keccak256(0x00, 0x41)
mstore(0x21, 0) // Restore the overwritten part of the free memory pointer.
break
}
// If the length is neither 64 nor 65, return a uniquely corrupted hash.
if iszero(lt(sub(l, 64), 2)) {
// `bytes4(keccak256("InvalidSignatureLength"))`.
result := xor(keccak256(add(signature, 0x20), l), 0xd62f1ab2)
}
}
}
/// @dev Returns the canonical hash of `signature`.
function canonicalHashCalldata(bytes calldata signature)
internal
pure
returns (bytes32 result)
{
/// @solidity memory-safe-assembly
assembly {
for {} 1 {} {
mstore(0x00, calldataload(signature.offset)) // `r`.
let s := calldataload(add(signature.offset, 0x20))
let v := calldataload(add(signature.offset, 0x21))
if eq(signature.length, 64) {
v := add(shr(255, s), 27)
s := shr(1, shl(1, s))
}
if iszero(lt(s, _HALF_N_PLUS_1)) {
v := xor(v, 7)
s := sub(N, s)
}
mstore(0x21, v)
mstore(0x20, s)
result := keccak256(0x00, 0x41)
mstore(0x21, 0) // Restore the overwritten part of the free memory pointer.
break
}
// If the length is neither 64 nor 65, return a uniquely corrupted hash.
if iszero(lt(sub(signature.length, 64), 2)) {
calldatacopy(mload(0x40), signature.offset, signature.length)
// `bytes4(keccak256("InvalidSignatureLength"))`.
result := xor(keccak256(mload(0x40), signature.length), 0xd62f1ab2)
}
}
}
/// @dev Returns the canonical hash of `signature`.
function canonicalHash(bytes32 r, bytes32 vs) internal pure returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, r) // `r`.
let v := add(shr(255, vs), 27)
let s := shr(1, shl(1, vs))
mstore(0x21, v)
mstore(0x20, s)
result := keccak256(0x00, 0x41)
mstore(0x21, 0) // Restore the overwritten part of the free memory pointer.
}
}
/// @dev Returns the canonical hash of `signature`.
function canonicalHash(uint8 v, bytes32 r, bytes32 s) internal pure returns (bytes32 result) {
/// @solidity memory-safe-assembly
assembly {
mstore(0x00, r) // `r`.
if iszero(lt(s, _HALF_N_PLUS_1)) {
v := xor(v, 7)
s := sub(N, s)
}
mstore(0x21, v)
mstore(0x20, s)
result := keccak256(0x00, 0x41)
mstore(0x21, 0) // Restore the overwritten part of the free memory pointer.
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* EMPTY CALLDATA HELPERS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Returns an empty calldata bytes.
function emptySignature() internal pure returns (bytes calldata signature) {
/// @solidity memory-safe-assembly
assembly {
signature.length := 0
}
}
}// SPDX-License-Identifier: MIT
pragma solidity ^0.8.4;
/// @notice Simple single owner authorization mixin.
/// @author Solady (https://github.com/vectorized/solady/blob/main/src/auth/Ownable.sol)
///
/// @dev Note:
/// This implementation does NOT auto-initialize the owner to `msg.sender`.
/// You MUST call the `_initializeOwner` in the constructor / initializer.
///
/// While the ownable portion follows
/// [EIP-173](https://eips.ethereum.org/EIPS/eip-173) for compatibility,
/// the nomenclature for the 2-step ownership handover may be unique to this codebase.
abstract contract Ownable {
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* CUSTOM ERRORS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev The caller is not authorized to call the function.
error Unauthorized();
/// @dev The `newOwner` cannot be the zero address.
error NewOwnerIsZeroAddress();
/// @dev The `pendingOwner` does not have a valid handover request.
error NoHandoverRequest();
/// @dev Cannot double-initialize.
error AlreadyInitialized();
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* EVENTS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev The ownership is transferred from `oldOwner` to `newOwner`.
/// This event is intentionally kept the same as OpenZeppelin's Ownable to be
/// compatible with indexers and [EIP-173](https://eips.ethereum.org/EIPS/eip-173),
/// despite it not being as lightweight as a single argument event.
event OwnershipTransferred(address indexed oldOwner, address indexed newOwner);
/// @dev An ownership handover to `pendingOwner` has been requested.
event OwnershipHandoverRequested(address indexed pendingOwner);
/// @dev The ownership handover to `pendingOwner` has been canceled.
event OwnershipHandoverCanceled(address indexed pendingOwner);
/// @dev `keccak256(bytes("OwnershipTransferred(address,address)"))`.
uint256 private constant _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE =
0x8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e0;
/// @dev `keccak256(bytes("OwnershipHandoverRequested(address)"))`.
uint256 private constant _OWNERSHIP_HANDOVER_REQUESTED_EVENT_SIGNATURE =
0xdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d;
/// @dev `keccak256(bytes("OwnershipHandoverCanceled(address)"))`.
uint256 private constant _OWNERSHIP_HANDOVER_CANCELED_EVENT_SIGNATURE =
0xfa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c92;
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* STORAGE */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev The owner slot is given by:
/// `bytes32(~uint256(uint32(bytes4(keccak256("_OWNER_SLOT_NOT")))))`.
/// It is intentionally chosen to be a high value
/// to avoid collision with lower slots.
/// The choice of manual storage layout is to enable compatibility
/// with both regular and upgradeable contracts.
bytes32 internal constant _OWNER_SLOT =
0xffffffffffffffffffffffffffffffffffffffffffffffffffffffff74873927;
/// The ownership handover slot of `newOwner` is given by:
/// ```
/// mstore(0x00, or(shl(96, user), _HANDOVER_SLOT_SEED))
/// let handoverSlot := keccak256(0x00, 0x20)
/// ```
/// It stores the expiry timestamp of the two-step ownership handover.
uint256 private constant _HANDOVER_SLOT_SEED = 0x389a75e1;
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* INTERNAL FUNCTIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Override to return true to make `_initializeOwner` prevent double-initialization.
function _guardInitializeOwner() internal pure virtual returns (bool guard) {}
/// @dev Initializes the owner directly without authorization guard.
/// This function must be called upon initialization,
/// regardless of whether the contract is upgradeable or not.
/// This is to enable generalization to both regular and upgradeable contracts,
/// and to save gas in case the initial owner is not the caller.
/// For performance reasons, this function will not check if there
/// is an existing owner.
function _initializeOwner(address newOwner) internal virtual {
if (_guardInitializeOwner()) {
/// @solidity memory-safe-assembly
assembly {
let ownerSlot := _OWNER_SLOT
if sload(ownerSlot) {
mstore(0x00, 0x0dc149f0) // `AlreadyInitialized()`.
revert(0x1c, 0x04)
}
// Clean the upper 96 bits.
newOwner := shr(96, shl(96, newOwner))
// Store the new value.
sstore(ownerSlot, or(newOwner, shl(255, iszero(newOwner))))
// Emit the {OwnershipTransferred} event.
log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, 0, newOwner)
}
} else {
/// @solidity memory-safe-assembly
assembly {
// Clean the upper 96 bits.
newOwner := shr(96, shl(96, newOwner))
// Store the new value.
sstore(_OWNER_SLOT, newOwner)
// Emit the {OwnershipTransferred} event.
log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, 0, newOwner)
}
}
}
/// @dev Sets the owner directly without authorization guard.
function _setOwner(address newOwner) internal virtual {
if (_guardInitializeOwner()) {
/// @solidity memory-safe-assembly
assembly {
let ownerSlot := _OWNER_SLOT
// Clean the upper 96 bits.
newOwner := shr(96, shl(96, newOwner))
// Emit the {OwnershipTransferred} event.
log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, sload(ownerSlot), newOwner)
// Store the new value.
sstore(ownerSlot, or(newOwner, shl(255, iszero(newOwner))))
}
} else {
/// @solidity memory-safe-assembly
assembly {
let ownerSlot := _OWNER_SLOT
// Clean the upper 96 bits.
newOwner := shr(96, shl(96, newOwner))
// Emit the {OwnershipTransferred} event.
log3(0, 0, _OWNERSHIP_TRANSFERRED_EVENT_SIGNATURE, sload(ownerSlot), newOwner)
// Store the new value.
sstore(ownerSlot, newOwner)
}
}
}
/// @dev Throws if the sender is not the owner.
function _checkOwner() internal view virtual {
/// @solidity memory-safe-assembly
assembly {
// If the caller is not the stored owner, revert.
if iszero(eq(caller(), sload(_OWNER_SLOT))) {
mstore(0x00, 0x82b42900) // `Unauthorized()`.
revert(0x1c, 0x04)
}
}
}
/// @dev Returns how long a two-step ownership handover is valid for in seconds.
/// Override to return a different value if needed.
/// Made internal to conserve bytecode. Wrap it in a public function if needed.
function _ownershipHandoverValidFor() internal view virtual returns (uint64) {
return 48 * 3600;
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* PUBLIC UPDATE FUNCTIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Allows the owner to transfer the ownership to `newOwner`.
function transferOwnership(address newOwner) public payable virtual onlyOwner {
/// @solidity memory-safe-assembly
assembly {
if iszero(shl(96, newOwner)) {
mstore(0x00, 0x7448fbae) // `NewOwnerIsZeroAddress()`.
revert(0x1c, 0x04)
}
}
_setOwner(newOwner);
}
/// @dev Allows the owner to renounce their ownership.
function renounceOwnership() public payable virtual onlyOwner {
_setOwner(address(0));
}
/// @dev Request a two-step ownership handover to the caller.
/// The request will automatically expire in 48 hours (172800 seconds) by default.
function requestOwnershipHandover() public payable virtual {
unchecked {
uint256 expires = block.timestamp + _ownershipHandoverValidFor();
/// @solidity memory-safe-assembly
assembly {
// Compute and set the handover slot to `expires`.
mstore(0x0c, _HANDOVER_SLOT_SEED)
mstore(0x00, caller())
sstore(keccak256(0x0c, 0x20), expires)
// Emit the {OwnershipHandoverRequested} event.
log2(0, 0, _OWNERSHIP_HANDOVER_REQUESTED_EVENT_SIGNATURE, caller())
}
}
}
/// @dev Cancels the two-step ownership handover to the caller, if any.
function cancelOwnershipHandover() public payable virtual {
/// @solidity memory-safe-assembly
assembly {
// Compute and set the handover slot to 0.
mstore(0x0c, _HANDOVER_SLOT_SEED)
mstore(0x00, caller())
sstore(keccak256(0x0c, 0x20), 0)
// Emit the {OwnershipHandoverCanceled} event.
log2(0, 0, _OWNERSHIP_HANDOVER_CANCELED_EVENT_SIGNATURE, caller())
}
}
/// @dev Allows the owner to complete the two-step ownership handover to `pendingOwner`.
/// Reverts if there is no existing ownership handover requested by `pendingOwner`.
function completeOwnershipHandover(address pendingOwner) public payable virtual onlyOwner {
/// @solidity memory-safe-assembly
assembly {
// Compute and set the handover slot to 0.
mstore(0x0c, _HANDOVER_SLOT_SEED)
mstore(0x00, pendingOwner)
let handoverSlot := keccak256(0x0c, 0x20)
// If the handover does not exist, or has expired.
if gt(timestamp(), sload(handoverSlot)) {
mstore(0x00, 0x6f5e8818) // `NoHandoverRequest()`.
revert(0x1c, 0x04)
}
// Set the handover slot to 0.
sstore(handoverSlot, 0)
}
_setOwner(pendingOwner);
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* PUBLIC READ FUNCTIONS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Returns the owner of the contract.
function owner() public view virtual returns (address result) {
/// @solidity memory-safe-assembly
assembly {
result := sload(_OWNER_SLOT)
}
}
/// @dev Returns the expiry timestamp for the two-step ownership handover to `pendingOwner`.
function ownershipHandoverExpiresAt(address pendingOwner)
public
view
virtual
returns (uint256 result)
{
/// @solidity memory-safe-assembly
assembly {
// Compute the handover slot.
mstore(0x0c, _HANDOVER_SLOT_SEED)
mstore(0x00, pendingOwner)
// Load the handover slot.
result := sload(keccak256(0x0c, 0x20))
}
}
/*´:°•.°+.*•´.*:˚.°*.˚•´.°:°•.°•.*•´.*:˚.°*.˚•´.°:°•.°+.*•´.*:*/
/* MODIFIERS */
/*.•°:°.´+˚.*°.˚:*.´•*.+°.•°:´*.´•*.•°.•°:°.´:•˚°.*°.˚:*.´+°.•*/
/// @dev Marks a function as only callable by the owner.
modifier onlyOwner() virtual {
_checkOwner();
_;
}
}//SPDX-License-Identifier: MIT
pragma solidity ^0.8.20;
/**
* @title Halo2Verifier from ezkl
* @notice This is the Halo2Verifier from the ezkl library
* You will need to obtain the PK (proving key) in order to generate the proof and instances
*/
interface IHalo2Verifier {
function verifyProof(bytes calldata proof, uint256[] calldata instances) external returns (bool);
}// SPDX-License-Identifier: GPL-3.0-or-later
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
pragma solidity >=0.7.0 <0.9.0;
/**
* @notice Maintain a set of pools whose static swap fee percentages can be changed from here, vs. directly on the pool.
* @dev Governance can add a set of pools to this contract, then grant swap fee setting permission to accounts on this
* contract, which allows greater granularity than setting the permission directly on the pool contracts.
* @dev Truncated version of the IPoolSwapFeeHelper interface for the FeeManagerV3_v2 contract
*/
interface IPoolSwapFeeHelperV2 {
/**
*
* Manage Pools
*
*/
/**
* @notice Set the swap fee percentage on a given pool.
* @dev This is a permissioned function. Governance must grant this contract permission to call
* `setSwapFeePercentage` on the pool. Since action ids are factory-based, this must be done for each pool type.
*
* @param poolId The ID of the pool
* @param swapFeePercentage The new swap fee percentage
*/
function setSwapFeePercentage(bytes32 poolId, uint256 swapFeePercentage) external;
}{
"remappings": [
"@openzeppelin/=lib/openzeppelin-contracts/",
"@solady/=lib/solady/src/",
"erc4626-tests/=lib/openzeppelin-contracts/lib/erc4626-tests/",
"forge-std/=lib/forge-std/src/",
"halmos-cheatcodes/=lib/openzeppelin-contracts/lib/halmos-cheatcodes/src/",
"openzeppelin-contracts/=lib/openzeppelin-contracts/",
"solady/=lib/solady/src/"
],
"optimizer": {
"enabled": true,
"runs": 100
},
"metadata": {
"useLiteralContent": false,
"bytecodeHash": "ipfs",
"appendCBOR": true
},
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
},
"evmVersion": "cancun",
"viaIR": false
}Contract Security Audit
- No Contract Security Audit Submitted- Submit Audit Here
Contract ABI
API[{"inputs":[{"internalType":"string","name":"_description","type":"string"},{"internalType":"address","name":"_swapFeeHelper","type":"address"},{"internalType":"address","name":"_litPublicKey","type":"address"},{"internalType":"address","name":"_verifier","type":"address"},{"internalType":"uint256","name":"_scalingFactorDiv","type":"uint256"},{"internalType":"uint256","name":"_scalingFactorMul","type":"uint256"},{"internalType":"uint256","name":"_signatureExpiryThreshold","type":"uint256"}],"stateMutability":"nonpayable","type":"constructor"},{"inputs":[],"name":"AlreadyInitialized","type":"error"},{"inputs":[],"name":"InvalidPool","type":"error"},{"inputs":[],"name":"NewOwnerIsZeroAddress","type":"error"},{"inputs":[],"name":"NoHandoverRequest","type":"error"},{"inputs":[],"name":"SignatureExpired","type":"error"},{"inputs":[],"name":"SignatureFailed","type":"error"},{"inputs":[],"name":"Unauthorized","type":"error"},{"inputs":[],"name":"VerificationFailed","type":"error"},{"anonymous":false,"inputs":[{"indexed":false,"internalType":"uint256","name":"swapFeePercentage","type":"uint256"}],"name":"FeeUpdated","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pendingOwner","type":"address"}],"name":"OwnershipHandoverCanceled","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"pendingOwner","type":"address"}],"name":"OwnershipHandoverRequested","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"address","name":"oldOwner","type":"address"},{"indexed":true,"internalType":"address","name":"newOwner","type":"address"}],"name":"OwnershipTransferred","type":"event"},{"anonymous":false,"inputs":[{"indexed":true,"internalType":"bytes32","name":"poolId","type":"bytes32"},{"indexed":false,"internalType":"uint256","name":"swapFeePercentage","type":"uint256"}],"name":"PoolUpdated","type":"event"},{"inputs":[],"name":"cancelOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"address","name":"pendingOwner","type":"address"}],"name":"completeOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"description","outputs":[{"internalType":"string","name":"","type":"string"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"dynamicFee","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"litPublicKey","outputs":[{"internalType":"address","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"owner","outputs":[{"internalType":"address","name":"result","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"pendingOwner","type":"address"}],"name":"ownershipHandoverExpiresAt","outputs":[{"internalType":"uint256","name":"result","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"bytes32[]","name":"poolIds","type":"bytes32[]"}],"name":"publishFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"renounceOwnership","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"requestOwnershipHandover","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[],"name":"scalingFactorDiv","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"scalingFactorMul","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"signatureExpiryThreshold","outputs":[{"internalType":"uint256","name":"","type":"uint256"}],"stateMutability":"view","type":"function"},{"inputs":[],"name":"swapFeeHelper","outputs":[{"internalType":"contract IPoolSwapFeeHelperV2","name":"","type":"address"}],"stateMutability":"view","type":"function"},{"inputs":[{"internalType":"address","name":"newOwner","type":"address"}],"name":"transferOwnership","outputs":[],"stateMutability":"payable","type":"function"},{"inputs":[{"internalType":"bytes","name":"proof","type":"bytes"},{"internalType":"uint256[]","name":"inputData","type":"uint256[]"},{"internalType":"uint256","name":"timestamp","type":"uint256"},{"internalType":"uint256","name":"dynamicFeeUnscaled","type":"uint256"},{"internalType":"bytes","name":"signature","type":"bytes"}],"name":"updateFee","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_litPublicKey","type":"address"}],"name":"updateLitPublicKey","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_scalingFactorDiv","type":"uint256"},{"internalType":"uint256","name":"_scalingFactorMul","type":"uint256"}],"name":"updateScalingFactors","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"uint256","name":"_signatureExpiryThreshold","type":"uint256"}],"name":"updateSignatureExpiryThreshold","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_swapFeeHelper","type":"address"}],"name":"updateSwapFeeHelper","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[{"internalType":"address","name":"_verifier","type":"address"}],"name":"updateVerifier","outputs":[],"stateMutability":"nonpayable","type":"function"},{"inputs":[],"name":"verifier","outputs":[{"internalType":"contract IHalo2Verifier","name":"","type":"address"}],"stateMutability":"view","type":"function"}]Contract Creation Code
608060405234801561000f575f80fd5b5060405161112738038061112783398101604081905261002e91610100565b61003733610096565b5f6100428882610282565b50600180546001600160a01b03199081166001600160a01b0398891617909155600280548216968816969096179095556003805490951693909516929092179092556004919091556005556006555061033c565b6001600160a01b0316638b78c6d819819055805f7f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e08180a350565b634e487b7160e01b5f52604160045260245ffd5b80516001600160a01b03811681146100fb575f80fd5b919050565b5f805f805f805f60e0888a031215610116575f80fd5b87516001600160401b0381111561012b575f80fd5b8801601f81018a1361013b575f80fd5b80516001600160401b03811115610154576101546100d1565b604051601f8201601f19908116603f011681016001600160401b0381118282101715610182576101826100d1565b6040528181528282016020018c1015610199575f80fd5b8160208401602083015e5f602083830101528099505050506101bd602089016100e5565b95506101cb604089016100e5565b94506101d9606089016100e5565b608089015160a08a015160c0909a0151989b979a509598909795969095945092505050565b600181811c9082168061021257607f821691505b60208210810361023057634e487b7160e01b5f52602260045260245ffd5b50919050565b601f82111561027d57805f5260205f20601f840160051c8101602085101561025b5750805b601f840160051c820191505b8181101561027a575f8155600101610267565b50505b505050565b81516001600160401b0381111561029b5761029b6100d1565b6102af816102a984546101fe565b84610236565b6020601f8211600181146102e1575f83156102ca5750848201515b5f19600385901b1c1916600184901b17845561027a565b5f84815260208120601f198516915b8281101561031057878501518255602094850194600190920191016102f0565b508482101561032d57868401515f19600387901b60f8161c191681555b50505050600190811b01905550565b610dde806103495f395ff3fe608060405260043610610131575f3560e01c80638da5cb5b116100a8578063b39db6861161006d578063b39db686146102ea578063ef2c21d914610309578063f04e283e1461031e578063f2fde38b14610331578063fbcbc5e614610344578063fee81cf414610363575f80fd5b80638da5cb5b1461026a57806397fc007c146102825780639b19f356146102a1578063a3b1bc24146102b6578063b20d550b146102d5575f80fd5b80636250bb55116100f95780636250bb55146101c5578063715018a6146101e45780637284e416146101ec5780637e390d591461020d57806384a101541461022c5780638771b6641461024b575f80fd5b806325692962146101355780632b7ac3f31461013f5780633534d6941461017b5780633ad5a7241461019a57806354d1f13d146101bd575b5f80fd5b61013d610394565b005b34801561014a575f80fd5b5060035461015e906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b348015610186575f80fd5b5061013d610195366004610a7c565b6103e0565b3480156101a5575f80fd5b506101af60055481565b604051908152602001610172565b61013d6105ef565b3480156101d0575f80fd5b5061013d6101df366004610b4f565b610628565b61013d610652565b3480156101f7575f80fd5b50610200610665565b6040516101729190610b7c565b348015610218575f80fd5b5061013d610227366004610bb1565b6106f0565b348015610237575f80fd5b5061013d610246366004610bc8565b6106fd565b348015610256575f80fd5b5061013d610265366004610b4f565b610710565b348015610275575f80fd5b50638b78c6d8195461015e565b34801561028d575f80fd5b5061013d61029c366004610b4f565b61073a565b3480156102ac575f80fd5b506101af60045481565b3480156102c1575f80fd5b5060025461015e906001600160a01b031681565b3480156102e0575f80fd5b506101af60075481565b3480156102f5575f80fd5b5061013d610304366004610be8565b610764565b348015610314575f80fd5b506101af60065481565b61013d61032c366004610b4f565b610852565b61013d61033f366004610b4f565b61088f565b34801561034f575f80fd5b5060015461015e906001600160a01b031681565b34801561036e575f80fd5b506101af61037d366004610b4f565b63389a75e1600c9081525f91909152602090205490565b5f6202a3006001600160401b03164201905063389a75e1600c52335f52806020600c2055337fdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d5f80a250565b600654830142111561040557604051630819bdcd60e01b815260040160405180910390fd5b5f61043a86868660405160200161041e93929190610c26565b60405160208183030381529060405280519060200120836108b5565b6002549091506001600160a01b0380831691161461046b5760405163338a70bd60e11b815260040160405180910390fd5b845f610478826001610c76565b6001600160401b0381111561048f5761048f6109df565b6040519080825280602002602001820160405280156104b8578160200160208202803683370190505b50905060208101602083028982376020830201859052600354604051631e8e1e1360e01b81526001600160a01b0390911690631e8e1e1390610502908d908d908690600401610c8f565b6020604051808303815f875af115801561051e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105429190610d07565b61055f5760405163439cc0cd60e01b815260040160405180910390fd5b6509184e72a000600454600554876105779190610d26565b6105819190610d3d565b6105919065048c27395000610c76565b61059b9190610d3d565b6105ab906509184e72a000610d26565b60078190556040519081527f8c4d35e54a3f2ef1134138fd8ea3daee6a3c89e10d2665996babdf70261e2c769060200160405180910390a150505050505050505050565b63389a75e1600c52335f525f6020600c2055337ffa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c925f80a2565b610630610941565b600180546001600160a01b0319166001600160a01b0392909216919091179055565b61065a610941565b6106635f61095b565b565b5f805461067190610d5c565b80601f016020809104026020016040519081016040528092919081815260200182805461069d90610d5c565b80156106e85780601f106106bf576101008083540402835291602001916106e8565b820191905f5260205f20905b8154815290600101906020018083116106cb57829003601f168201915b505050505081565b6106f8610941565b600655565b610705610941565b600491909155600555565b610718610941565b600280546001600160a01b0319166001600160a01b0392909216919091179055565b610742610941565b600380546001600160a01b0319166001600160a01b0392909216919091179055565b60075481905f5b8281101561084b576001546001600160a01b0316634d578eaf86868481811061079657610796610d94565b90506020020135846040518363ffffffff1660e01b81526004016107c4929190918252602082015260400190565b5f604051808303815f87803b1580156107db575f80fd5b505af11580156107ed573d5f803e3d5ffd5b5050505084848281811061080357610803610d94565b905060200201357f1fcb7d0fda33670fdf4237d8d7a473a941ba0d52671063a86f901de935483e328360405161083b91815260200190565b60405180910390a260010161076b565b5050505050565b61085a610941565b63389a75e1600c52805f526020600c20805442111561088057636f5e88185f526004601cfd5b5f905561088c8161095b565b50565b610897610941565b8060601b6108ac57637448fbae5f526004601cfd5b61088c8161095b565b5f6040518251604081146108d157604181146108f2575061092d565b604084015160ff81901c601b016020526001600160ff1b0316606052610905565b60608401515f1a60205260408401516060525b50835f5260208301516040526020600160805f60015afa5191505f606052806040523d61093a575b638baa579f5f526004601cfd5b5092915050565b638b78c6d819543314610663576382b429005f526004601cfd5b638b78c6d81980546001600160a01b039092169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e05f80a355565b5f8083601f8401126109a8575f80fd5b5081356001600160401b038111156109be575f80fd5b6020830191508360208260051b85010111156109d8575f80fd5b9250929050565b634e487b7160e01b5f52604160045260245ffd5b5f82601f830112610a02575f80fd5b81356001600160401b03811115610a1b57610a1b6109df565b604051601f8201601f19908116603f011681016001600160401b0381118282101715610a4957610a496109df565b604052818152838201602001851015610a60575f80fd5b816020850160208301375f918101602001919091529392505050565b5f805f805f805f60a0888a031215610a92575f80fd5b87356001600160401b03811115610aa7575f80fd5b8801601f81018a13610ab7575f80fd5b80356001600160401b03811115610acc575f80fd5b8a6020828401011115610add575f80fd5b6020918201985096508801356001600160401b03811115610afc575f80fd5b610b088a828b01610998565b909650945050604088013592506060880135915060808801356001600160401b03811115610b34575f80fd5b610b408a828b016109f3565b91505092959891949750929550565b5f60208284031215610b5f575f80fd5b81356001600160a01b0381168114610b75575f80fd5b9392505050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b5f60208284031215610bc1575f80fd5b5035919050565b5f8060408385031215610bd9575f80fd5b50508035926020909101359150565b5f8060208385031215610bf9575f80fd5b82356001600160401b03811115610c0e575f80fd5b610c1a85828601610998565b90969095509350505050565b604080825281018390525f6001600160fb1b03841115610c44575f80fd5b8360051b808660608501376020830193909352500160600192915050565b634e487b7160e01b5f52601160045260245ffd5b80820180821115610c8957610c89610c62565b92915050565b60408152826040820152828460608301375f606084830101525f601f19601f85011682016060810160608483030160208501528085518083526080840191506020870193505f92505b80831015610cfb5783518252602082019150602084019350600183019250610cd8565b50979650505050505050565b5f60208284031215610d17575f80fd5b81518015158114610b75575f80fd5b8082028115828204841417610c8957610c89610c62565b5f82610d5757634e487b7160e01b5f52601260045260245ffd5b500490565b600181811c90821680610d7057607f821691505b602082108103610d8e57634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52603260045260245ffdfea2646970667358221220909ee3765dcf0e0d456dc9089eedccca6d3ed97e082e75d1aa7940bd2c95c5e064736f6c634300081a003300000000000000000000000000000000000000000000000000000000000000e00000000000000000000000001a601e2aadb0710c587b7c6b13a014290702250800000000000000000000000030fe0fd65e89fc2bfb8a4b4a06cfcba0070ff0b7000000000000000000000000e47f07cc96b269c68e4a2a5b9b3bd0e02c6ae698000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000005af3107a4000000000000000000000000000000000000000000000000000000000000000627000000000000000000000000000000000000000000000000000000000000000094141564545544836680000000000000000000000000000000000000000000000
Deployed Bytecode
0x608060405260043610610131575f3560e01c80638da5cb5b116100a8578063b39db6861161006d578063b39db686146102ea578063ef2c21d914610309578063f04e283e1461031e578063f2fde38b14610331578063fbcbc5e614610344578063fee81cf414610363575f80fd5b80638da5cb5b1461026a57806397fc007c146102825780639b19f356146102a1578063a3b1bc24146102b6578063b20d550b146102d5575f80fd5b80636250bb55116100f95780636250bb55146101c5578063715018a6146101e45780637284e416146101ec5780637e390d591461020d57806384a101541461022c5780638771b6641461024b575f80fd5b806325692962146101355780632b7ac3f31461013f5780633534d6941461017b5780633ad5a7241461019a57806354d1f13d146101bd575b5f80fd5b61013d610394565b005b34801561014a575f80fd5b5060035461015e906001600160a01b031681565b6040516001600160a01b0390911681526020015b60405180910390f35b348015610186575f80fd5b5061013d610195366004610a7c565b6103e0565b3480156101a5575f80fd5b506101af60055481565b604051908152602001610172565b61013d6105ef565b3480156101d0575f80fd5b5061013d6101df366004610b4f565b610628565b61013d610652565b3480156101f7575f80fd5b50610200610665565b6040516101729190610b7c565b348015610218575f80fd5b5061013d610227366004610bb1565b6106f0565b348015610237575f80fd5b5061013d610246366004610bc8565b6106fd565b348015610256575f80fd5b5061013d610265366004610b4f565b610710565b348015610275575f80fd5b50638b78c6d8195461015e565b34801561028d575f80fd5b5061013d61029c366004610b4f565b61073a565b3480156102ac575f80fd5b506101af60045481565b3480156102c1575f80fd5b5060025461015e906001600160a01b031681565b3480156102e0575f80fd5b506101af60075481565b3480156102f5575f80fd5b5061013d610304366004610be8565b610764565b348015610314575f80fd5b506101af60065481565b61013d61032c366004610b4f565b610852565b61013d61033f366004610b4f565b61088f565b34801561034f575f80fd5b5060015461015e906001600160a01b031681565b34801561036e575f80fd5b506101af61037d366004610b4f565b63389a75e1600c9081525f91909152602090205490565b5f6202a3006001600160401b03164201905063389a75e1600c52335f52806020600c2055337fdbf36a107da19e49527a7176a1babf963b4b0ff8cde35ee35d6cd8f1f9ac7e1d5f80a250565b600654830142111561040557604051630819bdcd60e01b815260040160405180910390fd5b5f61043a86868660405160200161041e93929190610c26565b60405160208183030381529060405280519060200120836108b5565b6002549091506001600160a01b0380831691161461046b5760405163338a70bd60e11b815260040160405180910390fd5b845f610478826001610c76565b6001600160401b0381111561048f5761048f6109df565b6040519080825280602002602001820160405280156104b8578160200160208202803683370190505b50905060208101602083028982376020830201859052600354604051631e8e1e1360e01b81526001600160a01b0390911690631e8e1e1390610502908d908d908690600401610c8f565b6020604051808303815f875af115801561051e573d5f803e3d5ffd5b505050506040513d601f19601f820116820180604052508101906105429190610d07565b61055f5760405163439cc0cd60e01b815260040160405180910390fd5b6509184e72a000600454600554876105779190610d26565b6105819190610d3d565b6105919065048c27395000610c76565b61059b9190610d3d565b6105ab906509184e72a000610d26565b60078190556040519081527f8c4d35e54a3f2ef1134138fd8ea3daee6a3c89e10d2665996babdf70261e2c769060200160405180910390a150505050505050505050565b63389a75e1600c52335f525f6020600c2055337ffa7b8eab7da67f412cc9575ed43464468f9bfbae89d1675917346ca6d8fe3c925f80a2565b610630610941565b600180546001600160a01b0319166001600160a01b0392909216919091179055565b61065a610941565b6106635f61095b565b565b5f805461067190610d5c565b80601f016020809104026020016040519081016040528092919081815260200182805461069d90610d5c565b80156106e85780601f106106bf576101008083540402835291602001916106e8565b820191905f5260205f20905b8154815290600101906020018083116106cb57829003601f168201915b505050505081565b6106f8610941565b600655565b610705610941565b600491909155600555565b610718610941565b600280546001600160a01b0319166001600160a01b0392909216919091179055565b610742610941565b600380546001600160a01b0319166001600160a01b0392909216919091179055565b60075481905f5b8281101561084b576001546001600160a01b0316634d578eaf86868481811061079657610796610d94565b90506020020135846040518363ffffffff1660e01b81526004016107c4929190918252602082015260400190565b5f604051808303815f87803b1580156107db575f80fd5b505af11580156107ed573d5f803e3d5ffd5b5050505084848281811061080357610803610d94565b905060200201357f1fcb7d0fda33670fdf4237d8d7a473a941ba0d52671063a86f901de935483e328360405161083b91815260200190565b60405180910390a260010161076b565b5050505050565b61085a610941565b63389a75e1600c52805f526020600c20805442111561088057636f5e88185f526004601cfd5b5f905561088c8161095b565b50565b610897610941565b8060601b6108ac57637448fbae5f526004601cfd5b61088c8161095b565b5f6040518251604081146108d157604181146108f2575061092d565b604084015160ff81901c601b016020526001600160ff1b0316606052610905565b60608401515f1a60205260408401516060525b50835f5260208301516040526020600160805f60015afa5191505f606052806040523d61093a575b638baa579f5f526004601cfd5b5092915050565b638b78c6d819543314610663576382b429005f526004601cfd5b638b78c6d81980546001600160a01b039092169182907f8be0079c531659141344cd1fd0a4f28419497f9722a3daafe3b4186f6b6457e05f80a355565b5f8083601f8401126109a8575f80fd5b5081356001600160401b038111156109be575f80fd5b6020830191508360208260051b85010111156109d8575f80fd5b9250929050565b634e487b7160e01b5f52604160045260245ffd5b5f82601f830112610a02575f80fd5b81356001600160401b03811115610a1b57610a1b6109df565b604051601f8201601f19908116603f011681016001600160401b0381118282101715610a4957610a496109df565b604052818152838201602001851015610a60575f80fd5b816020850160208301375f918101602001919091529392505050565b5f805f805f805f60a0888a031215610a92575f80fd5b87356001600160401b03811115610aa7575f80fd5b8801601f81018a13610ab7575f80fd5b80356001600160401b03811115610acc575f80fd5b8a6020828401011115610add575f80fd5b6020918201985096508801356001600160401b03811115610afc575f80fd5b610b088a828b01610998565b909650945050604088013592506060880135915060808801356001600160401b03811115610b34575f80fd5b610b408a828b016109f3565b91505092959891949750929550565b5f60208284031215610b5f575f80fd5b81356001600160a01b0381168114610b75575f80fd5b9392505050565b602081525f82518060208401528060208501604085015e5f604082850101526040601f19601f83011684010191505092915050565b5f60208284031215610bc1575f80fd5b5035919050565b5f8060408385031215610bd9575f80fd5b50508035926020909101359150565b5f8060208385031215610bf9575f80fd5b82356001600160401b03811115610c0e575f80fd5b610c1a85828601610998565b90969095509350505050565b604080825281018390525f6001600160fb1b03841115610c44575f80fd5b8360051b808660608501376020830193909352500160600192915050565b634e487b7160e01b5f52601160045260245ffd5b80820180821115610c8957610c89610c62565b92915050565b60408152826040820152828460608301375f606084830101525f601f19601f85011682016060810160608483030160208501528085518083526080840191506020870193505f92505b80831015610cfb5783518252602082019150602084019350600183019250610cd8565b50979650505050505050565b5f60208284031215610d17575f80fd5b81518015158114610b75575f80fd5b8082028115828204841417610c8957610c89610c62565b5f82610d5757634e487b7160e01b5f52601260045260245ffd5b500490565b600181811c90821680610d7057607f821691505b602082108103610d8e57634e487b7160e01b5f52602260045260245ffd5b50919050565b634e487b7160e01b5f52603260045260245ffdfea2646970667358221220909ee3765dcf0e0d456dc9089eedccca6d3ed97e082e75d1aa7940bd2c95c5e064736f6c634300081a0033
Constructor Arguments (ABI-Encoded and is the last bytes of the Contract Creation Code above)
00000000000000000000000000000000000000000000000000000000000000e00000000000000000000000001a601e2aadb0710c587b7c6b13a014290702250800000000000000000000000030fe0fd65e89fc2bfb8a4b4a06cfcba0070ff0b7000000000000000000000000e47f07cc96b269c68e4a2a5b9b3bd0e02c6ae698000000000000000000000000000000000000000000000000000000000010000000000000000000000000000000000000000000000000000000005af3107a4000000000000000000000000000000000000000000000000000000000000000627000000000000000000000000000000000000000000000000000000000000000094141564545544836680000000000000000000000000000000000000000000000
-----Decoded View---------------
Arg [0] : _description (string): AAVEETH6h
Arg [1] : _swapFeeHelper (address): 0x1a601E2AadB0710c587b7c6B13A0142907022508
Arg [2] : _litPublicKey (address): 0x30fe0Fd65E89fc2bFB8A4b4a06cfcBa0070ff0b7
Arg [3] : _verifier (address): 0xe47F07cc96B269C68e4A2a5b9b3bd0E02c6aE698
Arg [4] : _scalingFactorDiv (uint256): 1048576
Arg [5] : _scalingFactorMul (uint256): 100000000000000
Arg [6] : _signatureExpiryThreshold (uint256): 25200
-----Encoded View---------------
9 Constructor Arguments found :
Arg [0] : 00000000000000000000000000000000000000000000000000000000000000e0
Arg [1] : 0000000000000000000000001a601e2aadb0710c587b7c6b13a0142907022508
Arg [2] : 00000000000000000000000030fe0fd65e89fc2bfb8a4b4a06cfcba0070ff0b7
Arg [3] : 000000000000000000000000e47f07cc96b269c68e4a2a5b9b3bd0e02c6ae698
Arg [4] : 0000000000000000000000000000000000000000000000000000000000100000
Arg [5] : 00000000000000000000000000000000000000000000000000005af3107a4000
Arg [6] : 0000000000000000000000000000000000000000000000000000000000006270
Arg [7] : 0000000000000000000000000000000000000000000000000000000000000009
Arg [8] : 4141564545544836680000000000000000000000000000000000000000000000
Loading...
Loading
Loading...
Loading
Net Worth in USD
$0.00
Net Worth in ETH
0
Multichain Portfolio | 33 Chains
| Chain | Token | Portfolio % | Price | Amount | Value |
|---|
Loading...
Loading
Loading...
Loading
Loading...
Loading
[ Download: CSV Export ]
A contract address hosts a smart contract, which is a set of code stored on the blockchain that runs when predetermined conditions are met. Learn more about addresses in our Knowledge Base.