Description:
Multi-signature wallet contract requiring multiple confirmations for transaction execution.
Blockchain: Ethereum
Source Code: View Code On The Blockchain
Solidity Source Code:
{{
"language": "Solidity",
"sources": {
"@openzeppelin/contracts/access/Ownable.sol": {
"content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.0) (access/Ownable.sol)
pragma solidity ^0.8.20;
import {Context} from "../utils/Context.sol";
/**
* @dev Contract module which provides a basic access control mechanism, where
* there is an account (an owner) that can be granted exclusive access to
* specific functions.
*
* The initial owner is set to the address provided by the deployer. This can
* later be changed with {transferOwnership}.
*
* This module is used through inheritance. It will make available the modifier
* `onlyOwner`, which can be applied to your functions to restrict their use to
* the owner.
*/
abstract contract Ownable is Context {
address private _owner;
/**
* @dev The caller account is not authorized to perform an operation.
*/
error OwnableUnauthorizedAccount(address account);
/**
* @dev The owner is not a valid owner account. (eg. `address(0)`)
*/
error OwnableInvalidOwner(address owner);
event OwnershipTransferred(address indexed previousOwner, address indexed newOwner);
/**
* @dev Initializes the contract setting the address provided by the deployer as the initial owner.
*/
constructor(address initialOwner) {
if (initialOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(initialOwner);
}
/**
* @dev Throws if called by any account other than the owner.
*/
modifier onlyOwner() {
_checkOwner();
_;
}
/**
* @dev Returns the address of the current owner.
*/
function owner() public view virtual returns (address) {
return _owner;
}
/**
* @dev Throws if the sender is not the owner.
*/
function _checkOwner() internal view virtual {
if (owner() != _msgSender()) {
revert OwnableUnauthorizedAccount(_msgSender());
}
}
/**
* @dev Leaves the contract without owner. It will not be possible to call
* `onlyOwner` functions. Can only be called by the current owner.
*
* NOTE: Renouncing ownership will leave the contract without an owner,
* thereby disabling any functionality that is only available to the owner.
*/
function renounceOwnership() public virtual onlyOwner {
_transferOwnership(address(0));
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Can only be called by the current owner.
*/
function transferOwnership(address newOwner) public virtual onlyOwner {
if (newOwner == address(0)) {
revert OwnableInvalidOwner(address(0));
}
_transferOwnership(newOwner);
}
/**
* @dev Transfers ownership of the contract to a new account (`newOwner`).
* Internal function without access restriction.
*/
function _transferOwnership(address newOwner) internal virtual {
address oldOwner = _owner;
_owner = newOwner;
emit OwnershipTransferred(oldOwner, newOwner);
}
}
"
},
"@openzeppelin/contracts/utils/Context.sol": {
"content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.0.1) (utils/Context.sol)
pragma solidity ^0.8.20;
/**
* @dev Provides information about the current execution context, including the
* sender of the transaction and its data. While these are generally available
* via msg.sender and msg.data, they should not be accessed in such a direct
* manner, since when dealing with meta-transactions the account sending and
* paying for execution may not be the actual sender (as far as an application
* is concerned).
*
* This contract is only required for intermediate, library-like contracts.
*/
abstract contract Context {
function _msgSender() internal view virtual returns (address) {
return msg.sender;
}
function _msgData() internal view virtual returns (bytes calldata) {
return msg.data;
}
function _contextSuffixLength() internal view virtual returns (uint256) {
return 0;
}
}
"
},
"@openzeppelin/contracts/utils/ReentrancyGuard.sol": {
"content": "// SPDX-License-Identifier: MIT
// OpenZeppelin Contracts (last updated v5.1.0) (utils/ReentrancyGuard.sol)
pragma solidity ^0.8.20;
/**
* @dev Contract module that helps prevent reentrant calls to a function.
*
* Inheriting from `ReentrancyGuard` will make the {nonReentrant} modifier
* available, which can be applied to functions to make sure there are no nested
* (reentrant) calls to them.
*
* Note that because there is a single `nonReentrant` guard, functions marked as
* `nonReentrant` may not call one another. This can be worked around by making
* those functions `private`, and then adding `external` `nonReentrant` entry
* points to them.
*
* TIP: If EIP-1153 (transient storage) is available on the chain you're deploying at,
* consider using {ReentrancyGuardTransient} instead.
*
* TIP: If you would like to learn more about reentrancy and alternative ways
* to protect against it, check out our blog post
* https://blog.openzeppelin.com/reentrancy-after-istanbul/[Reentrancy After Istanbul].
*/
abstract contract ReentrancyGuard {
// Booleans are more expensive than uint256 or any type that takes up a full
// word because each write operation emits an extra SLOAD to first read the
// slot's contents, replace the bits taken up by the boolean, and then write
// back. This is the compiler's defense against contract upgrades and
// pointer aliasing, and it cannot be disabled.
// The values being non-zero value makes deployment a bit more expensive,
// but in exchange the refund on every call to nonReentrant will be lower in
// amount. Since refunds are capped to a percentage of the total
// transaction's gas, it is best to keep them low in cases like this one, to
// increase the likelihood of the full refund coming into effect.
uint256 private constant NOT_ENTERED = 1;
uint256 private constant ENTERED = 2;
uint256 private _status;
/**
* @dev Unauthorized reentrant call.
*/
error ReentrancyGuardReentrantCall();
constructor() {
_status = NOT_ENTERED;
}
/**
* @dev Prevents a contract from calling itself, directly or indirectly.
* Calling a `nonReentrant` function from another `nonReentrant`
* function is not supported. It is possible to prevent this from happening
* by making the `nonReentrant` function external, and making it call a
* `private` function that does the actual work.
*/
modifier nonReentrant() {
_nonReentrantBefore();
_;
_nonReentrantAfter();
}
function _nonReentrantBefore() private {
// On the first call to nonReentrant, _status will be NOT_ENTERED
if (_status == ENTERED) {
revert ReentrancyGuardReentrantCall();
}
// Any calls to nonReentrant after this point will fail
_status = ENTERED;
}
function _nonReentrantAfter() private {
// By storing the original value once again, a refund is triggered (see
// https://eips.ethereum.org/EIPS/eip-2200)
_status = NOT_ENTERED;
}
/**
* @dev Returns true if the reentrancy guard is currently set to "entered", which indicates there is a
* `nonReentrant` function in the call stack.
*/
function _reentrancyGuardEntered() internal view returns (bool) {
return _status == ENTERED;
}
}
"
},
"contracts/adapters/UniswapV4Adapter.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
import {IUniswapV4PoolManager, IUniswapV4PositionManager, IUniswapV4Router, PoolKey, ModifyPositionParams, SwapParams, MintParams, IncreaseLiquidityParams, DecreaseLiquidityParams, CollectParams, ExactInputSingleParams, Currency, BalanceDelta} from "../interfaces/IUniswapV4.sol";
import {Ownable} from "@openzeppelin/contracts/access/Ownable.sol";
import {ReentrancyGuard} from "@openzeppelin/contracts/utils/ReentrancyGuard.sol";
/**
* @title UniswapV4Adapter
* @dev Adapter for Uniswap V4 integration with PonStrategy
*/
contract UniswapV4Adapter is Ownable, ReentrancyGuard {
IUniswapV4PoolManager public immutable poolManager;
IUniswapV4PositionManager public immutable positionManager;
IUniswapV4Router public immutable router;
// Pool configuration
address public token0; // PONSTR
address public token1; // WETH
uint24 public fee = 3000; // 0.3%
int24 public tickSpacing = 60;
// Events
event PositionCreated(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);
event PositionIncreased(uint256 indexed tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);
event PositionDecreased(uint256 indexed tokenId, uint256 amount0, uint256 amount1);
event TokensSwapped(address tokenIn, address tokenOut, uint256 amountIn, uint256 amountOut);
constructor(
address poolManager_,
address positionManager_,
address router_,
address owner_
) Ownable(owner_) {
poolManager = IUniswapV4PoolManager(poolManager_);
positionManager = IUniswapV4PositionManager(positionManager_);
router = IUniswapV4Router(router_);
}
/**
* @dev Set token addresses for the pool
*/
function setTokens(address token0_, address token1_) external onlyOwner {
token0 = token0_;
token1 = token1_;
}
/**
* @dev Create a new position in Uniswap V4
*/
function createPosition(
int24 tickLower,
int24 tickUpper,
uint256 amount0Desired,
uint256 amount1Desired,
uint256 amount0Min,
uint256 amount1Min,
uint256 deadline
) external payable onlyOwner nonReentrant returns (uint256 tokenId, uint128 liquidity, uint256 amount0, uint256 amount1) {
require(token0 != address(0) && token1 != address(0), "Tokens not set");
MintParams memory params = MintParams({
token0: token0,
token1: token1,
fee: fee,
tickLower: tickLower,
tickUpper: tickUpper,
amount0Desired: amount0Desired,
amount1Desired: amount1Desired,
amount0Min: amount0Min,
amount1Min: amount1Min,
recipient: address(this),
deadline: deadline
});
(tokenId, liquidity, amount0, amount1) = positionManager.mint{value: msg.value}(params);
emit PositionCreated(tokenId, liquidity, amount0, amount1);
}
/**
* @dev Increase liquidity in existing position
*/
function increaseLiquidity(
uint256 tokenId,
uint256 amount0Desired,
uint256 amount1Desired,
uint256 amount0Min,
uint256 amount1Min,
uint256 deadline
) external payable onlyOwner nonReentrant returns (uint128 liquidity, uint256 amount0, uint256 amount1) {
IncreaseLiquidityParams memory params = IncreaseLiquidityParams({
tokenId: tokenId,
amount0Desired: amount0Desired,
amount1Desired: amount1Desired,
amount0Min: amount0Min,
amount1Min: amount1Min,
deadline: deadline
});
(liquidity, amount0, amount1) = positionManager.increaseLiquidity{value: msg.value}(params);
emit PositionIncreased(tokenId, liquidity, amount0, amount1);
}
/**
* @dev Decrease liquidity in existing position
*/
function decreaseLiquidity(
uint256 tokenId,
uint128 liquidity,
uint256 amount0Min,
uint256 amount1Min,
uint256 deadline
) external payable onlyOwner nonReentrant returns (uint256 amount0, uint256 amount1) {
DecreaseLiquidityParams memory params = DecreaseLiquidityParams({
tokenId: tokenId,
liquidity: liquidity,
amount0Min: amount0Min,
amount1Min: amount1Min,
deadline: deadline
});
(amount0, amount1) = positionManager.decreaseLiquidity{value: msg.value}(params);
emit PositionDecreased(tokenId, amount0, amount1);
}
/**
* @dev Swap tokens using Uniswap V4
*/
function swapExactTokensForETH(
uint256 amountIn,
uint256 amountOutMinimum,
uint160 sqrtPriceLimitX96,
uint256 deadline
) external payable onlyOwner nonReentrant returns (uint256 amountOut) {
require(token0 != address(0) && token1 != address(0), "Tokens not set");
ExactInputSingleParams memory params = ExactInputSingleParams({
tokenIn: token0,
tokenOut: token1,
fee: fee,
recipient: address(this),
deadline: deadline,
amountIn: amountIn,
amountOutMinimum: amountOutMinimum,
sqrtPriceLimitX96: sqrtPriceLimitX96
});
amountOut = router.exactInputSingle{value: msg.value}(params);
emit TokensSwapped(token0, token1, amountIn, amountOut);
}
/**
* @dev Swap ETH for tokens using Uniswap V4
*/
function swapExactETHForTokens(
uint256 amountOutMinimum,
uint160 sqrtPriceLimitX96,
uint256 deadline
) external payable onlyOwner nonReentrant returns (uint256 amountOut) {
require(token0 != address(0) && token1 != address(0), "Tokens not set");
ExactInputSingleParams memory params = ExactInputSingleParams({
tokenIn: token1, // WETH
tokenOut: token0, // PONSTR
fee: fee,
recipient: address(this),
deadline: deadline,
amountIn: msg.value,
amountOutMinimum: amountOutMinimum,
sqrtPriceLimitX96: sqrtPriceLimitX96
});
amountOut = router.exactInputSingle{value: msg.value}(params);
emit TokensSwapped(token1, token0, msg.value, amountOut);
}
/**
* @dev Collect fees from position
*/
function collectFees(
uint256 tokenId,
address recipient,
uint128 amount0Max,
uint128 amount1Max
) external payable onlyOwner nonReentrant returns (uint256 amount0, uint256 amount1) {
CollectParams memory params = CollectParams({
tokenId: tokenId,
recipient: recipient,
amount0Max: amount0Max,
amount1Max: amount1Max
});
(amount0, amount1) = positionManager.collect{value: msg.value}(params);
}
/**
* @dev Burn position NFT
*/
function burnPosition(uint256 tokenId) external payable onlyOwner nonReentrant {
positionManager.burn{value: msg.value}(tokenId);
}
/**
* @dev Get position info
*/
function getPosition(uint256 tokenId) external view returns (
uint96 nonce,
address operator,
address token0Addr,
address token1Addr,
uint24 feeTier,
int24 tickLower,
int24 tickUpper,
uint128 liquidity,
uint256 feeGrowthInside0LastX128,
uint256 feeGrowthInside1LastX128,
uint128 tokensOwed0,
uint128 tokensOwed1
) {
return positionManager.positions(tokenId);
}
/**
* @dev Emergency withdraw ETH
*/
function emergencyWithdrawETH(address payable to, uint256 amount) external onlyOwner {
(bool success,) = to.call{value: amount}("");
require(success, "ETH transfer failed");
}
/**
* @dev Emergency withdraw tokens
*/
function emergencyWithdrawToken(address token, address to, uint256 amount) external onlyOwner {
(bool success,) = token.call(abi.encodeWithSignature("transfer(address,uint256)", to, amount));
require(success, "Token transfer failed");
}
receive() external payable {}
}
"
},
"contracts/interfaces/IUniswapV4.sol": {
"content": "// SPDX-License-Identifier: MIT
pragma solidity ^0.8.19;
interface IUniswapV4PoolManager {
function initialize(PoolKey memory key, uint160 sqrtPriceX96) external returns (int24 tick);
function getSlot0(bytes32 id) external view returns (uint160 sqrtPriceX96, int24 tick, uint24 protocolFee, uint24 lpFee);
function getLiquidity(bytes32 id) external view returns (uint128 liquidity);
function getPosition(bytes32 id, address owner, int24 tickLower, int24 tickUpper) external view returns (uint128 liquidity, uint256 feeGrowthInside0LastX128, uint256 feeGrowthInside1LastX128, uint128 tokensOwed0, uint128 tokensOwed1);
function modifyPosition(ModifyPositionParams memory params) external returns (BalanceDelta delta);
function swap(SwapParams memory params) external returns (BalanceDelta delta);
function donate(DonateParams memory params) external returns (BalanceDelta delta);
function take(Currency currency, address to, uint256 amount) external;
function settle(Currency currency) external payable returns (uint256 paid);
function mint(address to, uint256 amount) external;
function burn(address from, uint256 amount) external;
function collect(Currency currency, address to, uint256 amount) external;
function sweep(Currency currency, address to, uint256 amount) external;
function hook(Currency currency, address to, uint256 amount) external;
}
interface IUniswapV4PositionManager {
function mint(MintParams memory params) external payable returns (uint256 tokenId, uint128 liquidity, uint256 amount0, uint256 amount1);
function increaseLiquidity(IncreaseLiquidityParams memory params) external payable returns (uint128 liquidity, uint256 amount0, uint256 amount1);
function decreaseLiquidity(DecreaseLiquidityParams memory params) external payable returns (uint256 amount0, uint256 amount1);
function collect(CollectParams memory params) external payable returns (uint256 amount0, uint256 amount1);
function burn(uint256 tokenId) external payable;
function positions(uint256 tokenId) external view returns (uint96 nonce, address operator, address token0, address token1, uint24 fee, int24 tickLower, int24 tickUpper, uint128 liquidity, uint256 feeGrowthInside0LastX128, uint256 feeGrowthInside1LastX128, uint128 tokensOwed0, uint128 tokensOwed1);
}
interface IUniswapV4Router {
function exactInputSingle(ExactInputSingleParams memory params) external payable returns (uint256 amountOut);
function exactInput(ExactInputParams memory params) external payable returns (uint256 amountOut);
function exactOutputSingle(ExactOutputSingleParams memory params) external payable returns (uint256 amountIn);
function exactOutput(ExactOutputParams memory params) external payable returns (uint256 amountIn);
function multicall(bytes[] calldata data) external payable returns (bytes[] memory results);
}
// Data structures
struct PoolKey {
Currency currency0;
Currency currency1;
uint24 fee;
int24 tickSpacing;
IHooks hooks;
}
struct ModifyPositionParams {
PoolKey key;
int24 tickLower;
int24 tickUpper;
int256 liquidityDelta;
}
struct SwapParams {
PoolKey key;
bool zeroForOne;
int256 amountSpecified;
uint160 sqrtPriceLimitX96;
}
struct DonateParams {
PoolKey key;
uint256 amount0;
uint256 amount1;
}
struct MintParams {
address token0;
address token1;
uint24 fee;
int24 tickLower;
int24 tickUpper;
uint256 amount0Desired;
uint256 amount1Desired;
uint256 amount0Min;
uint256 amount1Min;
address recipient;
uint256 deadline;
}
struct IncreaseLiquidityParams {
uint256 tokenId;
uint256 amount0Desired;
uint256 amount1Desired;
uint256 amount0Min;
uint256 amount1Min;
uint256 deadline;
}
struct DecreaseLiquidityParams {
uint256 tokenId;
uint128 liquidity;
uint256 amount0Min;
uint256 amount1Min;
uint256 deadline;
}
struct CollectParams {
uint256 tokenId;
address recipient;
uint128 amount0Max;
uint128 amount1Max;
}
struct ExactInputSingleParams {
address tokenIn;
address tokenOut;
uint24 fee;
address recipient;
uint256 deadline;
uint256 amountIn;
uint256 amountOutMinimum;
uint160 sqrtPriceLimitX96;
}
struct ExactInputParams {
bytes path;
address recipient;
uint256 deadline;
uint256 amountIn;
uint256 amountOutMinimum;
}
struct ExactOutputSingleParams {
address tokenIn;
address tokenOut;
uint24 fee;
address recipient;
uint256 deadline;
uint256 amountOut;
uint256 amountInMaximum;
uint160 sqrtPriceLimitX96;
}
struct ExactOutputParams {
bytes path;
address recipient;
uint256 deadline;
uint256 amountOut;
uint256 amountInMaximum;
}
// Types
type Currency is address;
type BalanceDelta is int256;
interface IHooks {
function beforeInitialize(PoolKey memory key, uint160 sqrtPriceX96) external returns (bytes4);
function afterInitialize(PoolKey memory key, uint160 sqrtPriceX96, int24 tick) external returns (bytes4);
function beforeModifyPosition(PoolKey memory key, ModifyPositionParams memory params) external returns (bytes4);
function afterModifyPosition(PoolKey memory key, ModifyPositionParams memory params, BalanceDelta delta) external returns (bytes4);
function beforeSwap(PoolKey memory key, SwapParams memory params) external returns (bytes4);
function afterSwap(PoolKey memory key, SwapParams memory params, BalanceDelta delta) external returns (bytes4);
function beforeDonate(PoolKey memory key, DonateParams memory params) external returns (bytes4);
function afterDonate(PoolKey memory key, DonateParams memory params, BalanceDelta delta) external returns (bytes4);
}
"
}
},
"settings": {
"optimizer": {
"enabled": true,
"runs": 200
},
"viaIR": false,
"evmVersion": "paris",
"outputSelection": {
"*": {
"*": [
"evm.bytecode",
"evm.deployedBytecode",
"devdoc",
"userdoc",
"metadata",
"abi"
]
}
}
}
}}
Submitted on: 2025-09-17 12:31:56
Comments
Log in to comment.
No comments yet.