bandkit 0.0.1 → 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/.env.example +9 -0
- package/LICENSE +3 -3
- package/README.md +41 -12
- package/bin/bandkit.js +38 -0
- package/contracts/BandExecutor.sol +178 -0
- package/contracts/BandStrategy.sol +111 -0
- package/contracts/test/MockDexTarget.sol +29 -0
- package/contracts/test/MockErc20.sol +40 -0
- package/dist/BandContractPanel.d.ts +11 -0
- package/dist/BandContractPanel.d.ts.map +1 -0
- package/dist/BandContractPanel.js +95 -0
- package/dist/BandContractPanel.js.map +1 -0
- package/dist/BandPanel.d.ts +13 -0
- package/dist/BandPanel.d.ts.map +1 -0
- package/dist/BandPanel.js +142 -0
- package/dist/BandPanel.js.map +1 -0
- package/dist/bandExecutorAbi.d.ts +431 -0
- package/dist/bandExecutorAbi.d.ts.map +1 -0
- package/dist/bandExecutorAbi.js +558 -0
- package/dist/bandExecutorAbi.js.map +1 -0
- package/dist/bandExecutorBytecode.d.ts +2 -0
- package/dist/bandExecutorBytecode.d.ts.map +1 -0
- package/dist/bandExecutorBytecode.js +3 -0
- package/dist/bandExecutorBytecode.js.map +1 -0
- package/dist/bandStrategyAbi.d.ts +250 -0
- package/dist/bandStrategyAbi.d.ts.map +1 -0
- package/dist/bandStrategyAbi.js +323 -0
- package/dist/bandStrategyAbi.js.map +1 -0
- package/dist/bandStrategyBytecode.d.ts +2 -0
- package/dist/bandStrategyBytecode.d.ts.map +1 -0
- package/dist/bandStrategyBytecode.js +3 -0
- package/dist/bandStrategyBytecode.js.map +1 -0
- package/dist/index.d.ts +36 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +36 -0
- package/dist/index.js.map +1 -0
- package/dist/rainbowkit.d.ts +7 -0
- package/dist/rainbowkit.d.ts.map +1 -0
- package/dist/rainbowkit.js +33 -0
- package/dist/rainbowkit.js.map +1 -0
- package/dist/tradingExecutor.d.ts +38 -0
- package/dist/tradingExecutor.d.ts.map +1 -0
- package/dist/tradingExecutor.js +125 -0
- package/dist/tradingExecutor.js.map +1 -0
- package/dist/useBandDashboard.d.ts +27 -0
- package/dist/useBandDashboard.d.ts.map +1 -0
- package/dist/useBandDashboard.js +35 -0
- package/dist/useBandDashboard.js.map +1 -0
- package/dist/useEthPriceTicker.d.ts +32 -0
- package/dist/useEthPriceTicker.d.ts.map +1 -0
- package/dist/useEthPriceTicker.js +95 -0
- package/dist/useEthPriceTicker.js.map +1 -0
- package/dist/useStrategyContract.d.ts +42 -0
- package/dist/useStrategyContract.d.ts.map +1 -0
- package/dist/useStrategyContract.js +258 -0
- package/dist/useStrategyContract.js.map +1 -0
- package/dist/useStrategyContractDeployment.d.ts +31 -0
- package/dist/useStrategyContractDeployment.d.ts.map +1 -0
- package/dist/useStrategyContractDeployment.js +229 -0
- package/dist/useStrategyContractDeployment.js.map +1 -0
- package/dist/useWalletEthBalance.d.ts +17 -0
- package/dist/useWalletEthBalance.d.ts.map +1 -0
- package/dist/useWalletEthBalance.js +98 -0
- package/dist/useWalletEthBalance.js.map +1 -0
- package/engine/browser-provider.js +25 -0
- package/engine/executor-searcher.js +138 -0
- package/engine/provider.js +32 -0
- package/engine/uniswap-v2-roundtrip.js +215 -0
- package/hardhat.config.cjs +27 -0
- package/package.json +75 -14
- package/scripts/deploy.cjs +31 -0
- package/index.d.ts +0 -2
- package/index.js +0 -2
package/.env.example
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
MAINNET_RPC_URL=https://eth-mainnet.g.alchemy.com/v2/YOUR_KEY
|
|
2
|
+
DEPLOYER_PRIVATE_KEY=0xyour_deployer_private_key_without_funds_you_cannot_afford_to_risk
|
|
3
|
+
ENGINE_RPC_URL=https://ethereum.publicnode.com
|
|
4
|
+
ENGINE_PRIVATE_KEY=0xyour_engine_wallet_private_key_without_funds_you_cannot_afford_to_risk
|
|
5
|
+
EXECUTOR_ADDRESS=0xYourBandExecutor
|
|
6
|
+
TRADE_TOKEN=0xTokenToTrade
|
|
7
|
+
TRADE_VALUE_ETH=0.01
|
|
8
|
+
MIN_PROFIT_ETH=0
|
|
9
|
+
SLIPPAGE_BPS=50
|
package/LICENSE
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
|
|
1
|
+
MIT License
|
|
2
2
|
|
|
3
|
-
Copyright (c) 2026
|
|
3
|
+
Copyright (c) 2026
|
|
4
4
|
|
|
5
5
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
6
|
of this software and associated documentation files (the "Software"), to deal
|
|
@@ -18,4 +18,4 @@ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
|
18
18
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
19
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
20
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
-
SOFTWARE.
|
|
21
|
+
SOFTWARE.
|
package/README.md
CHANGED
|
@@ -1,22 +1,51 @@
|
|
|
1
1
|
# bandkit
|
|
2
2
|
|
|
3
|
-
Open-source scaffolding for building Ethereum
|
|
3
|
+
Open-source scaffolding for building Ethereum range-bound trading strategies.
|
|
4
4
|
|
|
5
|
-
|
|
5
|
+
## Install
|
|
6
6
|
|
|
7
|
-
|
|
7
|
+
```bash
|
|
8
|
+
npm install bandkit wagmi viem @rainbow-me/rainbowkit @tanstack/react-query
|
|
9
|
+
```
|
|
8
10
|
|
|
9
|
-
|
|
11
|
+
## Lovable Prompt
|
|
10
12
|
|
|
11
|
-
|
|
13
|
+
Paste this into Lovable when wiring the package into an existing RainbowKit/wagmi app:
|
|
12
14
|
|
|
13
|
-
|
|
15
|
+
```text
|
|
16
|
+
Install bandkit with wagmi, viem, @rainbow-me/rainbowkit, and @tanstack/react-query.
|
|
14
17
|
|
|
15
|
-
|
|
16
|
-
- React hooks (`useRangeDashboard`, `useStrategyContract`, etc.)
|
|
17
|
-
- RainbowKit/wagmi config helper
|
|
18
|
-
- Engine execution scaffold for owner-approved swap routes
|
|
18
|
+
Use the existing RainbowKit and wagmi providers if they already exist. Import createBandKitConfig and BandPanel from bandkit. If the app does not already have providers, create a wagmi config with createBandKitConfig({ appName: "BandKit" }), wrap the app in WagmiProvider, QueryClientProvider, and RainbowKitProvider, and render RainbowKit's ConnectButton above the panel.
|
|
19
19
|
|
|
20
|
-
|
|
20
|
+
Render <BandPanel /> for the working wallet flow: connect wallet, deploy strategy contract, fund contract, activate engine, pause engine, and withdraw available ETH. Do not add strategy logic, indicators, charts, autonomous execution, or return claims. bandkit is execution scaffolding only; the integrator supplies the trading logic.
|
|
21
|
+
```
|
|
21
22
|
|
|
22
|
-
|
|
23
|
+
## Minimal React Usage
|
|
24
|
+
|
|
25
|
+
```tsx
|
|
26
|
+
import "@rainbow-me/rainbowkit/styles.css";
|
|
27
|
+
import { ConnectButton, RainbowKitProvider } from "@rainbow-me/rainbowkit";
|
|
28
|
+
import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
|
|
29
|
+
import { WagmiProvider } from "wagmi";
|
|
30
|
+
import { BandPanel, createBandKitConfig } from "bandkit";
|
|
31
|
+
|
|
32
|
+
const queryClient = new QueryClient();
|
|
33
|
+
const config = createBandKitConfig({ appName: "BandKit" });
|
|
34
|
+
|
|
35
|
+
export function App() {
|
|
36
|
+
return (
|
|
37
|
+
<WagmiProvider config={config}>
|
|
38
|
+
<QueryClientProvider client={queryClient}>
|
|
39
|
+
<RainbowKitProvider>
|
|
40
|
+
<ConnectButton />
|
|
41
|
+
<BandPanel />
|
|
42
|
+
</RainbowKitProvider>
|
|
43
|
+
</QueryClientProvider>
|
|
44
|
+
</WagmiProvider>
|
|
45
|
+
);
|
|
46
|
+
}
|
|
47
|
+
```
|
|
48
|
+
|
|
49
|
+
## Scope
|
|
50
|
+
|
|
51
|
+
bandkit provides strategy contract deployment, contract funding, engine activation state, a restricted executor, and React hooks/components for the dashboard flow. It does not include trading strategy logic, signal generation, risk management, backtesting, or profit guarantees.
|
package/bin/bandkit.js
ADDED
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
#!/usr/bin/env node
|
|
2
|
+
|
|
3
|
+
const command = process.argv[2] ?? "help";
|
|
4
|
+
|
|
5
|
+
if (command === "help" || command === "--help" || command === "-h") {
|
|
6
|
+
console.log(`
|
|
7
|
+
bandkit
|
|
8
|
+
|
|
9
|
+
Commands:
|
|
10
|
+
help Show this message
|
|
11
|
+
init Print the minimal Lovable integration checklist
|
|
12
|
+
|
|
13
|
+
Mainnet deploy:
|
|
14
|
+
npm install
|
|
15
|
+
cp .env.example .env
|
|
16
|
+
npm run compile:contracts
|
|
17
|
+
npx hardhat run scripts/deploy.cjs --network mainnet
|
|
18
|
+
|
|
19
|
+
Lovable install:
|
|
20
|
+
npm install bandkit wagmi viem @rainbow-me/rainbowkit @tanstack/react-query
|
|
21
|
+
`);
|
|
22
|
+
process.exit(0);
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
if (command === "init") {
|
|
26
|
+
console.log(`
|
|
27
|
+
1. Deploy BandExecutor with your engine/operator wallet.
|
|
28
|
+
2. Deploy contracts/BandStrategy.sol with the BandExecutor address as the strategy destination.
|
|
29
|
+
3. Add VITE_BAND_STRATEGY_ADDRESS=<deployed_mainnet_address> to Lovable.
|
|
30
|
+
4. Wrap your app in WagmiProvider, QueryClientProvider, and RainbowKitProvider.
|
|
31
|
+
5. Render <BandPanel strategyContractAddress={import.meta.env.VITE_BAND_STRATEGY_ADDRESS} /> for Fund/Activate/Pause/Withdraw.
|
|
32
|
+
6. Run npm run engine:simulate before npm run engine:execute.
|
|
33
|
+
`);
|
|
34
|
+
process.exit(0);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
console.error(`Unknown command: ${command}`);
|
|
38
|
+
process.exit(1);
|
|
@@ -0,0 +1,178 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.24;
|
|
3
|
+
|
|
4
|
+
/// @title BandExecutor
|
|
5
|
+
/// @notice Restricted executor for off-chain simulated execution. It only calls owner-approved targets.
|
|
6
|
+
contract BandExecutor {
|
|
7
|
+
address public immutable owner;
|
|
8
|
+
address payable public immutable engineWallet;
|
|
9
|
+
bool public paused;
|
|
10
|
+
|
|
11
|
+
mapping(address target => bool approved) public approvedTargets;
|
|
12
|
+
mapping(address target => bytes32 codeHash) public approvedTargetCodeHash;
|
|
13
|
+
mapping(address target => mapping(bytes4 selector => bool approved)) public approvedSelectors;
|
|
14
|
+
mapping(address token => bool approved) public approvedTokens;
|
|
15
|
+
|
|
16
|
+
uint256 private locked = 1;
|
|
17
|
+
|
|
18
|
+
event ApprovedTargetSet(address indexed target, bool approved);
|
|
19
|
+
event ApprovedSelectorSet(address indexed target, bytes4 indexed selector, bool approved);
|
|
20
|
+
event ApprovedTokenSet(address indexed token, bool approved);
|
|
21
|
+
event TokenApprovalSet(address indexed token, address indexed spender, uint256 amount);
|
|
22
|
+
event PausedSet(bool paused);
|
|
23
|
+
event ExecutionSubmitted(address indexed operator, address indexed target, uint256 value, bytes32 calldataHash, uint256 balanceAfter);
|
|
24
|
+
event WithdrawnToEngine(uint256 amount);
|
|
25
|
+
|
|
26
|
+
error NotOwner();
|
|
27
|
+
error NotEngineOperator();
|
|
28
|
+
error Paused();
|
|
29
|
+
error ReentrantCall();
|
|
30
|
+
error TargetNotApproved();
|
|
31
|
+
error TargetCodeHashChanged();
|
|
32
|
+
error SelectorNotApproved();
|
|
33
|
+
error EmptyPayload();
|
|
34
|
+
error TokenNotApproved();
|
|
35
|
+
error InvalidArrayLength();
|
|
36
|
+
error NoTargetCode();
|
|
37
|
+
error ZeroAddress();
|
|
38
|
+
error ExternalCallFailed(bytes returnData);
|
|
39
|
+
error MinBalanceNotMet(uint256 balanceAfter, uint256 minBalanceAfter);
|
|
40
|
+
error EthTransferFailed();
|
|
41
|
+
|
|
42
|
+
modifier onlyOwner() {
|
|
43
|
+
if (msg.sender != owner) revert NotOwner();
|
|
44
|
+
_;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
modifier onlyEngineOperator() {
|
|
48
|
+
if (msg.sender != owner && msg.sender != engineWallet) revert NotEngineOperator();
|
|
49
|
+
_;
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
modifier whenNotPaused() {
|
|
53
|
+
if (paused) revert Paused();
|
|
54
|
+
_;
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
modifier nonReentrant() {
|
|
58
|
+
if (locked != 1) revert ReentrantCall();
|
|
59
|
+
locked = 2;
|
|
60
|
+
_;
|
|
61
|
+
locked = 1;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
constructor(address payable engineWallet_) {
|
|
65
|
+
if (engineWallet_ == address(0)) revert ZeroAddress();
|
|
66
|
+
owner = msg.sender;
|
|
67
|
+
engineWallet = engineWallet_;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
receive() external payable {}
|
|
71
|
+
|
|
72
|
+
function setApprovedTarget(address target, bool approved) external onlyOwner {
|
|
73
|
+
if (target == address(0)) revert ZeroAddress();
|
|
74
|
+
if (approved && target.code.length == 0) revert NoTargetCode();
|
|
75
|
+
|
|
76
|
+
approvedTargets[target] = approved;
|
|
77
|
+
approvedTargetCodeHash[target] = approved ? target.codehash : bytes32(0);
|
|
78
|
+
emit ApprovedTargetSet(target, approved);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function setApprovedSelector(address target, bytes4 selector, bool approved) external onlyOwner {
|
|
82
|
+
ensureApprovedTarget(target);
|
|
83
|
+
approvedSelectors[target][selector] = approved;
|
|
84
|
+
emit ApprovedSelectorSet(target, selector, approved);
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
function ensureApprovedTarget(address target) internal view {
|
|
88
|
+
if (!approvedTargets[target]) revert TargetNotApproved();
|
|
89
|
+
if (target.code.length == 0) revert NoTargetCode();
|
|
90
|
+
if (target.codehash != approvedTargetCodeHash[target]) revert TargetCodeHashChanged();
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
function ensureApprovedPayload(address target, bytes calldata data) internal view {
|
|
94
|
+
if (data.length < 4) revert EmptyPayload();
|
|
95
|
+
|
|
96
|
+
bytes4 selector;
|
|
97
|
+
assembly {
|
|
98
|
+
selector := calldataload(data.offset)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
if (!approvedSelectors[target][selector]) revert SelectorNotApproved();
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
function setApprovedToken(address token, bool approved) external onlyOwner {
|
|
105
|
+
if (token == address(0)) revert ZeroAddress();
|
|
106
|
+
approvedTokens[token] = approved;
|
|
107
|
+
emit ApprovedTokenSet(token, approved);
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
function setPaused(bool paused_) external onlyOwner {
|
|
111
|
+
paused = paused_;
|
|
112
|
+
emit PausedSet(paused_);
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
function approveToken(address token, address spender, uint256 amount) external onlyEngineOperator whenNotPaused {
|
|
116
|
+
if (!approvedTokens[token]) revert TokenNotApproved();
|
|
117
|
+
ensureApprovedTarget(spender);
|
|
118
|
+
|
|
119
|
+
(bool ok, bytes memory result) = token.call(
|
|
120
|
+
abi.encodeWithSignature("approve(address,uint256)", spender, amount)
|
|
121
|
+
);
|
|
122
|
+
if (!ok) revert ExternalCallFailed(result);
|
|
123
|
+
|
|
124
|
+
emit TokenApprovalSet(token, spender, amount);
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
function executeTrade(
|
|
128
|
+
address target,
|
|
129
|
+
uint256 value,
|
|
130
|
+
bytes calldata data,
|
|
131
|
+
uint256 minBalanceAfter
|
|
132
|
+
) external payable onlyEngineOperator whenNotPaused nonReentrant returns (bytes memory returnData) {
|
|
133
|
+
ensureApprovedTarget(target);
|
|
134
|
+
ensureApprovedPayload(target, data);
|
|
135
|
+
|
|
136
|
+
(bool ok, bytes memory result) = target.call{ value: value }(data);
|
|
137
|
+
if (!ok) revert ExternalCallFailed(result);
|
|
138
|
+
|
|
139
|
+
uint256 balanceAfter = address(this).balance;
|
|
140
|
+
if (balanceAfter < minBalanceAfter) revert MinBalanceNotMet(balanceAfter, minBalanceAfter);
|
|
141
|
+
|
|
142
|
+
emit ExecutionSubmitted(msg.sender, target, value, keccak256(data), balanceAfter);
|
|
143
|
+
return result;
|
|
144
|
+
}
|
|
145
|
+
|
|
146
|
+
function executeBatch(
|
|
147
|
+
address[] calldata targets,
|
|
148
|
+
uint256[] calldata values,
|
|
149
|
+
bytes[] calldata payloads,
|
|
150
|
+
uint256 minBalanceAfter
|
|
151
|
+
) external payable onlyEngineOperator whenNotPaused nonReentrant returns (bytes[] memory returnData) {
|
|
152
|
+
if (targets.length != values.length || targets.length != payloads.length) revert InvalidArrayLength();
|
|
153
|
+
|
|
154
|
+
returnData = new bytes[](targets.length);
|
|
155
|
+
|
|
156
|
+
for (uint256 i = 0; i < targets.length; i++) {
|
|
157
|
+
address target = targets[i];
|
|
158
|
+
ensureApprovedTarget(target);
|
|
159
|
+
ensureApprovedPayload(target, payloads[i]);
|
|
160
|
+
|
|
161
|
+
(bool ok, bytes memory result) = target.call{ value: values[i] }(payloads[i]);
|
|
162
|
+
if (!ok) revert ExternalCallFailed(result);
|
|
163
|
+
|
|
164
|
+
returnData[i] = result;
|
|
165
|
+
emit ExecutionSubmitted(msg.sender, target, values[i], keccak256(payloads[i]), address(this).balance);
|
|
166
|
+
}
|
|
167
|
+
|
|
168
|
+
uint256 balanceAfter = address(this).balance;
|
|
169
|
+
if (balanceAfter < minBalanceAfter) revert MinBalanceNotMet(balanceAfter, minBalanceAfter);
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
function withdrawToEngine(uint256 amount) external onlyEngineOperator nonReentrant {
|
|
173
|
+
(bool ok, ) = engineWallet.call{ value: amount }("");
|
|
174
|
+
if (!ok) revert EthTransferFailed();
|
|
175
|
+
|
|
176
|
+
emit WithdrawnToEngine(amount);
|
|
177
|
+
}
|
|
178
|
+
}
|
|
@@ -0,0 +1,111 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.24;
|
|
3
|
+
|
|
4
|
+
/// @title BandStrategy
|
|
5
|
+
/// @notice ETH strategy contract. Users can fund the contract, withdraw available funds, or allocate available funds to the configured strategy wallet or executor.
|
|
6
|
+
contract BandStrategy {
|
|
7
|
+
address public immutable owner;
|
|
8
|
+
address payable public immutable strategyWallet;
|
|
9
|
+
bool public depositsPaused;
|
|
10
|
+
uint256 public totalDeposits;
|
|
11
|
+
uint256 public totalAllocatedToStrategy;
|
|
12
|
+
|
|
13
|
+
mapping(address user => uint256 balance) public balances;
|
|
14
|
+
mapping(address user => bool enabled) public strategyActive;
|
|
15
|
+
mapping(address user => uint256 amount) public allocatedToStrategy;
|
|
16
|
+
|
|
17
|
+
uint256 private locked = 1;
|
|
18
|
+
|
|
19
|
+
event Deposited(address indexed user, uint256 amount);
|
|
20
|
+
event Withdrawn(address indexed user, uint256 amount);
|
|
21
|
+
event StrategyEngineActivated(address indexed user, uint256 amount);
|
|
22
|
+
event StrategyEngineDeactivated(address indexed user);
|
|
23
|
+
event DepositsPausedSet(bool paused);
|
|
24
|
+
|
|
25
|
+
error ZeroAmount();
|
|
26
|
+
error DepositsPaused();
|
|
27
|
+
error InsufficientBalance();
|
|
28
|
+
error EthTransferFailed();
|
|
29
|
+
error NotOwner();
|
|
30
|
+
error NoStrategyContractBalance();
|
|
31
|
+
error ReentrantCall();
|
|
32
|
+
error StrategyAlreadyActive();
|
|
33
|
+
error ZeroAddress();
|
|
34
|
+
|
|
35
|
+
modifier onlyOwner() {
|
|
36
|
+
if (msg.sender != owner) revert NotOwner();
|
|
37
|
+
_;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
modifier nonReentrant() {
|
|
41
|
+
if (locked != 1) revert ReentrantCall();
|
|
42
|
+
locked = 2;
|
|
43
|
+
_;
|
|
44
|
+
locked = 1;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
constructor(address payable strategyWallet_) {
|
|
48
|
+
if (strategyWallet_ == address(0)) revert ZeroAddress();
|
|
49
|
+
owner = msg.sender;
|
|
50
|
+
strategyWallet = strategyWallet_;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
receive() external payable {
|
|
54
|
+
deposit();
|
|
55
|
+
}
|
|
56
|
+
|
|
57
|
+
function deposit() public payable {
|
|
58
|
+
if (depositsPaused) revert DepositsPaused();
|
|
59
|
+
if (msg.value == 0) revert ZeroAmount();
|
|
60
|
+
|
|
61
|
+
balances[msg.sender] += msg.value;
|
|
62
|
+
totalDeposits += msg.value;
|
|
63
|
+
|
|
64
|
+
emit Deposited(msg.sender, msg.value);
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
function withdraw(uint256 amount) public nonReentrant {
|
|
68
|
+
if (amount == 0) revert ZeroAmount();
|
|
69
|
+
if (balances[msg.sender] < amount) revert InsufficientBalance();
|
|
70
|
+
|
|
71
|
+
strategyActive[msg.sender] = false;
|
|
72
|
+
balances[msg.sender] -= amount;
|
|
73
|
+
totalDeposits -= amount;
|
|
74
|
+
|
|
75
|
+
(bool ok, ) = payable(msg.sender).call{value: amount}("");
|
|
76
|
+
if (!ok) revert EthTransferFailed();
|
|
77
|
+
|
|
78
|
+
emit Withdrawn(msg.sender, amount);
|
|
79
|
+
}
|
|
80
|
+
|
|
81
|
+
function withdrawAll() external {
|
|
82
|
+
withdraw(balances[msg.sender]);
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
function activateStrategyEngine() public nonReentrant {
|
|
86
|
+
uint256 amount = balances[msg.sender];
|
|
87
|
+
if (amount == 0) revert NoStrategyContractBalance();
|
|
88
|
+
if (strategyActive[msg.sender]) revert StrategyAlreadyActive();
|
|
89
|
+
|
|
90
|
+
balances[msg.sender] = 0;
|
|
91
|
+
totalDeposits -= amount;
|
|
92
|
+
strategyActive[msg.sender] = true;
|
|
93
|
+
allocatedToStrategy[msg.sender] += amount;
|
|
94
|
+
totalAllocatedToStrategy += amount;
|
|
95
|
+
|
|
96
|
+
(bool ok, ) = strategyWallet.call{value: amount}("");
|
|
97
|
+
if (!ok) revert EthTransferFailed();
|
|
98
|
+
|
|
99
|
+
emit StrategyEngineActivated(msg.sender, amount);
|
|
100
|
+
}
|
|
101
|
+
|
|
102
|
+
function deactivateStrategyEngine() public {
|
|
103
|
+
strategyActive[msg.sender] = false;
|
|
104
|
+
emit StrategyEngineDeactivated(msg.sender);
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
function setDepositsPaused(bool paused) external onlyOwner {
|
|
108
|
+
depositsPaused = paused;
|
|
109
|
+
emit DepositsPausedSet(paused);
|
|
110
|
+
}
|
|
111
|
+
}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.24;
|
|
3
|
+
|
|
4
|
+
contract MockDexTarget {
|
|
5
|
+
event Swapped(address indexed sender, uint256 value, uint256 profit);
|
|
6
|
+
|
|
7
|
+
receive() external payable {}
|
|
8
|
+
|
|
9
|
+
function swapWithProfit(uint256 profit) external payable {
|
|
10
|
+
emit Swapped(msg.sender, msg.value, profit);
|
|
11
|
+
|
|
12
|
+
if (profit > 0) {
|
|
13
|
+
(bool ok, ) = msg.sender.call{ value: msg.value + profit }("");
|
|
14
|
+
require(ok, "profit transfer failed");
|
|
15
|
+
}
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
function alwaysRevert() external pure {
|
|
19
|
+
revert("mock revert");
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function pullToken(address token, uint256 amount) external {
|
|
23
|
+
(bool ok, bytes memory result) = token.call(
|
|
24
|
+
abi.encodeWithSignature("transferFrom(address,address,uint256)", msg.sender, address(this), amount)
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
require(ok && (result.length == 0 || abi.decode(result, (bool))), "token pull failed");
|
|
28
|
+
}
|
|
29
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
// SPDX-License-Identifier: MIT
|
|
2
|
+
pragma solidity ^0.8.24;
|
|
3
|
+
|
|
4
|
+
contract MockErc20 {
|
|
5
|
+
string public name = "Mock Token";
|
|
6
|
+
string public symbol = "MOCK";
|
|
7
|
+
uint8 public decimals = 18;
|
|
8
|
+
uint256 public totalSupply;
|
|
9
|
+
|
|
10
|
+
mapping(address account => uint256 balance) public balanceOf;
|
|
11
|
+
mapping(address owner => mapping(address spender => uint256 amount)) public allowance;
|
|
12
|
+
|
|
13
|
+
event Approval(address indexed owner, address indexed spender, uint256 amount);
|
|
14
|
+
event Transfer(address indexed from, address indexed to, uint256 amount);
|
|
15
|
+
|
|
16
|
+
function mint(address to, uint256 amount) external {
|
|
17
|
+
totalSupply += amount;
|
|
18
|
+
balanceOf[to] += amount;
|
|
19
|
+
emit Transfer(address(0), to, amount);
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
function approve(address spender, uint256 amount) external returns (bool) {
|
|
23
|
+
allowance[msg.sender][spender] = amount;
|
|
24
|
+
emit Approval(msg.sender, spender, amount);
|
|
25
|
+
return true;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
function transferFrom(address from, address to, uint256 amount) external returns (bool) {
|
|
29
|
+
uint256 allowed = allowance[from][msg.sender];
|
|
30
|
+
require(allowed >= amount, "allowance");
|
|
31
|
+
require(balanceOf[from] >= amount, "balance");
|
|
32
|
+
|
|
33
|
+
allowance[from][msg.sender] = allowed - amount;
|
|
34
|
+
balanceOf[from] -= amount;
|
|
35
|
+
balanceOf[to] += amount;
|
|
36
|
+
|
|
37
|
+
emit Transfer(from, to, amount);
|
|
38
|
+
return true;
|
|
39
|
+
}
|
|
40
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type { Address } from "viem";
|
|
2
|
+
import { type StrategyContractAction } from "./useStrategyContract.js";
|
|
3
|
+
export type BandContractPanelProps = {
|
|
4
|
+
strategyContractAddress?: Address;
|
|
5
|
+
chainId?: number;
|
|
6
|
+
title?: string;
|
|
7
|
+
className?: string;
|
|
8
|
+
onSubmitted?: (hash: string, action: StrategyContractAction) => void;
|
|
9
|
+
};
|
|
10
|
+
export declare function BandContractPanel({ strategyContractAddress, chainId, title, className, onSubmitted }: BandContractPanelProps): import("react/jsx-runtime").JSX.Element;
|
|
11
|
+
//# sourceMappingURL=BandContractPanel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BandContractPanel.d.ts","sourceRoot":"","sources":["../src/BandContractPanel.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAEpC,OAAO,EAAuB,KAAK,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAE5F,MAAM,MAAM,sBAAsB,GAAG;IACnC,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,sBAAsB,KAAK,IAAI,CAAC;CACtE,CAAC;AAoBF,wBAAgB,iBAAiB,CAAC,EAChC,uBAAuB,EACvB,OAAoB,EACpB,KAA2B,EAC3B,SAAS,EACT,WAAW,EACZ,EAAE,sBAAsB,2CAyJxB"}
|
|
@@ -0,0 +1,95 @@
|
|
|
1
|
+
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
+
import { useMemo, useState } from "react";
|
|
3
|
+
import { mainnet } from "wagmi/chains";
|
|
4
|
+
import { useStrategyContract } from "./useStrategyContract.js";
|
|
5
|
+
const buttonStyle = {
|
|
6
|
+
border: "1px solid #3b82f6",
|
|
7
|
+
borderRadius: 6,
|
|
8
|
+
background: "#2563eb",
|
|
9
|
+
color: "#ffffff",
|
|
10
|
+
cursor: "pointer",
|
|
11
|
+
fontWeight: 700,
|
|
12
|
+
minHeight: 42,
|
|
13
|
+
padding: "0 14px"
|
|
14
|
+
};
|
|
15
|
+
const secondaryButtonStyle = {
|
|
16
|
+
...buttonStyle,
|
|
17
|
+
background: "#111827",
|
|
18
|
+
border: "1px solid #334155",
|
|
19
|
+
color: "#e5e7eb"
|
|
20
|
+
};
|
|
21
|
+
export function BandContractPanel({ strategyContractAddress, chainId = mainnet.id, title = "Strategy Contract", className, onSubmitted }) {
|
|
22
|
+
const [amount, setAmount] = useState("");
|
|
23
|
+
const [mode, setMode] = useState("deposit");
|
|
24
|
+
const [localError, setLocalError] = useState();
|
|
25
|
+
const strategyContract = useStrategyContract({ strategyContractAddress, chainId });
|
|
26
|
+
const status = useMemo(() => {
|
|
27
|
+
if (!strategyContractAddress)
|
|
28
|
+
return "Strategy contract address missing";
|
|
29
|
+
if (!strategyContract.isConnected)
|
|
30
|
+
return "Connect wallet";
|
|
31
|
+
if (!strategyContract.isCorrectChain)
|
|
32
|
+
return "Switch to Ethereum mainnet";
|
|
33
|
+
if (strategyContract.depositsPaused && mode === "deposit")
|
|
34
|
+
return "Deposits paused";
|
|
35
|
+
if (strategyContract.transactionStatus !== "idle")
|
|
36
|
+
return strategyContract.transactionStatusText;
|
|
37
|
+
return "Ready";
|
|
38
|
+
}, [
|
|
39
|
+
mode,
|
|
40
|
+
strategyContract.depositsPaused,
|
|
41
|
+
strategyContract.isConnected,
|
|
42
|
+
strategyContract.isCorrectChain,
|
|
43
|
+
strategyContract.transactionStatus,
|
|
44
|
+
strategyContract.transactionStatusText,
|
|
45
|
+
strategyContractAddress
|
|
46
|
+
]);
|
|
47
|
+
const isBusy = strategyContract.isWritePending || strategyContract.isConfirming;
|
|
48
|
+
const canSubmit = Boolean(strategyContractAddress) &&
|
|
49
|
+
strategyContract.isConnected &&
|
|
50
|
+
!isBusy &&
|
|
51
|
+
(mode === "withdraw" || !strategyContract.depositsPaused);
|
|
52
|
+
async function submit(event) {
|
|
53
|
+
event.preventDefault();
|
|
54
|
+
setLocalError(undefined);
|
|
55
|
+
try {
|
|
56
|
+
const hash = mode === "deposit" ? await strategyContract.depositEth(amount) : await strategyContract.withdrawEth(amount);
|
|
57
|
+
setAmount("");
|
|
58
|
+
onSubmitted?.(hash, mode);
|
|
59
|
+
}
|
|
60
|
+
catch (error) {
|
|
61
|
+
setLocalError(error instanceof Error ? error.message : String(error));
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
async function withdrawAll() {
|
|
65
|
+
setLocalError(undefined);
|
|
66
|
+
try {
|
|
67
|
+
const hash = await strategyContract.withdrawAll();
|
|
68
|
+
setAmount("");
|
|
69
|
+
onSubmitted?.(hash, "withdrawAll");
|
|
70
|
+
}
|
|
71
|
+
catch (error) {
|
|
72
|
+
setLocalError(error instanceof Error ? error.message : String(error));
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
return (_jsxs("section", { className: className, style: {
|
|
76
|
+
background: "#020617",
|
|
77
|
+
border: "1px solid #1e293b",
|
|
78
|
+
borderRadius: 8,
|
|
79
|
+
boxShadow: "0 18px 60px rgba(2, 6, 23, 0.35)",
|
|
80
|
+
color: "#e5e7eb",
|
|
81
|
+
display: "grid",
|
|
82
|
+
gap: 16,
|
|
83
|
+
maxWidth: 460,
|
|
84
|
+
padding: 18
|
|
85
|
+
}, children: [_jsxs("header", { style: { display: "grid", gap: 6 }, children: [_jsx("h2", { style: { fontSize: 18, lineHeight: 1.2, margin: 0 }, children: title }), _jsxs("div", { style: { color: "#94a3b8", fontSize: 14 }, children: ["Status: ", status] })] }), _jsxs("div", { style: { display: "grid", gap: 8 }, children: [_jsxs("div", { style: { display: "flex", justifyContent: "space-between", gap: 12 }, children: [_jsx("span", { children: "Your contract balance" }), _jsxs("strong", { children: [strategyContract.balanceEth, " ETH"] })] }), _jsxs("div", { style: { display: "flex", justifyContent: "space-between", gap: 12 }, children: [_jsx("span", { children: "Total contract deposits" }), _jsxs("strong", { children: [strategyContract.totalDepositsEth, " ETH"] })] })] }), _jsxs("div", { style: { display: "grid", gridTemplateColumns: "1fr 1fr", gap: 8 }, children: [_jsx("button", { type: "button", onClick: () => setMode("deposit"), style: mode === "deposit" ? buttonStyle : secondaryButtonStyle, children: "Deposit" }), _jsx("button", { type: "button", onClick: () => setMode("withdraw"), style: mode === "withdraw" ? buttonStyle : secondaryButtonStyle, children: "Withdraw" })] }), _jsxs("form", { onSubmit: submit, style: { display: "grid", gap: 10 }, children: [_jsxs("label", { style: { display: "grid", gap: 6, fontSize: 14, fontWeight: 700 }, children: ["Amount ETH", _jsx("input", { inputMode: "decimal", min: "0", onChange: (event) => setAmount(event.target.value), placeholder: "0.01", step: "any", style: {
|
|
86
|
+
background: "#0f172a",
|
|
87
|
+
border: "1px solid #334155",
|
|
88
|
+
borderRadius: 6,
|
|
89
|
+
color: "#e5e7eb",
|
|
90
|
+
font: "inherit",
|
|
91
|
+
minHeight: 42,
|
|
92
|
+
padding: "0 12px"
|
|
93
|
+
}, type: "number", value: amount })] }), _jsx("button", { disabled: !canSubmit, style: { ...buttonStyle, opacity: canSubmit ? 1 : 0.5 }, type: "submit", children: mode === "deposit" ? "Deposit ETH" : "Withdraw ETH" }), mode === "withdraw" ? (_jsx("button", { disabled: !canSubmit || strategyContract.balanceWei === 0n, onClick: withdrawAll, style: secondaryButtonStyle, type: "button", children: "Withdraw All" })) : null] }), strategyContract.pendingHash ? (_jsx("a", { href: `https://etherscan.io/tx/${strategyContract.pendingHash}`, rel: "noreferrer", style: { color: "#60a5fa", fontSize: 14, overflowWrap: "anywhere" }, target: "_blank", children: "View transaction" })) : null, localError || strategyContract.error ? (_jsx("div", { style: { color: "#fca5a5", fontSize: 14 }, children: localError ?? strategyContract.error?.message })) : null] }));
|
|
94
|
+
}
|
|
95
|
+
//# sourceMappingURL=BandContractPanel.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BandContractPanel.js","sourceRoot":"","sources":["../src/BandContractPanel.tsx"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
import type { Address } from "viem";
|
|
2
|
+
import type { StrategyContractAction } from "./useStrategyContract.js";
|
|
3
|
+
export type BandPanelProps = {
|
|
4
|
+
strategyContractAddress?: Address;
|
|
5
|
+
strategyWalletAddress?: Address;
|
|
6
|
+
chainId?: number;
|
|
7
|
+
className?: string;
|
|
8
|
+
title?: string;
|
|
9
|
+
onSubmitted?: (hash: string, action: StrategyContractAction) => void;
|
|
10
|
+
onStrategyContractDeployed?: (address: Address) => void;
|
|
11
|
+
};
|
|
12
|
+
export declare function BandPanel({ strategyContractAddress, strategyWalletAddress, chainId, className, title, onSubmitted, onStrategyContractDeployed }: BandPanelProps): import("react/jsx-runtime").JSX.Element;
|
|
13
|
+
//# sourceMappingURL=BandPanel.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"BandPanel.d.ts","sourceRoot":"","sources":["../src/BandPanel.tsx"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,OAAO,EAAE,MAAM,MAAM,CAAC;AAGpC,OAAO,KAAK,EAAE,sBAAsB,EAAE,MAAM,0BAA0B,CAAC;AAEvE,MAAM,MAAM,cAAc,GAAG;IAC3B,uBAAuB,CAAC,EAAE,OAAO,CAAC;IAClC,qBAAqB,CAAC,EAAE,OAAO,CAAC;IAChC,OAAO,CAAC,EAAE,MAAM,CAAC;IACjB,SAAS,CAAC,EAAE,MAAM,CAAC;IACnB,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,WAAW,CAAC,EAAE,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,sBAAsB,KAAK,IAAI,CAAC;IACrE,0BAA0B,CAAC,EAAE,CAAC,OAAO,EAAE,OAAO,KAAK,IAAI,CAAC;CACzD,CAAC;AAiCF,wBAAgB,SAAS,CAAC,EACxB,uBAAuB,EACvB,qBAAqB,EACrB,OAAoB,EACpB,SAAS,EACT,KAAwB,EACxB,WAAW,EACX,0BAA0B,EAC3B,EAAE,cAAc,2CAsPhB"}
|